On Wed, 16 Nov 2016, Marc Glisse wrote:

> On Wed, 16 Nov 2016, Richard Biener wrote:
> 
> > I am testing the following to avoid undefined behavior when negating
> > a multiplication (basically extending a previous fix to properly handle
> > negative power of two).
> > 
> > Bootstrap / regtest running on x86_64-unknown-linux-gnu.
> > 
> > Richard.
> > 
> > 2016-11-16  Richard Biener  <rguent...@suse.de>
> > 
> >     PR middle-end/78305
> >     * fold-const.c (negate_expr_p): Fix multiplication case.
> > 
> >     * gcc.dg/torture/pr78305.c: New testcase.
> > 
> > Index: gcc/fold-const.c
> > ===================================================================
> > --- gcc/fold-const.c        (revision 242471)
> > +++ gcc/fold-const.c        (working copy)
> > @@ -450,13 +450,15 @@ negate_expr_p (tree t)
> >       if (TYPE_UNSIGNED (type))
> >     break;
> >       /* INT_MIN/n * n doesn't overflow while negating one operand it does
> > -         if n is a power of two.  */
> > +         if n is a power of (minus) two.  */
> 
> if n is (minus) a power of two.
> if n is a divisor of INT_MIN.

n is a divisor of INT_MIN is correct.

> >       if (INTEGRAL_TYPE_P (TREE_TYPE (t))
> >       && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (t))
> >       && ! ((TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST
> > -            && ! integer_pow2p (TREE_OPERAND (t, 0)))
> > +            && (wi::popcount (TREE_OPERAND (t, 0))
> > +                != 1 + wi::neg_p (TREE_OPERAND (t, 0), SIGNED)))
> 
> Is that supposed to test for (possibly negated) powers of 2? I don't see it.
> For -2, aka 0b11...110, popcount is 31 != 1 + 1.

It's supposed to test for a power of two with the sign-bit ORed in.
I believe those are which, when multiplied with some number can
yield INT_MIN.  That is, we look for a test that ensures that there
exists no number when multiplied with X yields INT_MIN.

Richard.

> >             || (TREE_CODE (TREE_OPERAND (t, 1)) == INTEGER_CST
> > -               && ! integer_pow2p (TREE_OPERAND (t, 1)))))
> > +               && (wi::popcount (TREE_OPERAND (t, 1))
> > +                   != 1 + wi::neg_p (TREE_OPERAND (t, 1), SIGNED)))))
> >     break;
> > 
> >       /* Fall through.  */
> > Index: gcc/testsuite/gcc.dg/torture/pr78305.c
> > ===================================================================
> > --- gcc/testsuite/gcc.dg/torture/pr78305.c  (revision 0)
> > +++ gcc/testsuite/gcc.dg/torture/pr78305.c  (working copy)
> > @@ -0,0 +1,14 @@
> > +/* { dg-require-effective-target int32plus } */
> > +/* { dg-do run } */
> > +
> > +int main ()
> > +{
> > +  int a = 2;
> > +  int b = 1;
> > +
> > +  int t = -1 * ( -0x40000000 * a / ( -0x20000000 + b ) )  / -1;
> > +
> > +  if (t != 4) __builtin_abort();
> > +
> > +  return 0;
> > +}
> > 
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to