Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 76ce3a9

Browse files
authoredOct 12, 2024
Rollup merge of rust-lang#124874 - jedbrown:float-mul-add-fast, r=saethlin
intrinsics fmuladdf{32,64}: expose llvm.fmuladd.* semantics Add intrinsics `fmuladd{f32,f64}`. 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 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). --- This topic has been discussed a few times on Zulip and was suggested, for example, by `@workingjubilee` in [Effect of fma disabled](https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/Effect.20of.20fma.20disabled/near/274179331).
2 parents eb8ff20 + eeb881d commit 76ce3a9

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed
 

‎core/src/intrinsics.rs

+53
Original file line numberDiff line numberDiff line change
@@ -1795,6 +1795,59 @@ extern "rust-intrinsic" {
17951795
#[rustc_nounwind]
17961796
pub fn fmaf128(a: f128, b: f128, c: f128) -> f128;
17971797

1798+
/// Returns `a * b + c` for `f16` values, non-deterministically executing
1799+
/// either a fused multiply-add or two operations with rounding of the
1800+
/// intermediate result.
1801+
///
1802+
/// The operation is fused if the code generator determines that target
1803+
/// instruction set has support for a fused operation, and that the fused
1804+
/// operation is more efficient than the equivalent, separate pair of mul
1805+
/// and add instructions. It is unspecified whether or not a fused operation
1806+
/// is selected, and that may depend on optimization level and context, for
1807+
/// example.
1808+
#[rustc_nounwind]
1809+
#[cfg(not(bootstrap))]
1810+
pub fn fmuladdf16(a: f16, b: f16, c: f16) -> f16;
1811+
/// Returns `a * b + c` for `f32` values, non-deterministically executing
1812+
/// either a fused multiply-add or two operations with rounding of the
1813+
/// intermediate result.
1814+
///
1815+
/// The operation is fused if the code generator determines that target
1816+
/// instruction set has support for a fused operation, and that the fused
1817+
/// operation is more efficient than the equivalent, separate pair of mul
1818+
/// and add instructions. It is unspecified whether or not a fused operation
1819+
/// is selected, and that may depend on optimization level and context, for
1820+
/// example.
1821+
#[rustc_nounwind]
1822+
#[cfg(not(bootstrap))]
1823+
pub fn fmuladdf32(a: f32, b: f32, c: f32) -> f32;
1824+
/// Returns `a * b + c` for `f64` values, non-deterministically executing
1825+
/// either a fused multiply-add or two operations with rounding of the
1826+
/// intermediate result.
1827+
///
1828+
/// The operation is fused if the code generator determines that target
1829+
/// instruction set has support for a fused operation, and that the fused
1830+
/// operation is more efficient than the equivalent, separate pair of mul
1831+
/// and add instructions. It is unspecified whether or not a fused operation
1832+
/// is selected, and that may depend on optimization level and context, for
1833+
/// example.
1834+
#[rustc_nounwind]
1835+
#[cfg(not(bootstrap))]
1836+
pub fn fmuladdf64(a: f64, b: f64, c: f64) -> f64;
1837+
/// Returns `a * b + c` for `f128` values, non-deterministically executing
1838+
/// either a fused multiply-add or two operations with rounding of the
1839+
/// intermediate result.
1840+
///
1841+
/// The operation is fused if the code generator determines that target
1842+
/// instruction set has support for a fused operation, and that the fused
1843+
/// operation is more efficient than the equivalent, separate pair of mul
1844+
/// and add instructions. It is unspecified whether or not a fused operation
1845+
/// is selected, and that may depend on optimization level and context, for
1846+
/// example.
1847+
#[rustc_nounwind]
1848+
#[cfg(not(bootstrap))]
1849+
pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
1850+
17981851
/// Returns the absolute value of an `f16`.
17991852
///
18001853
/// The stabilized version of this intrinsic is

0 commit comments

Comments
 (0)
Failed to load comments.