diff options
author | Jakub Jelinek <jakub@redhat.com> | 2007-12-05 23:24:08 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2007-12-05 23:24:08 +0100 |
commit | 517ddae96b847521c7761f74bb9ac522ed70f038 (patch) | |
tree | d91874c1661fc111f66e2b41c03740a7db664cb9 /gcc/fold-const.c | |
parent | e8608df46e1f096a942e0fff741fcdf2d9120df0 (diff) | |
download | gcc-517ddae96b847521c7761f74bb9ac522ed70f038.zip gcc-517ddae96b847521c7761f74bb9ac522ed70f038.tar.gz gcc-517ddae96b847521c7761f74bb9ac522ed70f038.tar.bz2 |
re PR middle-end/34337 (Internal error while building gtkwhiteboardc.c from pidgin 2.3.0)
PR middle-end/34337
* fold-const.c (fold_binary) <case BIT_IOR_EXPR>: Don't minimize
number of bits set in C1 if a mode mask for some mode can be used
instead.
* gcc.c-torture/execute/20071205-1.c: New test.
From-SVN: r130635
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 1502994..8519e68 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -10570,8 +10570,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) && TREE_CODE (arg1) == INTEGER_CST && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST) { - unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, mlo, mhi; - int width = TYPE_PRECISION (type); + unsigned HOST_WIDE_INT hi1, lo1, hi2, lo2, hi3, lo3, mlo, mhi; + 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); @@ -10599,16 +10599,35 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) return fold_build2 (BIT_IOR_EXPR, type, 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 + mode which allows further optimizations. */ hi1 &= mhi; lo1 &= mlo; - if ((hi1 & ~hi2) != hi1 || (lo1 & ~lo2) != lo1) + hi2 &= mhi; + lo2 &= mlo; + hi3 = hi1 & ~hi2; + lo3 = lo1 & ~lo2; + 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) + { + hi3 = 0; + lo3 = mask; + break; + } + } + if (hi3 != hi1 || lo3 != lo1) return fold_build2 (BIT_IOR_EXPR, type, fold_build2 (BIT_AND_EXPR, type, TREE_OPERAND (arg0, 0), build_int_cst_wide (type, - lo1 & ~lo2, - hi1 & ~hi2)), + lo3, hi3)), arg1); } |