================
@@ -4045,18 +4045,56 @@ seq\_cst total orderings of other operations that are
not marked
Floating-Point Environment
--------------------------
-The default LLVM floating-point environment assumes that traps are disabled and
-status flags are not observable. Therefore, floating-point math operations do
-not have side effects and may be speculated freely. Results assume the
-round-to-nearest rounding mode, and subnormals are assumed to be preserved.
-
-Running LLVM code in an environment where these assumptions are not met
-typically leads to undefined behavior. The ``strictfp`` and
-:ref:`denormal_fpenv <denormal_fpenv>` attributes as well as
-:ref:`Constrained Floating-Point Intrinsics <constrainedfp>` can be
-used to weaken LLVM's assumptions and ensure defined behavior in
-non-default floating-point environments; see their respective
-documentation for details.
+The execution of an operation on floating-point values is often a more complex
+process than simply evaluating a function of its input arguments. First, it can
+depend on various parameters like rounding mode, denormal behavior, trap masks
+and so on. These are referenced to as "control modes" and are stored in
+floating-point control registers. In addition, the operation may set status
bits
+in a status register. Floating-point environment is a collection of registers
+that hold control modes and status bits.
+
+Interaction with the floating-point environment, including reading control
+modes, writing status bits and trapping, is regarded as side effects. Depending
+on how the side effects are treated, compilation occurs in one of two modes.
+
+In the ``strict mode``, all side effects produced by the floating-point
+operations are taken into account. Modifications to the floating-point
+environment are allowed only in this mode.
+
+In the ``unconstrained mode``, control modes are not modified and status bits
+are not observed. This allows floating-point operations to be considered free
+of side effects, which facilitates code optimizations. An important case of
this
+mode is the ``default mode``, in which the control modes have default values:
+rounding mode is "round to nearest, ties to even", traps are disabled, and
+subnormals are assumed to be preserved.
+
+The compilation mode is defined for an entire function and is specified by
----------------
kpneal wrote:
> I think this is wrong. Both "round" and "fpexcept" metadata are compiler
> hints, they do not affect the execution environment. Simple manipulation of
> them can produce incorrect behavior. For example, the code:
>
> ```
> define float @fsin(float %a) {
> %t = call float @llvm.sin.f32(float %a)
> ret float %t
> }
>
> define float @fexp(float %a) strictfp {
> %0 = call float @llvm.experimental.constrained.exp.f32(float %a, metadata
> !"round.downward", metadata !"fpexcept.strict")
> %1 = call float @fsin(float %0)
> ret float %1
> }
> ```
>
> currently is transformed by inlining into:
>
> ```
> define float @fexp(float %a) #0 {
> %0 = call float @llvm.experimental.constrained.exp.f32(float %a, metadata
> !"round.downward", metadata !"fpexcept.strict")
> %t.i = call float @llvm.experimental.constrained.sin.f32(float %0, metadata
> !"round.tonearest", metadata !"fpexcept.ignore")
> ret float %t.i
> }
> ```
>
> This code is incorrect. The argument `metadata !"round.tonearest"` informs
> the compiler that the instruction is executed with the rounding mode register
> set to "round to nearest, ties to even". The two constrained functions above
> have different, incompatible expectations, and there is no instruction
> between them that would adjust the rounding mode.
>
> Of course, inlining is a separate concern, this example merely demonstrates
> that preserving the default environment for an instruction has no a good
> solution.
No, that inlining is correct. It gives exactly the same behavior as not
inlining at all. If there's no inlining then the call to `@fsin()` will have
`@fsin()` compiled expecting the default floating point environment. That's
exactly what we're saying is the case when we inline and convert to a
constrained intrinsic with arguments that match the default FP environment.
This is an example of user error. When running in an alternate FP mode it's the
user's responsibility to make sure that calls to functions that do FP math know
they're in an alternate FP mode OR it's the user's responsibility to change
back to the default FP environment when calling a function that expects the
default FP environment.
https://github.com/llvm/llvm-project/pull/188297
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits