summaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-13 18:33:32 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2006-02-13 18:33:32 +0000
commit191611dd4435c700ddaf3f2256ad6727bd240224 (patch)
treed38a31a2f50f89e4589d53b8f378f0319c82ce34 /gcc/fold-const.c
parent6d7204c30d64abffbf54530960ebec6d2b222355 (diff)
downloadgcc-191611dd4435c700ddaf3f2256ad6727bd240224.tar.gz
PR middle-end/24427
* fold-const.c (fold_binary) <BIT_IOR_EXPR>: Transform (X&C1)|C2 into (X,C2) if C1 is a subset of the bits of C2. Transform (X&C1)|C2 into X|C2 if C1|C2 == ~0. Canonicalize (X&C1)|C2 as (X&(C1&~C2))|C2. <BIT_AND_EXPR>: Canonicalize (X|C1)&C2 as (X&C2)|(C1&C2). * gcc.dg/tree-ssa/andor-1.c: New test case. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@110918 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 67991076577..03c9d1c17e5 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8114,6 +8114,53 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
return omit_one_operand (type, t1, arg0);
}
+ /* Canonicalize (X & C1) | C2. */
+ if (TREE_CODE (arg0) == BIT_AND_EXPR
+ && 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);
+ 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);
+
+ /* If (C1&C2) == C1, then (X&C1)|C2 becomes (X,C2). */
+ if ((hi1 & hi2) == hi1 && (lo1 & lo2) == lo1)
+ return omit_one_operand (type, arg1, 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);
+ }
+
+ /* If (C1|C2) == ~0 then (X&C1)|C2 becomes X|C2. */
+ if ((~(hi1 | hi2) & mhi) == 0 && (~(lo1 | lo2) & mlo) == 0)
+ 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. */
+ hi1 &= mhi;
+ lo1 &= mlo;
+ if ((hi1 & ~hi2) != hi1 || (lo1 & ~lo2) != 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)),
+ arg1);
+ }
+
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
@@ -8256,6 +8303,16 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0))
return omit_one_operand (type, integer_zero_node, arg0);
+ /* Canonicalize (X | C1) & C2 as (X & C2) | (C1 & C2). */
+ if (TREE_CODE (arg0) == BIT_IOR_EXPR
+ && TREE_CODE (arg1) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
+ return fold_build2 (BIT_IOR_EXPR, type,
+ fold_build2 (BIT_AND_EXPR, type,
+ TREE_OPERAND (arg0, 0), arg1),
+ fold_build2 (BIT_AND_EXPR, type,
+ TREE_OPERAND (arg0, 1), arg1));
+
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;