From 003b8eadd7a476c51956fe447894532d6e21937e Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 14 Apr 2021 15:07:36 -0700 Subject: [PATCH] Add more SIMD math.h intrinsics LLVM supports many functions from math.h in its IR. Many of these have single-instruction variants on various platforms. So, let's add them so std::arch can use them. Yes, exact comparison is intentional: rounding must always return a valid integer-equal value, except for inf/NAN. --- .../src/intrinsics/simd.rs | 2 ++ compiler/rustc_codegen_llvm/src/intrinsic.rs | 8 ++++-- compiler/rustc_span/src/symbol.rs | 2 ++ compiler/rustc_typeck/src/check/intrinsic.rs | 8 +++--- src/test/ui/simd/simd-intrinsic-float-math.rs | 27 +++++++++++++------ 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index c7ce32b385e94..27fc2abedc7e9 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -277,5 +277,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( // simd_select // simd_rem // simd_neg + // simd_trunc + // simd_floor } } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index af366f93b919e..52fab2ea17d8d 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1057,8 +1057,10 @@ fn generic_simd_intrinsic( sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), - sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)), @@ -1083,8 +1085,10 @@ fn generic_simd_intrinsic( | sym::simd_fsin | sym::simd_fcos | sym::simd_fabs - | sym::simd_floor | sym::simd_ceil + | sym::simd_floor + | sym::simd_round + | sym::simd_trunc | sym::simd_fexp | sym::simd_fexp2 | sym::simd_flog10 diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ee1d206095e5d..1269a99634f8e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1101,6 +1101,7 @@ symbols! { simd_reduce_or, simd_reduce_xor, simd_rem, + simd_round, simd_saturating_add, simd_saturating_sub, simd_scatter, @@ -1109,6 +1110,7 @@ symbols! { simd_shl, simd_shr, simd_sub, + simd_trunc, simd_xor, since, sinf32, diff --git a/compiler/rustc_typeck/src/check/intrinsic.rs b/compiler/rustc_typeck/src/check/intrinsic.rs index 303a77507cf7b..5741b6824b5d7 100644 --- a/compiler/rustc_typeck/src/check/intrinsic.rs +++ b/compiler/rustc_typeck/src/check/intrinsic.rs @@ -407,8 +407,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_fpow | sym::simd_saturating_add | sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)), - sym::simd_neg => (1, vec![param(0)], param(0)), - sym::simd_fsqrt + sym::simd_neg + | sym::simd_fsqrt | sym::simd_fsin | sym::simd_fcos | sym::simd_fexp @@ -417,8 +417,10 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) | sym::simd_flog10 | sym::simd_flog | sym::simd_fabs + | sym::simd_ceil | sym::simd_floor - | sym::simd_ceil => (1, vec![param(0)], param(0)), + | sym::simd_round + | sym::simd_trunc => (1, vec![param(0)], param(0)), sym::simd_fpowi => (1, vec![param(0), tcx.types.i32], param(0)), sym::simd_fma => (1, vec![param(0), param(0), param(0)], param(0)), sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)), diff --git a/src/test/ui/simd/simd-intrinsic-float-math.rs b/src/test/ui/simd/simd-intrinsic-float-math.rs index 220a59535cae4..7a4f7466559ff 100644 --- a/src/test/ui/simd/simd-intrinsic-float-math.rs +++ b/src/test/ui/simd/simd-intrinsic-float-math.rs @@ -20,16 +20,20 @@ extern "platform-intrinsic" { fn simd_fabs(x: T) -> T; fn simd_fsin(x: T) -> T; fn simd_fcos(x: T) -> T; - fn simd_ceil(x: T) -> T; fn simd_fexp(x: T) -> T; fn simd_fexp2(x: T) -> T; - fn simd_floor(x: T) -> T; fn simd_fma(x: T, y: T, z: T) -> T; fn simd_flog(x: T) -> T; fn simd_flog10(x: T) -> T; fn simd_flog2(x: T) -> T; fn simd_fpow(x: T, y: T) -> T; fn simd_fpowi(x: T, y: i32) -> T; + + // rounding functions + fn simd_ceil(x: T) -> T; + fn simd_floor(x: T) -> T; + fn simd_round(x: T) -> T; + fn simd_trunc(x: T) -> T; } macro_rules! assert_approx_eq_f32 { @@ -64,18 +68,12 @@ fn main() { let r = simd_fcos(z); assert_approx_eq!(x, r); - let r = simd_ceil(h); - assert_approx_eq!(x, r); - let r = simd_fexp(z); assert_approx_eq!(x, r); let r = simd_fexp2(z); assert_approx_eq!(x, r); - let r = simd_floor(h); - assert_approx_eq!(z, r); - let r = simd_fma(x, h, h); assert_approx_eq!(x, r); @@ -99,5 +97,18 @@ fn main() { let r = simd_fsin(z); assert_approx_eq!(z, r); + + // rounding functions + let r = simd_floor(h); + assert_eq!(z, r); + + let r = simd_ceil(h); + assert_eq!(x, r); + + let r = simd_round(h); + assert_eq!(x, r); + + let r = simd_trunc(h); + assert_eq!(z, r); } }