[PATCH] Fold x/x to 1, 0/x to 0 and 0%x to 0 consistently

Jason Merrill jason@redhat.com
Thu Jun 9 22:07:00 GMT 2016


On Thu, Jun 9, 2016 at 3:39 AM, Richard Biener <rguenther@suse.de> wrote:
> On Thu, 9 Jun 2016, Jakub Jelinek wrote:
>
>> On Thu, Jun 09, 2016 at 08:50:15AM +0200, Richard Biener wrote:
>> > On Wed, 8 Jun 2016, Jason Merrill wrote:
>> >
>> > > On Wed, Jun 8, 2016 at 11:16 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
>> > > > On Wed, 8 Jun 2016, Richard Biener wrote:
>> > > >
>> > > >> The following works around PR70992 but the issue came up repeatedly
>> > > >> that we are not very consistent in preserving the undefined behavior
>> > > >> of division or modulo by zero.  Ok - the only inconsistency is
>> > > >> that we fold 0 % x to 0 but not 0 % 0 (with literal zero).
>> > > >>
>> > > >> After folding is now no longer done early in the C family FEs the
>> > > >> number of diagnostic regressions with the patch below is two.
>> > > >>
>> > > >> FAIL: g++.dg/cpp1y/constexpr-sfinae.C  -std=c++14 (test for excess errors)
>> > >
>> > > Yep. We don't want to fold away undefined behavior in a constexpr
>> > > function, since constexpr evaluation wants to detect undefined
>> > > behavior and treat the expression as non-constant in that case.
>> >
>> > Hmm.  So 0 / x is not constant because x might be zero but 0 * x is
>> > constant because it can never invoke undefined behavior?  Does this mean
>> > that 0 << n is not const because n might be too large (I suppose
>> > 0 << 12000 is not const already)?  Is 0 * (-x) const?  x might be INT_MIN.
>>
>> E.g. for the shifts the C++ FE has cxx_eval_check_shift_p which should
>> optionally warn and/or set *non_constant_p.  0 * (-INT_MIN) would be
>> non-constant too, etc.
>> constexpr int foo (int x) { return -x; }
>> constexpr int bar (int x) { return 0 * (-x); }
>> constexpr int a = foo (-__INT_MAX__ - 1);
>> constexpr int b = bar (-__INT_MAX__ - 1);
>> shows that we don't diagnose the latter though, most likely because
>> constexpr evaluation is done on the folded tree.

I don't think there's any folding before constexpr evaluation in this
case, since this doesn't involve a call.

>> So, either whatever cp_fold does (which uses fold* underneath) should avoid
>> folding such cases, or the constexpr evaluation should be done on a copy
>> made before folding.  Then cp_fold doesn't have to prohibit optimizations
>> and it is a matter of constexpr.c routines to detect all the undefined
>> behavior.  After all, I think doing constexpr evaluation on unfolded trees
>> will have also the advantage of better diagnostic locations.
>
> Yes, I think constexpr diagnostic / detection should be done on
> unfolded trees (not sure why we'd need to a copy here, just do folding
> later?).  If cp_fold already avoids folding 0 * (-x) then it should
> simply avoid folding 0 / x or 0 % x as well (for the particular issue
> this thread started on).

The issue is with constexpr functions, which get delayed folding like
any other function before they are used in constant expression
evaluation.  The copy would be to preserve the unfolded trees through
cp_fold_function.  I've been thinking about doing this anyway; this
may be the motivation to go ahead with it.

Jason



More information about the Gcc-patches mailing list