public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Marc Glisse <marc.glisse@inria.fr>
To: Jason Merrill <jason@redhat.com>
Cc: gcc-patches@gcc.gnu.org, Jakub Jelinek <jakub@redhat.com>
Subject: Re: [PATCH] c++: Disable -frounding-math during manifestly constant evaluation [PR96862]
Date: Thu, 3 Sep 2020 00:43:16 +0200 (CEST)	[thread overview]
Message-ID: <alpine.DEB.2.23.453.2009030015130.35498@stedding.saclay.inria.fr> (raw)
In-Reply-To: <ee6ddb5f-7515-5b35-3bcf-1a1f3f0eb0b0@redhat.com>

On Wed, 2 Sep 2020, Jason Merrill via Gcc-patches wrote:

> On 9/1/20 6:13 AM, Marc Glisse wrote:
>> On Tue, 1 Sep 2020, Jakub Jelinek via Gcc-patches wrote:
>> 
>>> As discussed in the PR, fold-const.c punts on floating point constant
>>> evaluation if the result is inexact and -frounding-math is turned on.
>>>      /* Don't constant fold this floating point operation if the
>>>         result may dependent upon the run-time rounding mode and
>>>         flag_rounding_math is set, or if GCC's software emulation
>>>         is unable to accurately represent the result.  */
>>>      if ((flag_rounding_math
>>>           || (MODE_COMPOSITE_P (mode) && !flag_unsafe_math_optimizations))
>>>          && (inexact || !real_identical (&result, &value)))
>>>        return NULL_TREE;
>>> Jonathan said that we should be evaluating them anyway, e.g. conceptually
>>> as if they are done with the default rounding mode before user had a 
>>> chance
>>> to change that, and e.g. in C in initializers it is also ignored.
>>> In fact, fold-const.c for C initializers turns off various other options:
>>> 
>>> /* Perform constant folding and related simplification of initializer
>>>   expression EXPR.  These behave identically to "fold_buildN" but ignore
>>>   potential run-time traps and exceptions that fold must preserve.  */
>>> 
>>> #define START_FOLD_INIT \
>>>  int saved_signaling_nans = flag_signaling_nans;\
>>>  int saved_trapping_math = flag_trapping_math;\
>>>  int saved_rounding_math = flag_rounding_math;\
>>>  int saved_trapv = flag_trapv;\
>>>  int saved_folding_initializer = folding_initializer;\
>>>  flag_signaling_nans = 0;\
>>>  flag_trapping_math = 0;\
>>>  flag_rounding_math = 0;\
>>>  flag_trapv = 0;\
>>>  folding_initializer = 1;
>>> 
>>> #define END_FOLD_INIT \
>>>  flag_signaling_nans = saved_signaling_nans;\
>>>  flag_trapping_math = saved_trapping_math;\
>>>  flag_rounding_math = saved_rounding_math;\
>>>  flag_trapv = saved_trapv;\
>>>  folding_initializer = saved_folding_initializer;
>>> 
>>> So, shall cxx_eval_outermost_constant_expr instead turn off all those
>>> options (then warning_sentinel wouldn't be the right thing to use, but 
>>> given
>>> the 8 or how many return stmts in cxx_eval_outermost_constant_expr, we'd
>>> need a RAII class for this.  Not sure about the folding_initializer, that
>>> one is affecting complex multiplication and division constant evaluation
>>> somehow.
>> 
>> I don't think we need to turn off flag_signaling_nans or flag_trapv. I 
>> think we want to turn off flag_trapping_math so we can fold 1./0 to inf 
>> (still in a context where folding is mandatory). Setting 
>> folding_initializer seems consistent with that, enabling infinite results 
>> in complex folding (it also forces folding of __builtin_constant_p, which 
>> may be redundant with force_folding_builtin_constant_p).
>
> C++ says that division by zero has undefined behavior, and that an expression 
> with undefined behavior is not constant, so we shouldn't fold 1./0 to inf 
> anyway.  The same is true of other trapping operations.  So clearing 
> flag_signaling_nans, flag_trapping_math, and flag_trapv seems wrong for C++. 
> And folding_initializer seems to be used for the same sort of thing.

So we should actually force flag_trapping_math to true during constexpr
evaluation? And folding_initializer to false, and never mind trapv but
maybe disable wrapv?

#include <limits>
constexpr double a = std::numeric_limits<double>::infinity();
constexpr double b = a + a;
constexpr double c = a - a;
constexpr double d = 1. / a;
constexpr double e = 1. / d;

clang rejects c and e. MSVC rejects e. Intel warns on c.

Gcc rejects only e, and accepts the whole thing if I pass
-fno-trapping-math.

Almost any FP operation is possibly trapping, 1./3. sets FE_INEXACT just 
as 1./0. sets FE_DIVBYZERO. But the standard says

char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // Must be evaluated during translation

So it doesn't seem like it cares about that? Division by zero is the only 
one that gets weirdly special-cased...

-- 
Marc Glisse

  reply	other threads:[~2020-09-02 22:43 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-09-01  7:49 Jakub Jelinek
2020-09-01 10:13 ` Marc Glisse
2020-09-02 20:55   ` Jason Merrill
2020-09-02 22:43     ` Marc Glisse [this message]
2020-09-03 18:25       ` Jason Merrill
2020-09-03 15:03     ` Jakub Jelinek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=alpine.DEB.2.23.453.2009030015130.35498@stedding.saclay.inria.fr \
    --to=marc.glisse@inria.fr \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=jason@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).