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).
The following patch has been bootstrapped/regtested on x86_64-linux and i686-linux, but see above, maybe we want something else. 2020-09-01 Jakub Jelinek <ja...@redhat.com> PR c++/96862 * constexpr.c (cxx_eval_outermost_constant_expr): Temporarily disable flag_rounding_math during manifestly constant evaluation. * g++.dg/cpp1z/constexpr-96862.C: New test. --- gcc/cp/constexpr.c.jj 2020-08-31 14:10:15.826921458 +0200 +++ gcc/cp/constexpr.c 2020-08-31 15:41:26.429964532 +0200 @@ -6680,6 +6680,8 @@ cxx_eval_outermost_constant_expr (tree t allow_non_constant, strict, manifestly_const_eval || !allow_non_constant }; + /* Turn off -frounding-math for manifestly constant evaluation. */ + warning_sentinel rm (flag_rounding_math, ctx.manifestly_const_eval); tree type = initialized_type (t); tree r = t; bool is_consteval = false; --- gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C.jj 2020-08-31 15:50:07.847473028 +0200 +++ gcc/testsuite/g++.dg/cpp1z/constexpr-96862.C 2020-08-31 15:49:40.829861168 +0200 @@ -0,0 +1,20 @@ +// PR c++/96862 +// { dg-do compile { target c++17 } } +// { dg-additional-options "-frounding-math" } + +constexpr double a = 0x1.0p+100 + 0x1.0p-100; +const double b = 0x1.0p+100 + 0x1.0p-100; +const double &&c = 0x1.0p+100 + 0x1.0p-100; +static_assert (0x1.0p+100 + 0x1.0p-100 == 0x1.0p+100, ""); + +void +foo () +{ + constexpr double d = 0x1.0p+100 + 0x1.0p-100; + const double e = 0x1.0p+100 + 0x1.0p-100; + const double &&f = 0x1.0p+100 + 0x1.0p-100; + static_assert (0x1.0p+100 + 0x1.0p-100 == 0x1.0p+100, ""); +} + +const double &g = a; +const double &h = b; Jakub
-- Marc Glisse