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

Serge Pavlov via llvm-dev llvm-dev at lists.llvm.org
Thu Mar 5 21:58:48 PST 2020


Let's summarize.

The view point that absence of `pragma STDC FENV_ACCESS` means default
floating point modes is based on two statements in the standard:

1. Description of `pragma STDC FENV_ACCESS` (n2454, 7.6.1p2):

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.


2. Footnote in the same paragraph:

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 the
flags are not tested, and that default modes are in effect, except where
specified otherwise by an FENV_ROUND pragma.


As for the statement 1, it can be understood differently: to run under
non-default floating-point control modes, one must change these modes, and
the pragma informs compiler about the change not about using. This
interpretation is supported by the following statement in the same
paragraph:

If part of a program tests floating-point status flags or establishes
non-default floating-point mode settings using any means other than the
FENV_ROUND pragmas, but was translated with the state for the FENV_ACCESS
pragma "off", the behavior is undefined.


Hence if a function only queries about current rounding mode (as in the
above example with nearbyint), there is no undefined behavior. This is
either a conforming code, or an error, which requires diagnostics. In the
former case the function `nearbyint` must behave as prescribed by the
standard, - perform rounding according to current rounding mode.

As for the statement 2, yes, it almost clearly votes for implicit default
FP modes. "In general" is a bit confusing. May be "in particular" cases
compiler cannot make such assumptions? I think this question should be
addressed to language lawyers.

There is a concern that such interpretation can break compatibility with
existing programs. Even without `pragma STD FENV_ACCESS` users could use
non-default rounding modes, - library functions provided barriers that
prevented from undesirable code movement and programs worked as expected.
Changing rules may cause negative consequences.

Thanks,
--Serge


On Fri, Mar 6, 2020 at 1:28 AM Ulrich Weigand <Ulrich.Weigand at de.ibm.com>
wrote:

> 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/20200306/7b9fa3c2/attachment.html>


More information about the llvm-dev mailing list