[Mlir-commits] [mlir] [mlir][llvmir] Add new support for strict fp handling (PR #205158)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Mon Jun 22 13:51:24 PDT 2026


================
@@ -56,6 +58,229 @@ static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op) {
   return ret;
 }
 
+//===----------------------------------------------------------------------===//
+// Constrained floating-point lowering (the `#llvm.fenv` attribute).
+//===----------------------------------------------------------------------===//
+
+namespace {
+/// Scoped guard that configures the IRBuilder's constrained floating-point
+/// state, mirroring clang's `CodeGenFunction::CGFPOptionsRAII`. While the state
+/// is enabled, the IRBuilder automatically lowers ordinary floating-point
+/// operations (`CreateFAdd`, `CreateFCmp`, `CreateFPExt`, ...) to the matching
+/// `llvm.experimental.constrained.*` intrinsics. The previous state is restored
+/// on destruction.
+class ConstrainedFPStateRAII {
+public:
+  explicit ConstrainedFPStateRAII(llvm::IRBuilderBase &builder)
+      : builder(builder), oldIsConstrained(builder.getIsFPConstrained()),
+        oldExcept(builder.getDefaultConstrainedExcept()),
+        oldRounding(builder.getDefaultConstrainedRounding()) {}
+
+  ~ConstrainedFPStateRAII() {
+    builder.setIsFPConstrained(oldIsConstrained);
+    builder.setDefaultConstrainedExcept(oldExcept);
+    builder.setDefaultConstrainedRounding(oldRounding);
+  }
+
+  void enable(llvm::RoundingMode rounding, llvm::fp::ExceptionBehavior except) {
+    builder.setIsFPConstrained(true);
+    builder.setDefaultConstrainedRounding(rounding);
+    builder.setDefaultConstrainedExcept(except);
+  }
+
+private:
+  llvm::IRBuilderBase &builder;
+  bool oldIsConstrained;
+  llvm::fp::ExceptionBehavior oldExcept;
+  llvm::RoundingMode oldRounding;
+};
+} // namespace
+
+static llvm::RoundingMode
+getConstrainedRoundingMode(LLVM::FPEnvConstrainedOpInterface fenvOp) {
+  switch (fenvOp.getFenvRoundingMode()) {
----------------
adams381 wrote:

This switches on the static `rounding_mode` and emits it as the constrained intrinsic's rounding metadata, but that operand is descriptive, not prescriptive (your own words in Nikita's thread: the parameter was "intended to be descriptive").  So `#llvm.fenv<rounding_mode = upward>` comes out as `round.upward`, which tells the optimizer it may assume the dynamic mode is upward, not that the op forces upward.  For a static mode that's unsound, and the `binops` and `fptrunc` cases in `fenv.mlir` lock it in.

`getFenvDynamicRoundingMode()` is never read here, so `#llvm.fenv<dynamic_rounding_mode = tonearest>` comes out as `round.dynamic` and loses the known mode.  The field that matches the descriptive metadata is the one being ignored, and the field that can't be represented is the one being used.

I'd route `dynamic_rounding_mode` into the metadata and reject a non-`dynamic` static `rounding_mode` with the same NYI error you already give `fneg`, until there's real static-rounding lowering (Clang emits static, backend inserts `llvm.set.rounding`).

https://github.com/llvm/llvm-project/pull/205158


More information about the Mlir-commits mailing list