re PR tree-optimization/52286 (wrong code bug)

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.

From-SVN: r184391
This commit is contained in:
Jakub Jelinek 2012-02-20 13:19:47 +01:00 committed by Jakub Jelinek
parent e992fc2e5d
commit 5a226e0af1
4 changed files with 49 additions and 39 deletions

View File

@ -1,3 +1,10 @@
2012-02-20 Jakub Jelinek <jakub@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.
2012-02-20 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> 2012-02-20 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
PR target/50166 PR target/50166

View File

@ -1,7 +1,7 @@
/* Fold a constant sub-tree into a single node for C-compiler /* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
Free Software Foundation, Inc. 2012 Free Software Foundation, Inc.
This file is part of GCC. This file is part of GCC.
@ -10959,66 +10959,50 @@ fold_binary_loc (location_t loc,
&& TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (arg1) == INTEGER_CST
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == 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; int width = TYPE_PRECISION (type), w;
hi1 = TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)); c1 = tree_to_double_int (TREE_OPERAND (arg0, 1));
lo1 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)); c2 = tree_to_double_int (arg1);
hi2 = TREE_INT_CST_HIGH (arg1);
lo2 = TREE_INT_CST_LOW (arg1);
/* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2). */ /* 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, return omit_one_operand_loc (loc, type, arg1,
TREE_OPERAND (arg0, 0)); TREE_OPERAND (arg0, 0));
if (width > HOST_BITS_PER_WIDE_INT) msk = double_int_mask (width);
{
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);
}
/* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */ /* 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, 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, /* 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 unless (C1 & ~C2) | (C2 & C3) for some C3 is a mask of some
mode which allows further optimizations. */ mode which allows further optimizations. */
hi1 &= mhi; c1 = double_int_and (c1, msk);
lo1 &= mlo; c2 = double_int_and (c2, msk);
hi2 &= mhi; c3 = double_int_and_not (c1, c2);
lo2 &= mlo;
hi3 = hi1 & ~hi2;
lo3 = lo1 & ~lo2;
for (w = BITS_PER_UNIT; for (w = BITS_PER_UNIT;
w <= width && w <= HOST_BITS_PER_WIDE_INT; w <= width && w <= HOST_BITS_PER_WIDE_INT;
w <<= 1) w <<= 1)
{ {
unsigned HOST_WIDE_INT mask unsigned HOST_WIDE_INT mask
= (unsigned HOST_WIDE_INT) -1 >> (HOST_BITS_PER_WIDE_INT - w); = (unsigned HOST_WIDE_INT) -1 >> (HOST_BITS_PER_WIDE_INT - w);
if (((lo1 | lo2) & mask) == mask if (((c1.low | c2.low) & mask) == mask
&& (lo1 & ~mask) == 0 && hi1 == 0) && (c1.low & ~mask) == 0 && c1.high == 0)
{ {
hi3 = 0; c3 = uhwi_to_double_int (mask);
lo3 = mask;
break; break;
} }
} }
if (hi3 != hi1 || lo3 != lo1) if (!double_int_equal_p (c3, c1))
return fold_build2_loc (loc, BIT_IOR_EXPR, type, return fold_build2_loc (loc, BIT_IOR_EXPR, type,
fold_build2_loc (loc, BIT_AND_EXPR, type, fold_build2_loc (loc, BIT_AND_EXPR, type,
TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 0),
build_int_cst_wide (type, double_int_to_tree (type,
lo3, hi3)), c3)),
arg1); arg1);
} }
/* (X & Y) | Y is (X, Y). */ /* (X & Y) | Y is (X, Y). */

View File

@ -1,3 +1,8 @@
2012-02-20 Jakub Jelinek <jakub@redhat.com>
PR tree-optimization/52286
* gcc.c-torture/execute/pr52286.c: New test.
2012-02-18 Tobias Burnus <burnus@net-b.de> 2012-02-18 Tobias Burnus <burnus@net-b.de>
PR fortran/52295 PR fortran/52295

View File

@ -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;
}