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

Richard Biener rguenther@suse.de
Fri Jun 10 07:11:00 GMT 2016


On Thu, 9 Jun 2016, Jason Merrill wrote:

> 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.

Or delay the folding until genericization - that is, after all parsing
is complete.  Not sure what this would do to memory usage or compile-time
when we keep all unfolded bodies (or even re-use them in template
instantiation).

Richard.



More information about the Gcc-patches mailing list