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>
PR target/50166

View File

@ -1,7 +1,7 @@
/* Fold a constant sub-tree into a single node for C-compiler
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
2012 Free Software Foundation, Inc.
This file is part of GCC.
@ -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). */

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