This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR78305
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 <rguenther@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 <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)