Merge pull request #219 from sadlerap/float-intrinsics

simd: implement float math intrinsics
This commit is contained in:
antoyo 2022-09-28 10:45:46 -04:00 committed by GitHub
commit 8ead881fbf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 26 deletions

View File

@ -30,7 +30,6 @@ src/test/ui/sepcomp/sepcomp-extern.rs
src/test/ui/sepcomp/sepcomp-fns-backwards.rs src/test/ui/sepcomp/sepcomp-fns-backwards.rs
src/test/ui/sepcomp/sepcomp-fns.rs src/test/ui/sepcomp/sepcomp-fns.rs
src/test/ui/sepcomp/sepcomp-statics.rs src/test/ui/sepcomp/sepcomp-statics.rs
src/test/ui/simd/intrinsic/float-math-pass.rs
src/test/ui/simd/intrinsic/generic-arithmetic-pass.rs src/test/ui/simd/intrinsic/generic-arithmetic-pass.rs
src/test/ui/simd/intrinsic/generic-as.rs src/test/ui/simd/intrinsic/generic-as.rs
src/test/ui/simd/intrinsic/generic-bitmask-pass.rs src/test/ui/simd/intrinsic/generic-bitmask-pass.rs
@ -40,7 +39,6 @@ src/test/ui/simd/issue-17170.rs
src/test/ui/simd/issue-39720.rs src/test/ui/simd/issue-39720.rs
src/test/ui/simd/issue-85915-simd-ptrs.rs src/test/ui/simd/issue-85915-simd-ptrs.rs
src/test/ui/simd/issue-89193.rs src/test/ui/simd/issue-89193.rs
src/test/ui/simd/libm_std_can_float.rs
src/test/ui/simd/simd-bitmask.rs src/test/ui/simd/simd-bitmask.rs
src/test/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs src/test/ui/simd/type-generic-monomorphisation-extern-nonnull-ptr.rs
src/test/ui/sse2.rs src/test/ui/sse2.rs

View File

@ -14,7 +14,6 @@ use rustc_span::{Span, Symbol, sym};
use rustc_target::abi::Align; use rustc_target::abi::Align;
use crate::builder::Builder; use crate::builder::Builder;
use crate::intrinsic;
pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result<RValue<'gcc>, ()> { pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result<RValue<'gcc>, ()> {
// macros for error handling: // macros for error handling:
@ -415,8 +414,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if let ty::Float(f) = in_elem.kind() { if let ty::Float(f) = in_elem.kind() {
let elem_ty = bx.cx.type_float_from_ty(*f); let elem_ty = bx.cx.type_float_from_ty(*f);
match f.bit_width() { match f.bit_width() {
32 => ("f32", elem_ty), 32 => ("f", elem_ty),
64 => ("f64", elem_ty), 64 => ("", elem_ty),
_ => { _ => {
return_error!( return_error!(
"unsupported element type `{}` of floating-point vector `{}`", "unsupported element type `{}` of floating-point vector `{}`",
@ -432,30 +431,49 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let vec_ty = bx.cx.type_vector(elem_ty, in_len); let vec_ty = bx.cx.type_vector(elem_ty, in_len);
let (intr_name, fn_ty) = let intr_name =
match name { match name {
sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)), sym::simd_ceil => "ceil",
sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), // TODO(antoyo): pand with 170141183420855150465331762880109871103 sym::simd_fabs => "fabs", // TODO(antoyo): pand with 170141183420855150465331762880109871103
sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fcos => "cos",
sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp2 => "exp2",
sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fexp => "exp",
sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog10 => "log10",
sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog2 => "log2",
sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)), sym::simd_flog => "log",
sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), sym::simd_floor => "floor",
sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), sym::simd_fma => "fma",
sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)), sym::simd_fpowi => "__builtin_powi",
sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)), sym::simd_fpow => "pow",
sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fsin => "sin",
sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), sym::simd_fsqrt => "sqrt",
sym::simd_round => ("round", bx.type_func(&[vec_ty], vec_ty)), sym::simd_round => "round",
sym::simd_trunc => ("trunc", bx.type_func(&[vec_ty], vec_ty)), sym::simd_trunc => "trunc",
_ => return_error!("unrecognized intrinsic `{}`", name), _ => return_error!("unrecognized intrinsic `{}`", name),
}; };
let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); let builtin_name = format!("{}{}", intr_name, elem_ty_str);
let function = intrinsic::llvm::intrinsic(llvm_name, &bx.cx); let funcs = bx.cx.functions.borrow();
let function: RValue<'gcc> = unsafe { std::mem::transmute(function) }; let function = funcs.get(&builtin_name).unwrap_or_else(|| panic!("unable to find builtin function {}", builtin_name));
let c = bx.call(fn_ty, function, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None);
// TODO(antoyo): add platform-specific behavior here for architectures that have these
// intrinsics as instructions (for instance, gpus)
let mut vector_elements = vec![];
for i in 0..in_len {
let index = bx.context.new_rvalue_from_long(bx.ulong_type, i as i64);
// we have to treat fpowi specially, since fpowi's second argument is always an i32
let arguments = if name == sym::simd_fpowi {
vec![
bx.extract_element(args[0].immediate(), index).to_rvalue(),
args[1].immediate(),
]
} else {
args.iter()
.map(|arg| bx.extract_element(arg.immediate(), index).to_rvalue())
.collect()
};
vector_elements.push(bx.context.new_call(None, *function, &arguments));
}
let c = bx.context.new_rvalue_from_vector(None, vec_ty, &vector_elements);
Ok(c) Ok(c)
} }