[clang] [CIR] Implement support for builtin FMA (PR #210365)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 17 09:20:19 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangir
Author: Amr Hesham (AmrDeveloper)
<details>
<summary>Changes</summary>
Implement support for the _builtin_fma
---
Full diff: https://github.com/llvm/llvm-project/pull/210365.diff
4 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+37)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+17-1)
- (modified) clang/test/CIR/CodeGen/builtins-x86.c (+25)
- (modified) clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c (+9)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 0a60514ee21fc..814d88ac014fb 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -7262,6 +7262,43 @@ def CIR_ModfOp : CIR_Op<"modf", [Pure]> {
}];
}
+class CIR_TernaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
+ : CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]>
+{
+ let arguments = (ins
+ CIR_AnyFloatOrVecOfFloatType:$a,
+ CIR_AnyFloatOrVecOfFloatType:$b,
+ CIR_AnyFloatOrVecOfFloatType:$c
+ );
+
+ let results = (outs CIR_AnyFloatOrVecOfFloatType:$result);
+
+ let assemblyFormat = "$a `,` $b `,` $c `:` type($a) attr-dict";
+
+ let llvmOp = llvmOpName;
+}
+
+def CIR_FMAOp : CIR_TernaryFPToFPBuiltinOp<"fma", "FMAOp"> {
+ let summary = "Fused Multiply-Add operation";
+
+ let description = [{
+ Computes the fused multiply-add of three floating-point values or vector.
+
+ 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.fma %a, %b, %c : !cir.float
+
+ // vector
+ %v = cir.fma %a, %b, %c : !cir.vector<4 x !cir.float>
+ }];
+}
+
//===----------------------------------------------------------------------===//
// Variadic Operations
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 9b2ea8bf0e4bb..5fdc76bfbb362 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -394,6 +394,22 @@ static RValue emitBinaryFPBuiltin(CIRGenFunction &cgf, const CallExpr &e) {
return RValue::get(call->getResult(0));
}
+template <typename Op>
+static RValue emitTernaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
+ const CallExpr &e) {
+ mlir::Value arg0 = cgf.emitScalarExpr(e.getArg(0));
+ mlir::Value arg1 = cgf.emitScalarExpr(e.getArg(1));
+ mlir::Value arg2 = cgf.emitScalarExpr(e.getArg(2));
+
+ mlir::Location loc = cgf.getLoc(e.getExprLoc());
+ mlir::Type ty = cgf.convertType(e.getType());
+
+ assert(!cir::MissingFeatures::fpConstraints());
+
+ auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1, arg2);
+ return RValue::get(call->getResult(0));
+}
+
template <typename Op>
static mlir::Value emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
const CallExpr &e) {
@@ -648,7 +664,7 @@ static RValue tryEmitFPMathIntrinsic(CIRGenFunction &cgf, const CallExpr *e,
case Builtin::BI__builtin_fmal:
case Builtin::BI__builtin_fmaf128:
case Builtin::BI__builtin_elementwise_fma:
- return errorBuiltinNYI(cgf, e, builtinID);
+ return emitTernaryMaybeConstrainedFPBuiltin<cir::FMAOp>(cgf, *e);
case Builtin::BIfmax:
case Builtin::BIfmaxf:
case Builtin::BIfmaxl:
diff --git a/clang/test/CIR/CodeGen/builtins-x86.c b/clang/test/CIR/CodeGen/builtins-x86.c
index fa0cfd2fd5322..4f72a3000fc44 100644
--- a/clang/test/CIR/CodeGen/builtins-x86.c
+++ b/clang/test/CIR/CodeGen/builtins-x86.c
@@ -289,3 +289,28 @@ void test_movntss(float *dest, v4f src) {
// OGCG: store float %{{.*}}, ptr %{{.*}}, align 1, !nontemporal
return __builtin_ia32_movntss(dest, src);
}
+
+float test_fma_f32(float a, float b, float c) {
+ // CIR-LABEL: test_fma_f32
+ // CIR: %[[R:.*]] = cir.fma %[[A:.*]], %[[B:.*]], %[[C:.*]] : !cir.float
+
+ // LLVM-LABEL: @test_fma_f32
+ // LLVM: %[[R:.*]] = call float @llvm.fma.f32(float %[[A:.*]], float %[[B:.*]], float %[[C:.*]])
+
+ // OGCG-LABEL: @test_fma_f32
+ // OGCG: %[[R:.*]] = call float @llvm.fma.f32(float %[[A:.*]], float %[[B:.*]], float %[[C:.*]])
+ return __builtin_fmaf(a, b, c);
+}
+
+double test_fma_f64(double a, double b, double c) {
+ // CIR-LABEL: test_fma_f64
+ // CIR: %[[R:.*]] = cir.fma %[[A:.*]], %[[B:.*]], %[[C:.*]] : !cir.double
+
+ // LLVM-LABEL: @test_fma_f64
+ // LLVM: %[[R:.*]] = call double @llvm.fma.f64(double %[[A:.*]], double %[[B:.*]], double %[[C:.*]])
+
+ // OGCG-LABEL: @test_fma_f64
+ // OGCG: %[[R:.*]] = call double @llvm.fma.f64(double %[[A:.*]], double %[[B:.*]], double %[[C:.*]])
+ return __builtin_fma(a, b, c);
+}
+
diff --git a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
index 442ecdaa7faf1..b5600901be247 100644
--- a/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
+++ b/clang/test/CIR/CodeGenBuiltins/builtins-elementwise.c
@@ -640,3 +640,12 @@ void test_builtin_elementwise_sub_sat(int i1, int i2, unsigned u1, unsigned u2,
// LLVM: call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
vs1 = __builtin_elementwise_sub_sat(vs1, vs2);
}
+
+vfloat4 test_builtin_elementwise_fma(vfloat4 a, vfloat4 b, vfloat4 c) {
+ // CIR-LABEL: test_builtin_elementwise_fma
+ // LLVM-LABEL: test_builtin_elementwise_fma
+
+ // CIR: cir.fma %{{.*}}, %{{.*}}, %{{.*}} : !cir.vector<4 x !cir.float>
+ // LLVM: call <4 x float> @llvm.fma.v4f32(<4 x float> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}})
+ return __builtin_elementwise_fma(a, b, c);
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/210365
More information about the cfe-commits
mailing list