On Fri, Feb 17, 2012 at 2:50 PM, Jakub Jelinek <ja...@redhat.com> wrote: > Hi! > > The following testcase is miscompiled (by CCP, or, if -fno-tree-ccp, > by VRP), because the (X & C1) | C2 folding changes the C1 constant > into an integer constant with most significant bit set, but not > sign-extended into the double_int. Fixed by using double_int_to_tree > which extends it properly, instead of build_int_cst_wide. > Instead of creating a double_int from the hi3/lo3 pair I've changed > the code to actually work on double_ints. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
Ok. Thanks, Richard. > 2012-02-17 Jakub Jelinek <ja...@redhat.com> > > PR tree-optimization/52286 > * fold-const.c (fold_binary_loc): For (X & C1) | C2 > optimization use double_int_to_tree instead of build_int_cst_wide, > rewrite to use double_int vars. > > * gcc.c-torture/execute/pr52286.c: New test. > > --- gcc/fold-const.c.jj 2012-02-16 20:04:34.000000000 +0100 > +++ gcc/fold-const.c 2012-02-17 12:05:46.559700551 +0100 > @@ -10959,66 +10959,50 @@ fold_binary_loc (location_t loc, > && TREE_CODE (arg1) == INTEGER_CST > && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) > { > - unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, hi3, lo3, mlo, mhi; > + double_int c1, c2, c3, msk; > int width = TYPE_PRECISION (type), w; > - hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)); > - lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)); > - hi2 = TREE_INT_CST_HIGH (arg1); > - lo2 = TREE_INT_CST_LOW (arg1); > + c1 = tree_to_double_int (TREE_OPERAND (arg0, 1)); > + c2 = tree_to_double_int (arg1); > > /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2). */ > - if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1) > + if (double_int_equal_p (double_int_and (c1, c2), c1)) > return omit_one_operand_loc (loc, type, arg1, > - TREE_OPERAND (arg0, 0)); > + TREE_OPERAND (arg0, 0)); > > - if (width > HOST_BITS_PER_WIDE_INT) > - { > - mhi = (unsigned HOST_WIDE_INT) -1 > - >> (2 * HOST_BITS_PER_WIDE_INT - width); > - mlo = -1; > - } > - else > - { > - mhi = 0; > - mlo = (unsigned HOST_WIDE_INT) -1 > - >> (HOST_BITS_PER_WIDE_INT - width); > - } > + msk = double_int_mask (width); > > /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */ > - if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0) > + if (double_int_zero_p (double_int_and_not (msk, > + double_int_ior (c1, > c2)))) > return fold_build2_loc (loc, BIT_IOR_EXPR, type, > - TREE_OPERAND (arg0, 0), arg1); > + TREE_OPERAND (arg0, 0), arg1); > > /* Minimize the number of bits set in C1, i.e. C1 := C1 & ~C2, > unless (C1 & ~C2) | (C2 & C3) for some C3 is a mask of some > mode which allows further optimizations. */ > - hi1 &= mhi; > - lo1 &= mlo; > - hi2 &= mhi; > - lo2 &= mlo; > - hi3 = hi1 & ~hi2; > - lo3 = lo1 & ~lo2; > + c1 = double_int_and (c1, msk); > + c2 = double_int_and (c2, msk); > + c3 = double_int_and_not (c1, c2); > for (w = BITS_PER_UNIT; > w <= width && w <= HOST_BITS_PER_WIDE_INT; > w <<= 1) > { > unsigned HOST_WIDE_INT mask > = (unsigned HOST_WIDE_INT) -1 >> (HOST_BITS_PER_WIDE_INT - w); > - if (((lo1 | lo2) & mask) == mask > - && (lo1 & ~mask) == 0 && hi1 == 0) > + if (((c1.low | c2.low) & mask) == mask > + && (c1.low & ~mask) == 0 && c1.high == 0) > { > - hi3 = 0; > - lo3 = mask; > + c3 = uhwi_to_double_int (mask); > break; > } > } > - if (hi3 != hi1 || lo3 != lo1) > + if (!double_int_equal_p (c3, c1)) > return fold_build2_loc (loc, BIT_IOR_EXPR, type, > - fold_build2_loc (loc, BIT_AND_EXPR, type, > - TREE_OPERAND (arg0, 0), > - build_int_cst_wide (type, > - lo3, hi3)), > - arg1); > + fold_build2_loc (loc, BIT_AND_EXPR, type, > + TREE_OPERAND (arg0, 0), > + double_int_to_tree (type, > + c3)), > + arg1); > } > > /* (X & Y) | Y is (X, Y). */ > --- gcc/testsuite/gcc.c-torture/execute/pr52286.c.jj 2012-02-17 > 12:09:41.131621700 +0100 > +++ gcc/testsuite/gcc.c-torture/execute/pr52286.c 2012-02-17 > 12:09:22.000000000 +0100 > @@ -0,0 +1,14 @@ > +/* PR tree-optimization/52286 */ > + > +extern void abort (void); > + > +int > +main () > +{ > + int a, b; > + asm ("" : "=r" (a) : "0" (0)); > + b = (~a | 1) & -2038094497; > + if (b >= 0) > + abort (); > + return 0; > +} > > Jakub