From 5a226e0af1d34600e38f02e3e84485db3f96b56c Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 20 Feb 2012 13:19:47 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 +++ gcc/fold-const.c | 62 +++++++------------ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.c-torture/execute/pr52286.c | 14 +++++ 4 files changed, 49 insertions(+), 39 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr52286.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ee4560ae3d0..de00a9d9307 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-02-20 Jakub Jelinek + + 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 PR target/50166 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 40a0986dda8..ef630fb0d47 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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). */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8c66e09ee71..1287d7acb53 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-02-20 Jakub Jelinek + + PR tree-optimization/52286 + * gcc.c-torture/execute/pr52286.c: New test. + 2012-02-18 Tobias Burnus PR fortran/52295 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr52286.c b/gcc/testsuite/gcc.c-torture/execute/pr52286.c new file mode 100644 index 00000000000..003406d37ee --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr52286.c @@ -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; +}