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

Reply via email to