[clang] [CIR] Record -ffp-contract=fast as a per-op contract flag (PR #226334)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 25 05:21:15 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: David Rivera (RiverDave)
<details>
<summary>Changes</summary>
Classic CodeGen stamps contract on floating-point instructions so a later Standard-fusion backend can still form an FMA. CIR only fused within a statement via cir.fmuladd, which dropped FFMA on the CUDA device default. While the LLVM dialect specifies nearly the same fast math flags, I didn't make use of them given it would introduce a dependency (partly inspired by a similar comment in a different PR: https://github.com/llvm/llvm-project/pull/223890#pullrequestreview-5246892362).
Assisted-by: Cursor / Grok 4.7
---
Patch is 51.14 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/226334.diff
15 Files Affected:
- (modified) clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h (+30-8)
- (modified) clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td (+30)
- (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+54-17)
- (modified) clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp (+15-6)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+22-10)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+18-1)
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+2)
- (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+6)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+93-28)
- (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+4)
- (added) clang/test/CIR/CodeGen/fp-contract-fast.c (+138)
- (modified) clang/test/CIR/CodeGen/fp-math-precision-opts.c (+4-4)
- (added) clang/test/CIR/CodeGenCUDA/fp-contract.cu (+57)
- (added) clang/test/CIR/Lowering/fastmath-contract.cir (+47)
- (modified) clang/utils/TableGen/CIRLoweringEmitter.cpp (+15-2)
``````````diff
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 29f1a64ad1d17..e8ec07a66a77a 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -74,6 +74,18 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
clang::LangOptions::FPE_Ignore;
llvm::RoundingMode defaultConstrainedRounding =
llvm::RoundingMode::NearestTiesToEven;
+ // Fast-math flags applied to floating-point ops created by this builder.
+ // CIRGen currently populates `contract` only.
+ cir::FastMathFlags fastMathFlags = cir::FastMathFlags::none;
+
+ void setFastMathFlags(cir::FastMathFlags flags) { fastMathFlags = flags; }
+ cir::FastMathFlags getFastMathFlags() const { return fastMathFlags; }
+
+ cir::FastMathFlagsAttr getFastMathFlagsAttr() {
+ if (fastMathFlags == cir::FastMathFlags::none)
+ return {};
+ return cir::FastMathFlagsAttr::get(getContext(), fastMathFlags);
+ }
mlir::Value getConstAPInt(mlir::Location loc, mlir::Type typ,
const llvm::APInt &val) {
@@ -848,32 +860,39 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
mlir::Value createFAdd(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
assert(!cir::MissingFeatures::metaDataNode());
+ // `contract` is applied via getFastMathFlagsAttr(). The other fast-math
+ // bits are still unimplemented.
assert(!cir::MissingFeatures::fastMathFlags());
- return cir::FAddOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
+ return cir::FAddOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr(),
+ getFastMathFlagsAttr());
}
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
assert(!cir::MissingFeatures::metaDataNode());
assert(!cir::MissingFeatures::fastMathFlags());
- return cir::FSubOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
+ return cir::FSubOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr(),
+ getFastMathFlagsAttr());
}
mlir::Value createFMul(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
assert(!cir::MissingFeatures::metaDataNode());
assert(!cir::MissingFeatures::fastMathFlags());
- return cir::FMulOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
+ return cir::FMulOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr(),
+ getFastMathFlagsAttr());
}
mlir::Value createFDiv(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
assert(!cir::MissingFeatures::metaDataNode());
assert(!cir::MissingFeatures::fastMathFlags());
- return cir::FDivOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
+ return cir::FDivOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr(),
+ getFastMathFlagsAttr());
}
mlir::Value createFRem(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
assert(!cir::MissingFeatures::metaDataNode());
assert(!cir::MissingFeatures::fastMathFlags());
- return cir::FRemOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr());
+ return cir::FRemOp::create(*this, loc, lhs, rhs, getConstrainedFPAttr(),
+ getFastMathFlagsAttr());
}
mlir::Value createFNeg(mlir::Location loc, mlir::Value operand) {
@@ -883,7 +902,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
assert(!cir::MissingFeatures::fastMathFlags());
// fneg does not raise FP exceptions or depend on the rounding mode, so it
// never carries an fenv attribute.
- return cir::FNegOp::create(*this, loc, operand);
+ return cir::FNegOp::create(*this, loc, operand, getFastMathFlagsAttr());
}
mlir::Value createXor(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
@@ -903,7 +922,10 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
cir::FenvAttr fenv;
if (cir::isAnyFloatingPointType(lhs.getType()))
fenv = getConstrainedFPAttr();
- return cir::CmpOp::create(*this, loc, kind, lhs, rhs, fenv);
+ return cir::CmpOp::create(*this, loc, kind, lhs, rhs, fenv,
+ cir::isAnyFloatingPointType(lhs.getType())
+ ? getFastMathFlagsAttr()
+ : cir::FastMathFlagsAttr{});
}
cir::VecCmpOp createVecCompare(mlir::Location loc, cir::CmpOpKind kind,
@@ -917,7 +939,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
if (cir::isFPOrVectorOfFPType(lhs.getType()))
fenv = getConstrainedFPAttr();
return cir::VecCmpOp::create(*this, loc, integralVecTy, kind, lhs, rhs,
- fenv);
+ fenv, getFastMathFlagsAttr());
}
mlir::Value createIsNaN(mlir::Location loc, mlir::Value operand) {
diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
index 3ee06412d8a90..ecd981593ec04 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td
@@ -47,6 +47,36 @@ class CIR_EnumAttr<EnumInfo info, string name = "", list<Trait> traits = []>
let assemblyFormat = "`<` $value `>`";
}
+// Bit positions match `mlir::LLVM::FastmathFlags`. Only `contract` is set by
+// CIRGen today; the other bits exist so the attribute can round-trip.
+def CIR_FastMathFlags : CIR_I32BitEnum<
+ "FastMathFlags", "fast-math flags", [
+ I32BitEnumCaseNone<"none">,
+ I32BitEnumCaseBit<"nnan", 0>,
+ I32BitEnumCaseBit<"ninf", 1>,
+ I32BitEnumCaseBit<"nsz", 2>,
+ I32BitEnumCaseBit<"arcp", 3>,
+ I32BitEnumCaseBit<"contract", 4>,
+ I32BitEnumCaseBit<"afn", 5>,
+ I32BitEnumCaseBit<"reassoc", 6>
+]> {
+ let description = [{
+ Per-operation fast-math flags. These are the LLVM fast-math bits, carried
+ on CIR floating-point operations and lowered onto the corresponding LLVM
+ dialect operation's `fastmathFlags`.
+
+ `contract` allows the backend to fuse this operation with another
+ floating-point operation, including across statements. It is what
+ `-ffp-contract=fast` records. `-ffp-contract=on` is represented separately
+ by `cir.fmuladd`.
+ }];
+ let separator = ", ";
+}
+
+def CIR_FastMathFlagsAttr : CIR_EnumAttr<CIR_FastMathFlags, "fastmath"> {
+ let summary = "Fast-math flags for a floating-point operation";
+}
+
def CIR_LangAddressSpace : CIR_I32Enum<
"LangAddressSpace", "language address space kind", [
I32EnumCase<"Default", 0, "default">,
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index c1ba78eea2835..9a83faff745d2 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -87,6 +87,10 @@ class LLVMLoweringInfo {
string llvmOp = "";
string constrainedLLVMIntrinsic = "";
bit constrainedLLVMIntrinsicHasRoundingMode = true;
+ // Copy an optional `fastmath` attribute onto the lowered LLVM operation.
+ // Floating-point ops that go through `lowerConstrainableFPOp` propagate the
+ // attribute there and do not need this bit.
+ bit propagateFastMathFlags = false;
}
class LoweringBuilders<dag p> {
@@ -2160,18 +2164,31 @@ def CIR_FNegOp : CIR_UnaryOp<"fneg", CIR_AnyFloatOrVecOfFloatType> {
The `cir.fneg` operation negates the operand. The operand and result must
have the same type.
+ The optional `fastmath` attribute carries LLVM fast-math flags for this
+ operation. `-ffp-contract=fast` sets `contract`.
+
Example:
```
%1 = cir.fneg %0 : !cir.float
- %3 = cir.fneg %2 : !cir.double
+ %3 = cir.fneg %2 : !cir.double {fastmath = #cir.fastmath<contract>}
%5 = cir.fneg %4 : !cir.vector<4 x !cir.float>
```
}];
+ let arguments = !con(commonArgs,
+ (ins OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath));
+
+ let builders = [
+ OpBuilder<(ins "mlir::Value":$input), [{
+ build($_builder, $_state, input, cir::FastMathFlagsAttr{});
+ }]>
+ ];
+
let hasFolder = 1;
let llvmOp = "FNegOp";
+ let propagateFastMathFlags = true;
}
//===----------------------------------------------------------------------===//
@@ -2626,7 +2643,8 @@ def CIR_CmpOp : CIR_Op<"cmp",
CIR_CmpOpKindAttr:$kind,
CIR_ComparableType:$lhs,
CIR_ComparableType:$rhs,
- OptionalAttr<CIR_FenvAttr>:$fenv
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath
);
let results = (outs CIR_BoolType:$result);
@@ -2638,11 +2656,13 @@ def CIR_CmpOp : CIR_Op<"cmp",
let builders = [
OpBuilder<(ins "cir::CmpOpKind":$kind, "mlir::Value":$lhs,
"mlir::Value":$rhs), [{
- build($_builder, $_state, kind, lhs, rhs, cir::FenvAttr{});
+ build($_builder, $_state, kind, lhs, rhs, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>,
OpBuilder<(ins "mlir::Type":$result, "cir::CmpOpKind":$kind,
"mlir::Value":$lhs, "mlir::Value":$rhs), [{
- build($_builder, $_state, result, kind, lhs, rhs, cir::FenvAttr{});
+ build($_builder, $_state, result, kind, lhs, rhs, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
@@ -2941,18 +2961,23 @@ def CIR_RemOp : CIR_BinaryOp<"rem", CIR_AnyIntOrVecOfIntType> {
// and result must all be the same floating-point scalar or vector type.
//
// The optional `fenv` attribute describes constraints on the floating-point
-// handling of the operation.
+// handling of the operation. The optional `fastmath` attribute carries LLVM
+// fast-math flags; `-ffp-contract=fast` sets `contract` here rather than
+// forming `cir.fmuladd`.
class CIR_FPBinaryOp<string mnemonic, list<Trait> traits = []>
: CIR_BinaryOp<mnemonic, CIR_AnyFloatOrVecOfFloatType,
!listconcat(CIR_FenvOpTraits, traits),
CIR_DynamicMemoryEffects> {
- let arguments = !con(commonArgs, (ins OptionalAttr<CIR_FenvAttr>:$fenv));
+ let arguments = !con(commonArgs, (ins
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath));
let constrainedLLVMIntrinsic = mnemonic;
let builders = [
OpBuilder<(ins "mlir::Value":$lhs, "mlir::Value":$rhs), [{
- build($_builder, $_state, lhs, rhs, cir::FenvAttr{});
+ build($_builder, $_state, lhs, rhs, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
}
@@ -6084,7 +6109,8 @@ def CIR_VecCmpOp : CIR_Op<"vec.cmp",
CIR_CmpOpKindAttr:$kind,
CIR_VectorType:$lhs,
CIR_VectorType:$rhs,
- OptionalAttr<CIR_FenvAttr>:$fenv
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath
);
let results = (outs CIR_VectorType:$result);
@@ -6097,7 +6123,8 @@ def CIR_VecCmpOp : CIR_Op<"vec.cmp",
let builders = [
OpBuilder<(ins "mlir::Type":$result, "cir::CmpOpKind":$kind,
"mlir::Value":$lhs, "mlir::Value":$rhs), [{
- build($_builder, $_state, result, kind, lhs, rhs, cir::FenvAttr{});
+ build($_builder, $_state, result, kind, lhs, rhs, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
@@ -7438,14 +7465,16 @@ class CIR_UnaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
!listconcat([SameOperandsAndResultType], CIR_FenvOpTraits)>
{
let arguments = (ins CIR_AnyFloatOrVecOfFloatType:$src,
- OptionalAttr<CIR_FenvAttr>:$fenv);
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath);
let results = (outs CIR_AnyFloatOrVecOfFloatType:$result);
let assemblyFormat = "$src `:` type($src) attr-dict";
let builders = [
OpBuilder<(ins "mlir::Value":$src), [{
- build($_builder, $_state, src, cir::FenvAttr{});
+ build($_builder, $_state, src, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
@@ -7706,6 +7735,7 @@ def CIR_FAbsOp : CIR_UnaryFPToFPBuiltinOp<"fabs", "FAbsOp"> {
// fabs is exact and does not raise exceptions, so it is always lowered to
// the plain llvm.fabs intrinsic.
let constrainedLLVMIntrinsic = "";
+ let propagateFastMathFlags = true;
}
def CIR_AbsOp : CIR_Op<"abs", [Pure, SameOperandsAndResultType]> {
@@ -7760,7 +7790,8 @@ class CIR_UnaryFPToIntBuiltinOp<string mnemonic, string llvmOpName>
: CIR_Op<mnemonic, CIR_FenvOpTraits>
{
let arguments = (ins CIR_AnyFloatType:$src,
- OptionalAttr<CIR_FenvAttr>:$fenv);
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath);
let results = (outs CIR_IntType:$result);
let summary = [{
@@ -7774,7 +7805,8 @@ class CIR_UnaryFPToIntBuiltinOp<string mnemonic, string llvmOpName>
let builders = [
OpBuilder<(ins "mlir::Type":$result, "mlir::Value":$src), [{
- build($_builder, $_state, result, src, cir::FenvAttr{});
+ build($_builder, $_state, result, src, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
@@ -7829,7 +7861,8 @@ class CIR_BinaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
let arguments = (ins
CIR_AnyFloatOrVecOfFloatType:$lhs,
CIR_AnyFloatOrVecOfFloatType:$rhs,
- OptionalAttr<CIR_FenvAttr>:$fenv
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath
);
let results = (outs CIR_AnyFloatOrVecOfFloatType:$result);
@@ -7841,7 +7874,8 @@ class CIR_BinaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
let builders = [
OpBuilder<(ins "mlir::Type":$result, "mlir::Value":$lhs,
"mlir::Value":$rhs), [{
- build($_builder, $_state, result, lhs, rhs, cir::FenvAttr{});
+ build($_builder, $_state, result, lhs, rhs, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
@@ -7857,6 +7891,7 @@ def CIR_CopysignOp : CIR_BinaryFPToFPBuiltinOp<"copysign", "CopySignOp"> {
// copysign is exact and does not raise exceptions, so it is always lowered
// to the plain llvm.copysign intrinsic.
+ let propagateFastMathFlags = true;
}
def CIR_FMaxNumOp : CIR_BinaryFPToFPBuiltinOp<"fmaxnum", "MaxNumOp"> {
@@ -7981,7 +8016,8 @@ class CIR_TernaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
CIR_AnyFloatOrVecOfFloatType:$a,
CIR_AnyFloatOrVecOfFloatType:$b,
CIR_AnyFloatOrVecOfFloatType:$c,
- OptionalAttr<CIR_FenvAttr>:$fenv
+ OptionalAttr<CIR_FenvAttr>:$fenv,
+ OptionalAttr<CIR_FastMathFlagsAttr>:$fastmath
);
let results = (outs CIR_AnyFloatOrVecOfFloatType:$result);
@@ -7991,7 +8027,8 @@ class CIR_TernaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
let builders = [
OpBuilder<(ins "mlir::Type":$result, "mlir::Value":$a, "mlir::Value":$b,
"mlir::Value":$c), [{
- build($_builder, $_state, result, a, b, c, cir::FenvAttr{});
+ build($_builder, $_state, result, a, b, c, cir::FenvAttr{},
+ cir::FastMathFlagsAttr{});
}]>
];
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 2b223c8ae1939..2d2ed0cceefbe 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
@@ -558,14 +558,18 @@ static RValue emitUnaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, &e);
auto call = Operation::create(cgf.getBuilder(), arg.getLoc(), arg.getType(),
- arg, cgf.getBuilder().getConstrainedFPAttr());
+ arg, cgf.getBuilder().getConstrainedFPAttr(),
+ cgf.getBuilder().getFastMathFlagsAttr());
return RValue::get(call->getResult(0));
}
template <class Operation>
static RValue emitUnaryFPBuiltin(CIRGenFunction &cgf, const CallExpr &e) {
mlir::Value arg = cgf.emitScalarExpr(e.getArg(0));
- auto call = Operation::create(cgf.getBuilder(), arg.getLoc(), arg);
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, &e);
+ auto call = Operation::create(cgf.getBuilder(), arg.getLoc(), arg.getType(),
+ arg, cir::FenvAttr{},
+ cgf.getBuilder().getFastMathFlagsAttr());
return RValue::get(call->getResult(0));
}
@@ -578,7 +582,8 @@ static RValue emitUnaryMaybeConstrainedFPToIntBuiltin(CIRGenFunction &cgf,
CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, &e);
auto call = Op::create(cgf.getBuilder(), src.getLoc(), resultType, src,
- cgf.getBuilder().getConstrainedFPAttr());
+ cgf.getBuilder().getConstrainedFPAttr(),
+ cgf.getBuilder().getFastMathFlagsAttr());
return RValue::get(call->getResult(0));
}
@@ -587,9 +592,11 @@ static RValue emitBinaryFPBuiltin(CIRGenFunction &cgf, const CallExpr &e) {
mlir::Value arg0 = cgf.emitScalarExpr(e.getArg(0));
mlir::Value arg1 = cgf.emitScalarExpr(e.getArg(1));
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, &e);
mlir::Location loc = cgf.getLoc(e.getExprLoc());
mlir::Type ty = cgf.convertType(e.getType());
- auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1);
+ auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1, cir::FenvAttr{},
+ cgf.getBuilder().getFastMathFlagsAttr());
return RValue::get(call->getResult(0));
}
@@ -621,7 +628,8 @@ static RValue emitTernaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
mlir::Type ty = cgf.convertType(e.getType());
auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1, arg2,
- cgf.getBuilder().getConstrainedFPAttr());
+ cgf.getBuilder().getConstrainedFPAttr(),
+ cgf.getBuilder().getFastMathFlagsAttr());
return RValue::get(call->getResult(0));
}
@@ -637,7 +645,8 @@ static mlir::Value emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &cgf,
mlir::Type ty = cgf.convertType(e.getType());
auto call = Op::create(cgf.getBuilder(), loc, ty, arg0, arg1,
- cgf.getBuilder().getConstrainedFPAttr());
+ cgf.getBuilder().getConstrainedFPAttr(),
+ cgf.getBuilder().getFastMathFlagsAttr());
return call->getResult(0);
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 80e8b36dfda6b..cc29109883b77 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -899,8 +899,11 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
mlir::Location loc = cgf.getLoc(e->getSourceRange().getBegin());
- if (cir::isFPOrVectorOfFPType(operand.getType()))
- return builder.createOrFold<cir::FNegOp>(loc, operand);
+ if (cir::isFPOrVectorOfFPType(operand.getType())) {
+ CIRGenFunction::CIRGenFPOptionsRAII FPOptsRAII(cgf, e);
+ return builder.createOrFold<cir::FNegOp>(loc, operand,
+ builder.getFastMathFlagsAttr());
+ }
// TODO(cir): We might have to change this to support overflow trapping.
// Classic codegen routes unary minus through emitSub to ensure
@@ -1281,6 +1284,9 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
BinOpInfo boInfo = emitBinOps(e);
mlir::Value lhs = boInfo.lhs;
mlir::Value rhs = boInfo.rhs;
+ std::optional<CIRGenFunction::CIRGenFPOptionsRAII> fpOpts;
+ if (cir::isFPOrVectorOfFPType(lhs.getType()))
+ fpOpts.emplace(cgf, boInfo.fpFeatures);
if (lhsTy->isVectorType()) {
if (!e->getType()->isVectorType()) {
@@ -1290,9 +1296,15 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
} else {
// Other kinds of vectors. Element-wise comparison returning
// a vector.
- result = cir::VecCmpOp::create(builder, cgf.getLoc(boInfo.loc),
- cgf.convertType(boInfo.fullType), kind,
- boInfo.lhs, boInfo.rhs);
+ result = cir::VecCmpOp::create(
+ bu...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/226334
More information about the cfe-commits
mailing list