Skip to content

Commit deec82c

Browse files
authored
[Neon] Absolute Value fns (#877)
1 parent 7a6a442 commit deec82c

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

crates/core_arch/src/aarch64/neon/mod.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,14 @@ pub struct poly8x16x4_t(
7171

7272
#[allow(improper_ctypes)]
7373
extern "C" {
74+
// absolute value
75+
#[link_name = "llvm.aarch64.neon.abs.i64"]
76+
fn vabsd_s64_(a: i64) -> i64;
77+
#[link_name = "llvm.aarch64.neon.abs.v1i64"]
78+
fn vabs_s64_(a: int64x1_t) -> int64x1_t;
79+
#[link_name = "llvm.aarch64.neon.abs.v2i64"]
80+
fn vabsq_s64_(a: int64x2_t) -> int64x2_t;
81+
7482
#[link_name = "llvm.aarch64.neon.pmull64"]
7583
fn vmull_p64_(a: i64, b: i64) -> int8x16_t;
7684

@@ -246,6 +254,28 @@ extern "C" {
246254
) -> int8x16_t;
247255
}
248256

257+
/// Absolute Value (wrapping).
258+
#[inline]
259+
#[target_feature(enable = "neon")]
260+
#[cfg_attr(test, assert_instr(abs))]
261+
pub unsafe fn vabsd_s64(a: i64) -> i64 {
262+
vabsd_s64_(a)
263+
}
264+
/// Absolute Value (wrapping).
265+
#[inline]
266+
#[target_feature(enable = "neon")]
267+
#[cfg_attr(test, assert_instr(abs))]
268+
pub unsafe fn vabs_s64(a: int64x1_t) -> int64x1_t {
269+
vabs_s64_(a)
270+
}
271+
/// Absolute Value (wrapping).
272+
#[inline]
273+
#[target_feature(enable = "neon")]
274+
#[cfg_attr(test, assert_instr(abs))]
275+
pub unsafe fn vabsq_s64(a: int64x2_t) -> int64x2_t {
276+
vabsq_s64_(a)
277+
}
278+
249279
/// Add pairwise
250280
#[inline]
251281
#[target_feature(enable = "neon")]
@@ -2503,6 +2533,33 @@ mod tests {
25032533
unsafe fn test_vsubq_f64() {
25042534
testq_ari_f64(|i, j| vsubq_f64(i, j), |a: f64, b: f64| -> f64 { a - b });
25052535
}
2536+
2537+
#[simd_test(enable = "neon")]
2538+
unsafe fn test_vabsd_s64() {
2539+
assert_eq!(vabsd_s64(-1), 1);
2540+
assert_eq!(vabsd_s64(0), 0);
2541+
assert_eq!(vabsd_s64(1), 1);
2542+
assert_eq!(vabsd_s64(i64::MIN), i64::MIN);
2543+
assert_eq!(vabsd_s64(i64::MIN + 1), i64::MAX);
2544+
}
2545+
#[simd_test(enable = "neon")]
2546+
unsafe fn test_vabs_s64() {
2547+
let a = i64x1::new(i64::MIN);
2548+
let r: i64x1 = transmute(vabs_s64(transmute(a)));
2549+
let e = i64x1::new(i64::MIN);
2550+
assert_eq!(r, e);
2551+
let a = i64x1::new(i64::MIN + 1);
2552+
let r: i64x1 = transmute(vabs_s64(transmute(a)));
2553+
let e = i64x1::new(i64::MAX);
2554+
assert_eq!(r, e);
2555+
}
2556+
#[simd_test(enable = "neon")]
2557+
unsafe fn test_vabsq_s64() {
2558+
let a = i64x2::new(i64::MIN, i64::MIN + 1);
2559+
let r: i64x2 = transmute(vabsq_s64(transmute(a)));
2560+
let e = i64x2::new(i64::MIN, i64::MAX);
2561+
assert_eq!(r, e);
2562+
}
25062563
}
25072564

25082565
#[cfg(test)]

crates/core_arch/src/arm/neon/mod.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,27 @@ pub struct poly8x8x4_t(pub poly8x8_t, pub poly8x8_t, pub poly8x8_t, pub poly8x8_
102102

103103
#[allow(improper_ctypes)]
104104
extern "C" {
105+
// absolute value (64-bit)
106+
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v8i8")]
107+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v8i8")]
108+
fn vabs_s8_(a: int8x8_t) -> int8x8_t;
109+
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v4i16")]
110+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v4i16")]
111+
fn vabs_s16_(a: int16x4_t) -> int16x4_t;
112+
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v2i32")]
113+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v2i32")]
114+
fn vabs_s32_(a: int32x2_t) -> int32x2_t;
115+
// absolute value (128-bit)
116+
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v16i8")]
117+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v16i8")]
118+
fn vabsq_s8_(a: int8x16_t) -> int8x16_t;
119+
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v8i16")]
120+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v8i16")]
121+
fn vabsq_s16_(a: int16x8_t) -> int16x8_t;
122+
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v4i32")]
123+
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v4i32")]
124+
fn vabsq_s32_(a: int32x4_t) -> int32x4_t;
125+
105126
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vrsqrte.v2f32")]
106127
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.frsqrte.v2f32")]
107128
fn frsqrte_v2f32(a: float32x2_t) -> float32x2_t;
@@ -185,6 +206,61 @@ extern "C" {
185206
) -> int8x8_t;
186207
}
187208

209+
/// Absolute value (wrapping).
210+
#[inline]
211+
#[target_feature(enable = "neon")]
212+
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
213+
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
214+
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))]
215+
pub unsafe fn vabs_s8(a: int8x8_t) -> int8x8_t {
216+
vabs_s8_(a)
217+
}
218+
/// Absolute value (wrapping).
219+
#[inline]
220+
#[target_feature(enable = "neon")]
221+
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
222+
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
223+
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))]
224+
pub unsafe fn vabs_s16(a: int16x4_t) -> int16x4_t {
225+
vabs_s16_(a)
226+
}
227+
/// Absolute value (wrapping).
228+
#[inline]
229+
#[target_feature(enable = "neon")]
230+
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
231+
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
232+
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))]
233+
pub unsafe fn vabs_s32(a: int32x2_t) -> int32x2_t {
234+
vabs_s32_(a)
235+
}
236+
/// Absolute value (wrapping).
237+
#[inline]
238+
#[target_feature(enable = "neon")]
239+
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
240+
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
241+
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))]
242+
pub unsafe fn vabsq_s8(a: int8x16_t) -> int8x16_t {
243+
vabsq_s8_(a)
244+
}
245+
/// Absolute value (wrapping).
246+
#[inline]
247+
#[target_feature(enable = "neon")]
248+
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
249+
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
250+
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))]
251+
pub unsafe fn vabsq_s16(a: int16x8_t) -> int16x8_t {
252+
vabsq_s16_(a)
253+
}
254+
/// Absolute value (wrapping).
255+
#[inline]
256+
#[target_feature(enable = "neon")]
257+
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
258+
#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))]
259+
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(abs))]
260+
pub unsafe fn vabsq_s32(a: int32x4_t) -> int32x4_t {
261+
vabsq_s32_(a)
262+
}
263+
188264
/// Unsigned saturating extract narrow.
189265
#[inline]
190266
#[target_feature(enable = "neon")]
@@ -3945,6 +4021,48 @@ mod tests {
39454021
let e = i8x16::new(-1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
39464022
assert_eq!(r, e)
39474023
}
4024+
#[simd_test(enable = "neon")]
4025+
unsafe fn test_vabs_s8() {
4026+
let a = i8x8::new(-1, 0, 1, -2, 0, 2, -128, 127);
4027+
let r: i8x8 = transmute(vabs_s8(transmute(a)));
4028+
let e = i8x8::new(1, 0, 1, 2, 0, 2, -128, 127);
4029+
assert_eq!(r, e);
4030+
}
4031+
#[simd_test(enable = "neon")]
4032+
unsafe fn test_vabsq_s8() {
4033+
let a = i8x16::new(-1, 0, 1, -2, 0, 2, -128, 127, -1, 0, 1, -2, 0, 2, -128, 127);
4034+
let r: i8x16 = transmute(vabsq_s8(transmute(a)));
4035+
let e = i8x16::new(1, 0, 1, 2, 0, 2, -128, 127, 1, 0, 1, 2, 0, 2, -128, 127);
4036+
assert_eq!(r, e);
4037+
}
4038+
#[simd_test(enable = "neon")]
4039+
unsafe fn test_vabs_s16() {
4040+
let a = i16x4::new(-1, 0, i16::MIN, i16::MAX);
4041+
let r: i16x4 = transmute(vabs_s16(transmute(a)));
4042+
let e = i16x4::new(1, 0, i16::MIN, i16::MAX);
4043+
assert_eq!(r, e);
4044+
}
4045+
#[simd_test(enable = "neon")]
4046+
unsafe fn test_vabsq_s16() {
4047+
let a = i16x8::new(-1, 0, i16::MIN, i16::MAX, -1, 0, i16::MIN, i16::MAX);
4048+
let r: i16x8 = transmute(vabsq_s16(transmute(a)));
4049+
let e = i16x8::new(1, 0, i16::MIN, i16::MAX, 1, 0, i16::MIN, i16::MAX);
4050+
assert_eq!(r, e);
4051+
}
4052+
#[simd_test(enable = "neon")]
4053+
unsafe fn test_vabs_s32() {
4054+
let a = i32x2::new(i32::MIN, i32::MIN + 1);
4055+
let r: i32x2 = transmute(vabs_s32(transmute(a)));
4056+
let e = i32x2::new(i32::MIN, i32::MAX);
4057+
assert_eq!(r, e);
4058+
}
4059+
#[simd_test(enable = "neon")]
4060+
unsafe fn test_vabsq_s32() {
4061+
let a = i32x4::new(i32::MIN, i32::MIN + 1, 0, -1);
4062+
let r: i32x4 = transmute(vabsq_s32(transmute(a)));
4063+
let e = i32x4::new(i32::MIN, i32::MAX, 0, 1);
4064+
assert_eq!(r, e);
4065+
}
39484066
}
39494067

39504068
#[cfg(test)]

0 commit comments

Comments
 (0)