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) <[email protected]> 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 } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
