diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index f829cc0dcfcf..d417838b543f 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -271,6 +271,22 @@ pub unsafe fn vceqzq_f64(a: float64x2_t) -> uint64x2_t { simd_eq(a, transmute(b)) } +/// Floating-point absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fabs))] +pub unsafe fn vabs_f64(a: float64x1_t) -> float64x1_t { + simd_fabs(a) +} + +/// Floating-point absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(test, assert_instr(fabs))] +pub unsafe fn vabsq_f64(a: float64x2_t) -> float64x2_t { + simd_fabs(a) +} + /// Compare signed greater than #[inline] #[target_feature(enable = "neon")] @@ -838,6 +854,22 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vabs_f64() { + let a: f64 = -0.1; + let e: f64 = 0.1; + let r: f64 = transmute(vabs_f64(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabsq_f64() { + let a: f64x2 = f64x2::new(-0.1, -2.2); + let e: f64x2 = f64x2::new(0.1, 2.2); + let r: f64x2 = transmute(vabsq_f64(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vcgt_s64() { let a: i64x1 = i64x1::new(1); diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index 85c5ac77ba3e..3d83a9a9999e 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -72,10 +72,6 @@ extern "C" { fn vabs_s64_(a: int64x1_t) -> int64x1_t; #[link_name = "llvm.aarch64.neon.abs.v2i64"] fn vabsq_s64_(a: int64x2_t) -> int64x2_t; - #[link_name = "llvm.fabs.v1f64"] - fn vabs_f64_(a: float64x1_t) -> float64x1_t; - #[link_name = "llvm.fabs.v2f64"] - fn vabsq_f64_(a: float64x2_t) -> float64x2_t; #[link_name = "llvm.aarch64.neon.suqadd.v8i8"] fn vuqadd_s8_(a: int8x8_t, b: uint8x8_t) -> int8x8_t; @@ -708,21 +704,6 @@ pub unsafe fn vabsq_s64(a: int64x2_t) -> int64x2_t { vabsq_s64_(a) } -/// Floating-point absolute value. -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fabs))] -pub unsafe fn vabs_f64(a: float64x1_t) -> float64x1_t { - vabs_f64_(a) -} -/// Floating-point absolute value. -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(test, assert_instr(fabs))] -pub unsafe fn vabsq_f64(a: float64x2_t) -> float64x2_t { - vabsq_f64_(a) -} - /// Signed saturating Accumulate of Unsigned value. #[inline] #[target_feature(enable = "neon")] @@ -3932,20 +3913,6 @@ mod tests { let e = i64x2::new(i64::MIN, i64::MAX); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vabs_f64() { - let a = f64x1::new(f64::MIN); - let r: f64x1 = transmute(vabs_f64(transmute(a))); - let e = f64x1::new(f64::MAX); - assert_eq!(r, e); - } - #[simd_test(enable = "neon")] - unsafe fn test_vabsq_f64() { - let a = f64x2::new(f64::MIN, -4.2); - let r: f64x2 = transmute(vabsq_f64(transmute(a))); - let e = f64x2::new(f64::MAX, 4.2); - assert_eq!(r, e); - } #[simd_test(enable = "neon")] unsafe fn test_vaddv_s16() { diff --git a/library/stdarch/crates/core_arch/src/arm/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm/neon/generated.rs index da8fcefcf6f4..5373e343d0c8 100644 --- a/library/stdarch/crates/core_arch/src/arm/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm/neon/generated.rs @@ -629,6 +629,26 @@ pub unsafe fn vceqq_f32(a: float32x4_t, b: float32x4_t) -> uint32x4_t { simd_eq(a, b) } +/// Floating-point absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))] +pub unsafe fn vabs_f32(a: float32x2_t) -> float32x2_t { + simd_fabs(a) +} + +/// Floating-point absolute value +#[inline] +#[target_feature(enable = "neon")] +#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] +#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))] +pub unsafe fn vabsq_f32(a: float32x4_t) -> float32x4_t { + simd_fabs(a) +} + /// Compare signed greater than #[inline] #[target_feature(enable = "neon")] @@ -3651,6 +3671,22 @@ mod test { assert_eq!(r, e); } + #[simd_test(enable = "neon")] + unsafe fn test_vabs_f32() { + let a: f32x2 = f32x2::new(-0.1, -2.2); + let e: f32x2 = f32x2::new(0.1, 2.2); + let r: f32x2 = transmute(vabs_f32(transmute(a))); + assert_eq!(r, e); + } + + #[simd_test(enable = "neon")] + unsafe fn test_vabsq_f32() { + let a: f32x4 = f32x4::new(-0.1, -2.2, -3.3, -6.6); + let e: f32x4 = f32x4::new(0.1, 2.2, 3.3, 6.6); + let r: f32x4 = transmute(vabsq_f32(transmute(a))); + assert_eq!(r, e); + } + #[simd_test(enable = "neon")] unsafe fn test_vcgt_s8() { let a: i8x8 = i8x8::new(1, 2, 3, 4, 5, 6, 7, 8); diff --git a/library/stdarch/crates/core_arch/src/arm/neon/mod.rs b/library/stdarch/crates/core_arch/src/arm/neon/mod.rs index e5e64548779e..6b8b0e4a5fa7 100644 --- a/library/stdarch/crates/core_arch/src/arm/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/arm/neon/mod.rs @@ -125,9 +125,6 @@ extern "C" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v2i32")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v2i32")] fn vabs_s32_(a: int32x2_t) -> int32x2_t; - #[cfg_attr(target_arch = "arm", link_name = "llvm.fabs.v2f32")] - #[cfg_attr(target_arch = "aarch64", link_name = "llvm.fabs.v2f32")] - fn vabs_f32_(a: float32x2_t) -> float32x2_t; // absolute value (128-bit) #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vabs.v16i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.abs.v16i8")] @@ -1153,24 +1150,6 @@ pub unsafe fn vabsq_s16(a: int16x8_t) -> int16x8_t { pub unsafe fn vabsq_s32(a: int32x4_t) -> int32x4_t { vabsq_s32_(a) } -/// Floating-point absolute value. -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))] -pub unsafe fn vabs_f32(a: float32x2_t) -> float32x2_t { - vabs_f32_(a) -} -/// Floating-point absolute value. -#[inline] -#[target_feature(enable = "neon")] -#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vabs))] -#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(fabs))] -pub unsafe fn vabsq_f32(a: float32x4_t) -> float32x4_t { - vabsq_f32_(a) -} /// Add pairwise. #[inline] @@ -8588,20 +8567,7 @@ mod tests { let e = i32x4::new(i32::MIN, i32::MAX, 0, 1); assert_eq!(r, e); } - #[simd_test(enable = "neon")] - unsafe fn test_vabs_f32() { - let a = f32x2::new(f32::MIN, -1.0); - let r: f32x2 = transmute(vabs_f32(transmute(a))); - let e = f32x2::new(f32::MAX, 1.0); - assert_eq!(r, e); - } - #[simd_test(enable = "neon")] - unsafe fn test_vabsq_f32() { - let a = f32x4::new(f32::MIN, -1.32, -4.3, -6.8); - let r: f32x4 = transmute(vabsq_f32(transmute(a))); - let e = f32x4::new(f32::MAX, 1.32, 4.3, 6.8); - assert_eq!(r, e); - } + #[simd_test(enable = "neon")] unsafe fn test_vpadd_s16() { let a = i16x4::new(1, 2, 3, 4); diff --git a/library/stdarch/crates/stdarch-gen/neon.spec b/library/stdarch/crates/stdarch-gen/neon.spec index 6c2234b1275f..0c6c80ee4737 100644 --- a/library/stdarch/crates/stdarch-gen/neon.spec +++ b/library/stdarch/crates/stdarch-gen/neon.spec @@ -53,12 +53,12 @@ // FALSE - 'false' all bits are set to 0 // FF - same as 'true' // MIN - minimal value (either 0 or the lowest negative number) -// MAX - maximal value propr to overflow +// MAX - maximal value proper to overflow // // # validate // Validates a and b aginst the expected result of the test. // The special values 'TRUE' and 'FALSE' can be used to -// represent the corect NEON representation of true or +// represent the correct NEON representation of true or // false values. It too gets scaled to the type. // // Validate needs to be called before generate as it sets @@ -166,6 +166,29 @@ validate TRUE, FALSE, FALSE, FALSE aarch64 = fcmeq generate float32x2_t:uint32x2_t, float32x4_t:uint32x4_t, float64x1_t:uint64x1_t, float64x2_t:uint64x2_t +//////////////////// +// Floating-point absolute value +//////////////////// + +/// Floating-point absolute value +name = vabs +fn = simd_fabs +a = -0.1, -2.2, -3.3, -6.6 +validate 0.1, 2.2, 3.3, 6.6 + +arm = vabs +aarch64 = fabs +generate float32x2_t:float32x2_t, float32x4_t:float32x4_t + +/// Floating-point absolute value +name = vabs +fn = simd_fabs +a = -0.1, -2.2, -3.3, -6.6 +validate 0.1, 2.2, 3.3, 6.6 + +aarch64 = fabs +generate float64x1_t:float64x1_t, float64x2_t:float64x2_t + //////////////////// // greater then //////////////////// diff --git a/library/stdarch/crates/stdarch-gen/src/main.rs b/library/stdarch/crates/stdarch-gen/src/main.rs index 47164a7c8b82..caa4b5c8b92a 100644 --- a/library/stdarch/crates/stdarch-gen/src/main.rs +++ b/library/stdarch/crates/stdarch-gen/src/main.rs @@ -299,7 +299,7 @@ fn gen_aarch64( in_t: &str, out_t: &str, current_tests: &[(Vec, Vec, Vec)], - single_para: bool, + para_num: i32, fixed: &Vec, ) -> (String, String) { let _global_t = type_to_global_type(in_t); @@ -335,27 +335,36 @@ fn gen_aarch64( } else { String::new() }; - let call = if !single_para { + let call = if para_num == 2 { format!( r#"pub unsafe fn {}(a: {}, b: {}) -> {} {{ {}{}(a, b) }}"#, name, in_t, in_t, out_t, ext_c, current_fn, ) - } else if fixed.len() != 0 { - let fixed: Vec = fixed.iter().take(type_len(in_t)).cloned().collect(); - format!( - r#"pub unsafe fn {}(a: {}) -> {} {{ + } else if para_num == 1 { + if fixed.len() != 0 { + let fixed: Vec = fixed.iter().take(type_len(in_t)).cloned().collect(); + format!( + r#"pub unsafe fn {}(a: {}) -> {} {{ let b{}; {}{}(a, transmute(b)) }}"#, - name, - in_t, - out_t, - values(in_t, &fixed), - ext_c, - current_fn, - ) + name, + in_t, + out_t, + values(in_t, &fixed), + ext_c, + current_fn, + ) + } else { + format!( + r#"pub unsafe fn {}(a: {}) -> {} {{ + {}{}(a) +}}"#, + name, in_t, out_t, ext_c, current_fn, + ) + } } else { String::new() }; @@ -370,14 +379,7 @@ fn gen_aarch64( current_comment, current_aarch64, call ); - let test = gen_test( - name, - &in_t, - &out_t, - current_tests, - type_len(in_t), - single_para, - ); + let test = gen_test(name, &in_t, &out_t, current_tests, type_len(in_t), para_num); (function, test) } @@ -387,7 +389,7 @@ fn gen_test( out_t: &str, current_tests: &[(Vec, Vec, Vec)], len: usize, - single_para: bool, + para_num: i32, ) -> String { let mut test = format!( r#" @@ -399,35 +401,44 @@ fn gen_test( let a: Vec = a.iter().take(len).cloned().collect(); let b: Vec = b.iter().take(len).cloned().collect(); let e: Vec = e.iter().take(len).cloned().collect(); - let t = if !single_para { - format!( - r#" + let t = { + match para_num { + 1 => { + format!( + r#" + let a{}; + let e{}; + let r: {} = transmute({}(transmute(a))); + assert_eq!(r, e); +"#, + values(in_t, &a), + values(out_t, &e), + type_to_global_type(out_t), + name + ) + } + 2 => { + format!( + r#" let a{}; let b{}; let e{}; let r: {} = transmute({}(transmute(a), transmute(b))); assert_eq!(r, e); "#, - values(in_t, &a), - values(in_t, &b), - values(out_t, &e), - type_to_global_type(out_t), - name - ) - } else { - format!( - r#" - let a{}; - let e{}; - let r: {} = transmute({}(transmute(a))); - assert_eq!(r, e); -"#, - values(in_t, &a), - values(out_t, &e), - type_to_global_type(out_t), - name - ) + values(in_t, &a), + values(in_t, &b), + values(out_t, &e), + type_to_global_type(out_t), + name + ) + } + _ => { + panic!("no support para_num:{}", para_num.to_string()) + } + } }; + test.push_str(&t); } test.push_str(" }\n"); @@ -446,7 +457,7 @@ fn gen_arm( in_t: &str, out_t: &str, current_tests: &[(Vec, Vec, Vec)], - single_para: bool, + para_num: i32, fixed: &Vec, ) -> (String, String) { let _global_t = type_to_global_type(in_t); @@ -472,7 +483,6 @@ fn gen_arm( } format!("{}_", name) }; - let ext_c = if let (Some(link_arm), Some(link_aarch64)) = (link_arm.clone(), link_aarch64.clone()) { let ext = type_to_ext(in_t); @@ -495,27 +505,36 @@ fn gen_arm( } else { String::new() }; - let call = if !single_para { + let call = if para_num == 2 { format!( r#"pub unsafe fn {}(a: {}, b: {}) -> {} {{ {}{}(a, b) }}"#, name, in_t, in_t, out_t, ext_c, current_fn, ) - } else if fixed.len() != 0 { - let fixed: Vec = fixed.iter().take(type_len(in_t)).cloned().collect(); - format!( - r#"pub unsafe fn {}(a: {}) -> {} {{ + } else if para_num == 1 { + if fixed.len() != 0 { + let fixed: Vec = fixed.iter().take(type_len(in_t)).cloned().collect(); + format!( + r#"pub unsafe fn {}(a: {}) -> {} {{ let b{}; {}{}(a, transmute(b)) }}"#, - name, - in_t, - out_t, - values(in_t, &fixed), - ext_c, - current_fn, - ) + name, + in_t, + out_t, + values(in_t, &fixed), + ext_c, + current_fn, + ) + } else { + format!( + r#"pub unsafe fn {}(a: {}) -> {} {{ + {}{}(a) +}}"#, + name, in_t, out_t, ext_c, current_fn, + ) + } } else { String::new() }; @@ -534,14 +553,7 @@ fn gen_arm( expand_intrinsic(¤t_aarch64, in_t), call, ); - let test = gen_test( - name, - &in_t, - &out_t, - current_tests, - type_len(in_t), - single_para, - ); + let test = gen_test(name, &in_t, &out_t, current_tests, type_len(in_t), para_num); (function, test) } @@ -628,10 +640,10 @@ fn main() -> io::Result<()> { let mut current_aarch64: Option = None; let mut link_arm: Option = None; let mut link_aarch64: Option = None; + let mut para_num = 2; let mut a: Vec = Vec::new(); let mut b: Vec = Vec::new(); let mut fixed: Vec = Vec::new(); - let mut single_para: bool = true; let mut current_tests: Vec<(Vec, Vec, Vec)> = Vec::new(); // @@ -702,7 +714,10 @@ mod test { link_aarch64 = None; link_arm = None; current_tests = Vec::new(); - single_para = true; + para_num = 2; + a = vec![]; + b = vec![]; + fixed = vec![]; } else if line.starts_with("//") { } else if line.starts_with("name = ") { current_name = Some(String::from(&line[7..])); @@ -716,7 +731,6 @@ mod test { a = line[4..].split(',').map(|v| v.trim().to_string()).collect(); } else if line.starts_with("b = ") { b = line[4..].split(',').map(|v| v.trim().to_string()).collect(); - single_para = false; } else if line.starts_with("fixed = ") { fixed = line[8..].split(',').map(|v| v.trim().to_string()).collect(); } else if line.starts_with("validate ") { @@ -755,9 +769,11 @@ mod test { } else { panic!("Bad spec: {}", line) } + if b.len() == 0 { + para_num = 1; + } let current_name = current_name.clone().unwrap(); let name = format!("{}{}", current_name, type_to_suffix(in_t),); - if let Some(current_arm) = current_arm.clone() { let (function, test) = gen_arm( ¤t_comment, @@ -770,7 +786,7 @@ mod test { &in_t, &out_t, ¤t_tests, - single_para, + para_num, &fixed, ); out_arm.push_str(&function); @@ -785,7 +801,7 @@ mod test { &in_t, &out_t, ¤t_tests, - single_para, + para_num, &fixed, ); out_aarch64.push_str(&function);