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
next prev parent 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).