<div dir="ltr"><div>Let's summarize.<br><br>The view point that absence of `pragma STDC FENV_ACCESS` means default floating point modes is based on two statements in the standard:<br><br> 1. Description of `pragma STDC FENV_ACCESS` (n2454, 7.6.1p2):<br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div> 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.</div></blockquote><div><br> 2. Footnote in the same paragraph:<br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div> 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.</div></blockquote><div> <br>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:<br><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div>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.</div></blockquote><div><br>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.<br><br>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.<br><br>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.<br><br></div><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">Thanks,<br>--Serge<br></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Fri, Mar 6, 2020 at 1:28 AM Ulrich Weigand <<a href="mailto:Ulrich.Weigand@de.ibm.com">Ulrich.Weigand@de.ibm.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><p><tt><font size="2">Serge Pavlov <<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>> wrote on 05.03.2020 18:48:33:<br><br>>> I'm not sure what problem you see here. In default mode, i.e.<br>>> when there is no "#pragma STDC FENV_ACCESS on" in effect,<br>>> then the compiler can always assume that the default rounding<br>>> mode is in effect. </font></tt><br><tt><font size="2">> <br>> Well, if #pragma STDC FENV_ACCESS on is not in effect, that means<br>> that the user has promised that at this point during execution,<br>> we will *always* have the default FP environment.</font></tt><br><tt><font size="2">> </font></tt><br><tt><font size="2">> This is a strong statement (no pragma == default mode), we need to <br>> confirm it with proper references to the standard.</font></tt><br><br><tt><font size="2">That statement is made explicitly (multiple times) in the standard.</font></tt><br><br><tt><font size="2">Most specifically, C11 7.6.1.2 says:</font></tt><br><br><tt><font size="2">"The FENV_ACCESS pragma provides a means to inform the implementation when a</font></tt><br><tt><font size="2">program might access the floating-point environment to test floating-point status flags or</font></tt><br><tt><font size="2">run under non-default floating-point control modes. 213)"</font></tt><br><br><tt><font size="2">where the footnote clarifies:</font></tt><br><br><tt><font size="2">"213) The purpose of the FENV_ACCESS pragma is to allow certain optimizations that could subvert flag</font></tt><br><tt><font size="2">tests and mode changes (e.g., global common subexpression elimination, code motion, and constant</font></tt><br><tt><font size="2">folding). In general, if the state of FENV_ACCESS is ‘‘off’’, the translator can assume that default</font></tt><br><tt><font size="2">modes are in effect and the flags are not tested."</font></tt><br><br><tt><font size="2">This explicitly says the if FENV_ACCESS is off, the compiler can assume</font></tt><br><tt><font size="2">that default modes (including default rounding modes) are in effect.</font></tt><br><br><tt><font size="2">Later, C11 7.6.1.2 goes on to say:</font></tt><br><br><tt><font size="2">"If part of a program tests floating-point status flags, sets floating-point control</font></tt><br><tt><font size="2">modes, or runs under non-default mode settings, but was translated with the state for the</font></tt><br><tt><font size="2">FENV_ACCESS pragma ‘‘off’’, the behavior is undefined."</font></tt><br><br><tt><font size="2">This reiterates explicitly what I said in my earlier email, that whenever</font></tt><br><tt><font size="2">any code is run that was compiled with FENV_ACCESS off, then at run-time</font></tt><br><tt><font size="2">the default modes (including default rounding mode) must be in effect, or</font></tt><br><tt><font size="2">else the behavior of the whole program is undefined.</font></tt><br><br><tt><font size="2">The upcoming C2x standard complicates the logic a little bit since it</font></tt><br><tt><font size="2">also introduces a FENV_ROUND pragma which may be used even in the</font></tt><br><tt><font size="2">absence of FENV_ACCESS. Nevertheless, if code is compiled without</font></tt><br><tt><font size="2">either of FENV_ACCESS or FENV_ROUND in effect, the compiler may still</font></tt><br><tt><font size="2">assume default modes.</font></tt><br><br><tt><font size="2">>If it is true and the code:</font></tt><br><tt><font size="2">> <br>> float qqq(float x) {</font></tt><br><tt><font size="2">> return nearbyint(x);</font></tt><br><tt><font size="2">> }</font></tt><br><tt><font size="2">> <br>> is really equivalent to:</font></tt><br><tt><font size="2">> <br>> float qqq(float x) {</font></tt><br><tt><font size="2">> return roundeven(x);</font></tt><br><tt><font size="2">> }</font></tt><br><tt><font size="2">> <br>> (in absence of 'pragma STD FENV_ACCESS), it is a fact that would be <br>> surprise for many user.</font></tt><br><br><tt><font size="2">In the absence of FENV_ACCESS, the compiler can assume "default" modes.</font></tt><br><tt><font size="2">But what exactly those default modes are is implementation-defined,</font></tt><br><tt><font size="2">so nearbyint *may* be equivalent to roundeven if that's the default,</font></tt><br><tt><font size="2">but it may also be something else.</font></tt><br><br><tt><font size="2">Bye,</font></tt><br><tt><font size="2">Ulrich</font></tt><br><br>
</p></div>
</blockquote></div>