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

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

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

suyash singh via cfe-dev
+cfe-dev as the discussion is now biased toward C standard.

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. 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.

Thanks,
--Serge


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

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

suyash singh via cfe-dev


> On Mar 5, 2020, at 12:48 PM, Serge Pavlov <[hidden email]> wrote:
>
> +cfe-dev as the discussion is now biased toward C standard.
>
> 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. 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.
>
> Thanks,
> —Serge


C standard: _The FENV_ACCESS pragma_
> 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.

"When set appropriately, the implementation may assume the default rounding mode is in effect."

> … The default state ("on" or "off") for the pragma is implementation-defined.


“`Off` is allowed to be the default mode.”

In the presence of the default rounding mode, if you cannot access flags, nearbyint and roundeven have identical observable behavior.

– Steve
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

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

suyash singh via cfe-dev
In reply to this post by suyash singh via cfe-dev

Serge Pavlov <[hidden email]> 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


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

Reply | Threaded
Open this post in threaded view
|

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

suyash singh via cfe-dev
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 <[hidden email]> wrote:

Serge Pavlov <[hidden email]> 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


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev