Skip to content

Commit 270fb21

Browse files
committed
intrinsics.fmuladdf{16,32,64,128}: expose llvm.fmuladd.* semantics
Add intrinsics `fmuladd{f16,f32,f64,f128}`. This computes `(a * b) + c`, to be fused if the code generator determines that (i) the target instruction set has support for a fused operation, and (ii) that the fused operation is more efficient than the equivalent, separate pair of `mul` and `add` instructions. https://llvm.org/docs/LangRef.html#llvm-fmuladd-intrinsic MIRI support is included for f32 and f64. The codegen_cranelift uses the `fma` function from libc, which is a correct implementation, but without the desired performance semantic. I think this requires an update to cranelift to expose a suitable instruction in its IR. I have not tested with codegen_gcc, but it should behave the same way (using `fma` from libc).
1 parent 4850441 commit 270fb21

File tree

1 file changed

+4
-1
lines changed

1 file changed

+4
-1
lines changed

src/intrinsics/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,9 @@ fn codegen_float_intrinsic_call<'tcx>(
328328
sym::fabsf64 => ("fabs", 1, fx.tcx.types.f64, types::F64),
329329
sym::fmaf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32),
330330
sym::fmaf64 => ("fma", 3, fx.tcx.types.f64, types::F64),
331+
// FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation
332+
sym::fmuladdf32 => ("fmaf", 3, fx.tcx.types.f32, types::F32), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f32
333+
sym::fmuladdf64 => ("fma", 3, fx.tcx.types.f64, types::F64), // TODO: use cranelift intrinsic analogous to llvm.fmuladd.f64
331334
sym::copysignf32 => ("copysignf", 2, fx.tcx.types.f32, types::F32),
332335
sym::copysignf64 => ("copysign", 2, fx.tcx.types.f64, types::F64),
333336
sym::floorf32 => ("floorf", 1, fx.tcx.types.f32, types::F32),
@@ -381,7 +384,7 @@ fn codegen_float_intrinsic_call<'tcx>(
381384

382385
let layout = fx.layout_of(ty);
383386
let res = match intrinsic {
384-
sym::fmaf32 | sym::fmaf64 => {
387+
sym::fmaf32 | sym::fmaf64 | sym::fmuladdf32 | sym::fmuladdf64 => {
385388
CValue::by_val(fx.bcx.ins().fma(args[0], args[1], args[2]), layout)
386389
}
387390
sym::copysignf32 | sym::copysignf64 => {

0 commit comments

Comments
 (0)