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.
This commit is contained in:
parent
d0695c9081
commit
003b8eadd7
5 changed files with 34 additions and 13 deletions
|
@ -277,5 +277,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||||
// simd_select
|
// simd_select
|
||||||
// simd_rem
|
// simd_rem
|
||||||
// simd_neg
|
// simd_neg
|
||||||
|
// simd_trunc
|
||||||
|
// simd_floor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1057,8 +1057,10 @@ fn generic_simd_intrinsic(
|
||||||
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
|
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
sym::simd_fcos => ("cos", 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_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_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_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
sym::simd_fexp2 => ("exp2", 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)),
|
sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)),
|
||||||
|
@ -1083,8 +1085,10 @@ fn generic_simd_intrinsic(
|
||||||
| sym::simd_fsin
|
| sym::simd_fsin
|
||||||
| sym::simd_fcos
|
| sym::simd_fcos
|
||||||
| sym::simd_fabs
|
| sym::simd_fabs
|
||||||
| sym::simd_floor
|
|
||||||
| sym::simd_ceil
|
| sym::simd_ceil
|
||||||
|
| sym::simd_floor
|
||||||
|
| sym::simd_round
|
||||||
|
| sym::simd_trunc
|
||||||
| sym::simd_fexp
|
| sym::simd_fexp
|
||||||
| sym::simd_fexp2
|
| sym::simd_fexp2
|
||||||
| sym::simd_flog10
|
| sym::simd_flog10
|
||||||
|
|
|
@ -1101,6 +1101,7 @@ symbols! {
|
||||||
simd_reduce_or,
|
simd_reduce_or,
|
||||||
simd_reduce_xor,
|
simd_reduce_xor,
|
||||||
simd_rem,
|
simd_rem,
|
||||||
|
simd_round,
|
||||||
simd_saturating_add,
|
simd_saturating_add,
|
||||||
simd_saturating_sub,
|
simd_saturating_sub,
|
||||||
simd_scatter,
|
simd_scatter,
|
||||||
|
@ -1109,6 +1110,7 @@ symbols! {
|
||||||
simd_shl,
|
simd_shl,
|
||||||
simd_shr,
|
simd_shr,
|
||||||
simd_sub,
|
simd_sub,
|
||||||
|
simd_trunc,
|
||||||
simd_xor,
|
simd_xor,
|
||||||
since,
|
since,
|
||||||
sinf32,
|
sinf32,
|
||||||
|
|
|
@ -407,8 +407,8 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
|
||||||
| sym::simd_fpow
|
| sym::simd_fpow
|
||||||
| sym::simd_saturating_add
|
| sym::simd_saturating_add
|
||||||
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
|
| sym::simd_saturating_sub => (1, vec![param(0), param(0)], param(0)),
|
||||||
sym::simd_neg => (1, vec![param(0)], param(0)),
|
sym::simd_neg
|
||||||
sym::simd_fsqrt
|
| sym::simd_fsqrt
|
||||||
| sym::simd_fsin
|
| sym::simd_fsin
|
||||||
| sym::simd_fcos
|
| sym::simd_fcos
|
||||||
| sym::simd_fexp
|
| sym::simd_fexp
|
||||||
|
@ -417,8 +417,10 @@ pub fn check_platform_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>)
|
||||||
| sym::simd_flog10
|
| sym::simd_flog10
|
||||||
| sym::simd_flog
|
| sym::simd_flog
|
||||||
| sym::simd_fabs
|
| sym::simd_fabs
|
||||||
|
| sym::simd_ceil
|
||||||
| sym::simd_floor
|
| 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_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_fma => (1, vec![param(0), param(0), param(0)], param(0)),
|
||||||
sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)),
|
sym::simd_gather => (3, vec![param(0), param(1), param(2)], param(0)),
|
||||||
|
|
|
@ -20,16 +20,20 @@ extern "platform-intrinsic" {
|
||||||
fn simd_fabs<T>(x: T) -> T;
|
fn simd_fabs<T>(x: T) -> T;
|
||||||
fn simd_fsin<T>(x: T) -> T;
|
fn simd_fsin<T>(x: T) -> T;
|
||||||
fn simd_fcos<T>(x: T) -> T;
|
fn simd_fcos<T>(x: T) -> T;
|
||||||
fn simd_ceil<T>(x: T) -> T;
|
|
||||||
fn simd_fexp<T>(x: T) -> T;
|
fn simd_fexp<T>(x: T) -> T;
|
||||||
fn simd_fexp2<T>(x: T) -> T;
|
fn simd_fexp2<T>(x: T) -> T;
|
||||||
fn simd_floor<T>(x: T) -> T;
|
|
||||||
fn simd_fma<T>(x: T, y: T, z: T) -> T;
|
fn simd_fma<T>(x: T, y: T, z: T) -> T;
|
||||||
fn simd_flog<T>(x: T) -> T;
|
fn simd_flog<T>(x: T) -> T;
|
||||||
fn simd_flog10<T>(x: T) -> T;
|
fn simd_flog10<T>(x: T) -> T;
|
||||||
fn simd_flog2<T>(x: T) -> T;
|
fn simd_flog2<T>(x: T) -> T;
|
||||||
fn simd_fpow<T>(x: T, y: T) -> T;
|
fn simd_fpow<T>(x: T, y: T) -> T;
|
||||||
fn simd_fpowi<T>(x: T, y: i32) -> T;
|
fn simd_fpowi<T>(x: T, y: i32) -> T;
|
||||||
|
|
||||||
|
// rounding functions
|
||||||
|
fn simd_ceil<T>(x: T) -> T;
|
||||||
|
fn simd_floor<T>(x: T) -> T;
|
||||||
|
fn simd_round<T>(x: T) -> T;
|
||||||
|
fn simd_trunc<T>(x: T) -> T;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! assert_approx_eq_f32 {
|
macro_rules! assert_approx_eq_f32 {
|
||||||
|
@ -64,18 +68,12 @@ fn main() {
|
||||||
let r = simd_fcos(z);
|
let r = simd_fcos(z);
|
||||||
assert_approx_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_ceil(h);
|
|
||||||
assert_approx_eq!(x, r);
|
|
||||||
|
|
||||||
let r = simd_fexp(z);
|
let r = simd_fexp(z);
|
||||||
assert_approx_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_fexp2(z);
|
let r = simd_fexp2(z);
|
||||||
assert_approx_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
let r = simd_floor(h);
|
|
||||||
assert_approx_eq!(z, r);
|
|
||||||
|
|
||||||
let r = simd_fma(x, h, h);
|
let r = simd_fma(x, h, h);
|
||||||
assert_approx_eq!(x, r);
|
assert_approx_eq!(x, r);
|
||||||
|
|
||||||
|
@ -99,5 +97,18 @@ fn main() {
|
||||||
|
|
||||||
let r = simd_fsin(z);
|
let r = simd_fsin(z);
|
||||||
assert_approx_eq!(z, r);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue