[Mlir-commits] [mlir] [mlir][llvmir] Add new support for strict fp handling (PR #205158)
Andy Kaylor
llvmlistbot at llvm.org
Thu Jun 25 15:50:17 PDT 2026
================
@@ -1790,4 +1790,183 @@ def LLVM_AnyMDAttr : AnyAttrOf<[
LLVM_MDStringAttr, LLVM_MDConstantAttr, LLVM_MDFuncAttr, LLVM_MDNodeAttr],
"LLVM metadata attribute (md_string, md_const, md_func, or md_node)">;
+//===----------------------------------------------------------------------===//
+// FenvAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_FenvAttr : LLVM_Attr<"Fenv", "fenv"> {
+ let summary = "Describes floating-point environment constraints";
+ let description = [{
+ The `#llvm.fenv` attribute describes constraints on the floating-point
+ handling of a floating-point operation. It can be attached to
+ floating-point operations to capture rounding and exception behavior. All
+ of its parameters are optional.
+
+ - `rounding_mode`: the rounding mode to use. Every value other than
+ `dynamic` specifies a static rounding mode.
+ - `dynamic_rounding_mode`: the known dynamic rounding mode at the point the
+ instruction is executed. Otherwise the behavior is undefined.
+ - `except_mode`: the known exception mode at the point the instruction is
+ executed. Otherwise the behavior is undefined.
+ - `strict_snan`: whether to handle sNaN according to IEEE rules (`true`) or
+ LLVM's relaxed NaN propagation rules (`false`). This flag is only
+ meaningful when `except_mode` is `unmasked` or `unknown`, where it
+ defaults to `true`; when `except_mode` is `masked` the flag is ignored.
+ - `strict_except`: if `false`, any case that would produce an FP exception
+ produces it non-deterministically instead (i.e. it may or may not occur).
+ This means the FP status is written non-deterministically, and, if
+ exceptions are unmasked, the instruction traps non-deterministically.
+ This flag is only meaningful when `except_mode` is `unmasked` or
+ `unknown`, where it defaults to `true`; when `except_mode` is `masked`
+ the flag is ignored.
+
+ When this attribute is present on an operation, the operation is lowered to
+ the corresponding `llvm.experimental.constrained.*` intrinsic during
+ translation to LLVM IR.
+
+ The default setting for each parameter (`dynamic` rounding mode, `unknown`
+ dynamic rounding mode, `masked` exception mode, and, when exceptions are not
+ masked, `true` for both `strict_snan` and `strict_except`) is canonically
+ represented as an unset parameter. Constructing an attribute whose
+ parameters are all set to their defaults therefore yields the same
+ canonical, empty attribute as `#llvm.fenv<>`.
+
+ Carrying the (possibly empty) attribute is *not* the same as having no
+ attribute at all. An operation that carries the attribute is lowered to the
+ corresponding constrained intrinsic, even when every parameter is at its
----------------
andykaylor wrote:
It's not quite harmless. The point of forcing the use of constrained intrinsics when the default environment is specified is to provide a way to generate constrained intrinsics for all FP operations in a function when the environment may be changed anywhere in the function. The purpose of this is to provide a way to prevent instructions with default enviornment assumptions from migrating across instruction that may change the environment or read status flags. Without the intrinsic, the `fcmp` instruction could be hoisted into a region that was translated with fenv access enabled, potentially migrating above some operation that reads the status flags. This would be incorrect.
I'll fix that.
https://github.com/llvm/llvm-project/pull/205158
More information about the Mlir-commits
mailing list