[llvm-dev] Should rint and nearbyint be always constrained?

Ulrich Weigand via llvm-dev llvm-dev at lists.llvm.org
Thu Mar 5 10:15:09 PST 2020


Serge Pavlov <sepavloff at gmail.com> wrote on 05.03.2020 18:48:33:

>> I'm not sure what problem you see here.  In default mode, i.e.
>> when there is no "#pragma STDC FENV_ACCESS on" in effect,
>> then the compiler can always assume that the default rounding
>> mode is in effect.
>
> Well, if #pragma STDC FENV_ACCESS on is not in effect, that means
> that the user has promised that at this point during execution,
> we will *always* have the default FP environment.
>
> This is a strong statement (no pragma == default mode), we need to
> confirm it with proper references to the standard.

That statement is made explicitly (multiple times) in the standard.

Most specifically, C11 7.6.1.2 says:

"The FENV_ACCESS pragma provides a means to inform the implementation when
a
program might access the floating-point environment to test floating-point
status flags or
run under non-default floating-point control modes. 213)"

where the footnote clarifies:

"213) The purpose of the FENV_ACCESS pragma is to allow certain
optimizations that could subvert flag
tests and mode changes (e.g., global common subexpression elimination, code
motion, and constant
folding). In general, if the state of FENV_ACCESS is ‘‘off’’, the
translator can assume that default
modes are in effect and the flags are not tested."

This explicitly says the if FENV_ACCESS is off, the compiler can assume
that default modes (including default rounding modes) are in effect.

Later, C11 7.6.1.2 goes on to say:

"If part of a program tests floating-point status flags, sets
floating-point control
modes, or runs under non-default mode settings, but was translated with the
state for the
FENV_ACCESS pragma ‘‘off’’, the behavior is undefined."

This reiterates explicitly what I said in my earlier email, that whenever
any code is run that was compiled with FENV_ACCESS off, then at run-time
the default modes (including default rounding mode) must be in effect, or
else the behavior of the whole program is undefined.

The upcoming C2x standard complicates the logic a little bit since it
also introduces a FENV_ROUND pragma which may be used even in the
absence of FENV_ACCESS.  Nevertheless, if code is compiled without
either of FENV_ACCESS or FENV_ROUND in effect, the compiler may still
assume default modes.

>If it is true and the code:
>
> float qqq(float x) {
>   return nearbyint(x);
> }
>
> is really equivalent to:
>
> float qqq(float x) {
>   return roundeven(x);
> }
>
> (in absence of 'pragma STD FENV_ACCESS), it is a fact that would be
> surprise for many user.

In the absence of FENV_ACCESS, the compiler can assume "default" modes.
But what exactly those default modes are is implementation-defined,
so nearbyint *may* be equivalent to roundeven if that's the default,
but it may also be something else.

Bye,
Ulrich
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200305/4298db5b/attachment.html>


More information about the llvm-dev mailing list