[clang] 025458b - [CIR] Add cir.fmuladd op lowering to llvm.fmuladd (#215329)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Aug 10 13:01:51 PDT 2026
Author: Konstantinos Parasyris
Date: 2026-08-10T13:01:46-07:00
New Revision: 025458b32a86364dd793c3a47f972364cbb2dad4
URL: https://github.com/llvm/llvm-project/commit/025458b32a86364dd793c3a47f972364cbb2dad4
DIFF: https://github.com/llvm/llvm-project/commit/025458b32a86364dd793c3a47f972364cbb2dad4.diff
LOG: [CIR] Add cir.fmuladd op lowering to llvm.fmuladd (#215329)
Adds a new `cir.fmuladd` operation to the CIR dialect, modeling the
contractable fused multiply-add — `(a * b) + c` where the backend may
fuse into a single rounding step or not, at its discretion.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply at anthropic.com>
Added:
Modified:
clang/include/clang/CIR/Dialect/IR/CIROps.td
clang/test/CIR/IR/fenv.cir
clang/test/CIR/Lowering/fenv.cir
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index d0f3c9ee6715f..88e869f7c2c4d 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -7757,6 +7757,35 @@ def CIR_FMAOp : CIR_TernaryFPToFPBuiltinOp<"fma", "FMAOp"> {
}];
}
+def CIR_FMulAddOp : CIR_TernaryFPToFPBuiltinOp<"fmuladd", "FMulAddOp"> {
+ let summary = "Contractable fused multiply-add operation";
+
+ let description = [{
+ Computes `(a * b) + c`, allowing the multiply and add to be fused (or not)
+ into a single rounding step at the target's discretion. It lowers to the
+ `llvm.fmuladd` intrinsic (or its constrained variant when an `fenv`
+ attribute is present).
+
+ Unlike `cir.fma`, which maps to `llvm.fma` and guarantees a single
+ rounding, `cir.fmuladd` expresses the FP-contraction relaxation used for
+ `a * b + c` under `-ffp-contract=on` / `fast`, where the backend is free to
+ emit either a fused or an unfused sequence.
+
+ The inputs must be either:
+ • floating-point scalar types, or
+ • vectors whose element type is floating-point.
+
+ The result type must match the input type exactly.
+
+ Examples:
+ // scalar
+ %r = cir.fmuladd %a, %b, %c : !cir.float
+
+ // vector
+ %v = cir.fmuladd %a, %b, %c : !cir.vector<4 x !cir.float>
+ }];
+}
+
//===----------------------------------------------------------------------===//
// Variadic Operations
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/IR/fenv.cir b/clang/test/CIR/IR/fenv.cir
index 5602212ea1de1..cb0a9287deb44 100644
--- a/clang/test/CIR/IR/fenv.cir
+++ b/clang/test/CIR/IR/fenv.cir
@@ -82,12 +82,27 @@ cir.func @unary_fp_to_int_builtin_fenv(%a: !cir.float) -> !s32i {
}
// CHECK-LABEL: cir.func @ternary_fp_builtin_fenv
-cir.func @ternary_fp_builtin_fenv(%a: !cir.float, %b: !cir.float, %c: !cir.float) {
+cir.func @ternary_fp_builtin_fenv(%a: !cir.float, %b: !cir.float, %c: !cir.float,
+ %va: !cir.vector<4 x !cir.float>,
+ %vb: !cir.vector<4 x !cir.float>,
+ %vc: !cir.vector<4 x !cir.float>) {
// CHECK: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.float {fenv = #cir.fenv<dynamic_rounding_mode = downward, strict_except = true>}
%0 = cir.fma %a, %b, %c : !cir.float {fenv = #cir.fenv<dynamic_rounding_mode = downward, strict_except = true>}
// CHECK: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.float
// CHECK-NOT: fenv
%1 = cir.fma %a, %b, %c : !cir.float
+ // CHECK: cir.fmuladd %{{.*}}, %{{.*}}, %{{.*}} : !cir.float {fenv = #cir.fenv<dynamic_rounding_mode = downward, strict_except = true>}
+ %2 = cir.fmuladd %a, %b, %c : !cir.float {fenv = #cir.fenv<dynamic_rounding_mode = downward, strict_except = true>}
+ // CHECK: cir.fmuladd %{{.*}}, %{{.*}}, %{{.*}} : !cir.float
+ // CHECK-NOT: fenv
+ %3 = cir.fmuladd %a, %b, %c : !cir.float
+ // CHECK: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float> {fenv = #cir.fenv<strict_except = true>}
+ %4 = cir.fma %va, %vb, %vc : !cir.vector<4 x !cir.float> {fenv = #cir.fenv<strict_except = true>}
+ // CHECK: cir.fmuladd %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float> {fenv = #cir.fenv<strict_except = true>}
+ %5 = cir.fmuladd %va, %vb, %vc : !cir.vector<4 x !cir.float> {fenv = #cir.fenv<strict_except = true>}
+ // CHECK: cir.fmuladd %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float>
+ // CHECK-NOT: fenv
+ %6 = cir.fmuladd %va, %vb, %vc : !cir.vector<4 x !cir.float>
cir.return
}
diff --git a/clang/test/CIR/Lowering/fenv.cir b/clang/test/CIR/Lowering/fenv.cir
index 282d51d2e73a7..cdb0c3f30bc62 100644
--- a/clang/test/CIR/Lowering/fenv.cir
+++ b/clang/test/CIR/Lowering/fenv.cir
@@ -124,6 +124,25 @@ module {
%0 = cir.fma %a, %b, %c : !cir.double {fenv = #cir.fenv<strict_except = true>}
// CHECK: llvm.intr.fma(%{{.*}}, %{{.*}}, %{{.*}}) : (f64, f64, f64) -> f64
%1 = cir.fma %a, %b, %c : !cir.double
+ // CHECK: llvm.call_intrinsic "llvm.experimental.constrained.fmuladd"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (f64, f64, f64, !llvm.metadata, !llvm.metadata) -> f64
+ %2 = cir.fmuladd %a, %b, %c : !cir.double {fenv = #cir.fenv<strict_except = true>}
+ // CHECK: llvm.intr.fmuladd(%{{.*}}, %{{.*}}, %{{.*}}) : (f64, f64, f64) -> f64
+ %3 = cir.fmuladd %a, %b, %c : !cir.double
+ cir.return
+ }
+
+ // CHECK-LABEL: llvm.func @ternary_fp_vec_builtins
+ cir.func @ternary_fp_vec_builtins(%a: !cir.vector<4 x !cir.float>,
+ %b: !cir.vector<4 x !cir.float>,
+ %c: !cir.vector<4 x !cir.float>) {
+ // CHECK: llvm.call_intrinsic "llvm.experimental.constrained.fma"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (vector<4xf32>, vector<4xf32>, vector<4xf32>, !llvm.metadata, !llvm.metadata) -> vector<4xf32>
+ %0 = cir.fma %a, %b, %c : !cir.vector<4 x !cir.float> {fenv = #cir.fenv<strict_except = true>}
+ // CHECK: llvm.intr.fma(%{{.*}}, %{{.*}}, %{{.*}}) : (vector<4xf32>, vector<4xf32>, vector<4xf32>) -> vector<4xf32>
+ %1 = cir.fma %a, %b, %c : !cir.vector<4 x !cir.float>
+ // CHECK: llvm.call_intrinsic "llvm.experimental.constrained.fmuladd"(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}, %{{.*}}) : (vector<4xf32>, vector<4xf32>, vector<4xf32>, !llvm.metadata, !llvm.metadata) -> vector<4xf32>
+ %2 = cir.fmuladd %a, %b, %c : !cir.vector<4 x !cir.float> {fenv = #cir.fenv<strict_except = true>}
+ // CHECK: llvm.intr.fmuladd(%{{.*}}, %{{.*}}, %{{.*}}) : (vector<4xf32>, vector<4xf32>, vector<4xf32>) -> vector<4xf32>
+ %3 = cir.fmuladd %a, %b, %c : !cir.vector<4 x !cir.float>
cir.return
}
More information about the cfe-commits
mailing list