aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1992-12-28 06:07:05 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1992-12-28 06:07:05 -0500
commit85d2e16cf73d8c815b73fe2d4680512a5669a768 (patch)
treec7e960f29f5b9c5572d29f4ef46058dce0140065 /gcc/fold-const.c
parent4a0094c3e9d349376b2282995fd85f53c17b2962 (diff)
downloadgcc-85d2e16cf73d8c815b73fe2d4680512a5669a768.zip
gcc-85d2e16cf73d8c815b73fe2d4680512a5669a768.tar.gz
gcc-85d2e16cf73d8c815b73fe2d4680512a5669a768.tar.bz2
(fold, case BIT_IOR_EXPR): Convert the IOR of a pair of shifts into a
rotate when it is equivalent. From-SVN: r2970
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index f7c2b8a..2ff043f 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3496,6 +3496,28 @@ fold (expr)
t1 = distribute_bit_expr (code, type, arg0, arg1);
if (t1 != NULL_TREE)
return t1;
+
+ /* (a << C1) | (a >> C2) if A is unsigned and C1+C2 is the size of A
+ is a rotate of A by C1 bits. */
+
+ if ((TREE_CODE (arg0) == RSHIFT_EXPR
+ || TREE_CODE (arg0) == LSHIFT_EXPR)
+ && (TREE_CODE (arg1) == RSHIFT_EXPR
+ || TREE_CODE (arg1) == LSHIFT_EXPR)
+ && TREE_CODE (arg0) != TREE_CODE (arg1)
+ && operand_equal_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg1,0), 0)
+ && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
+ && TREE_CODE (TREE_OPERAND (arg1, 1)) == INTEGER_CST
+ && TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == 0
+ && TREE_INT_CST_HIGH (TREE_OPERAND (arg1, 1)) == 0
+ && ((TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1))
+ + TREE_INT_CST_LOW (TREE_OPERAND (arg1, 1)))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
+ return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
+ TREE_CODE (arg0) == LSHIFT_EXPR
+ ? TREE_OPERAND (arg0, 1) : TREE_OPERAND (arg1, 1));
+
goto associate;
case BIT_XOR_EXPR: