aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1996-03-25 18:48:05 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1996-03-25 18:48:05 -0500
commit65d8b1ce9fbf4b70cd210d04caf700b1506f617f (patch)
treefb1889b8ae488c5f7395eb8d4437982b7231fd95 /gcc
parentfda924283fc7d63021aa52553b6ffe10b586d42d (diff)
downloadgcc-65d8b1ce9fbf4b70cd210d04caf700b1506f617f.zip
gcc-65d8b1ce9fbf4b70cd210d04caf700b1506f617f.tar.gz
gcc-65d8b1ce9fbf4b70cd210d04caf700b1506f617f.tar.bz2
(fold, case BIT_IOR_EXPR): Recognize rotates with variable count.
From-SVN: r11614
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fold-const.c60
1 files changed, 44 insertions, 16 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5901325..2f08ead 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3901,6 +3901,9 @@ fold (expr)
case BIT_IOR_EXPR:
bit_ior:
+ {
+ register enum tree_code code0, code1;
+
if (integer_all_onesp (arg1))
return omit_one_operand (type, arg1, arg0);
if (integer_zerop (arg1))
@@ -3909,28 +3912,53 @@ fold (expr)
if (t1 != NULL_TREE)
return t1;
- /* (a << C1) | (a >> C2) if A is unsigned and C1+C2 is the size of A
+ /* (A << C1) | (A >> C2) if A is unsigned and C1+C2 is the size of A
is a rotate of A by C1 bits. */
+ /* (A << B) | (A >> (Z - B)) if A is unsigned and Z is the size of A
+ is a rotate of A by B 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)
+ code0 = TREE_CODE (arg0);
+ code1 = TREE_CODE (arg1);
+ if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
+ || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
&& 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)))
+ && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+ {
+ register tree tree01, tree11;
+ register enum tree_code code01, code11;
+
+ tree01 = TREE_OPERAND (arg0, 1);
+ tree11 = TREE_OPERAND (arg1, 1);
+ code01 = TREE_CODE (tree01);
+ code11 = TREE_CODE (tree11);
+ if (code01 == INTEGER_CST
+ && code11 == INTEGER_CST
+ && TREE_INT_CST_HIGH (tree01) == 0
+ && TREE_INT_CST_HIGH (tree11) == 0
+ && ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== 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));
+ return build (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
+ code0 == LSHIFT_EXPR ? tree01 : tree11);
+ else if (code11 == MINUS_EXPR
+ && TREE_CODE (TREE_OPERAND (tree11, 0)) == INTEGER_CST
+ && TREE_INT_CST_HIGH (TREE_OPERAND (tree11, 0)) == 0
+ && TREE_INT_CST_LOW (TREE_OPERAND (tree11, 0))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ && operand_equal_p (tree01, TREE_OPERAND (tree11, 1), 0))
+ return build (code0 == LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
+ type, TREE_OPERAND (arg0, 0), tree01);
+ else if (code01 == MINUS_EXPR
+ && TREE_CODE (TREE_OPERAND (tree01, 0)) == INTEGER_CST
+ && TREE_INT_CST_HIGH (TREE_OPERAND (tree01, 0)) == 0
+ && TREE_INT_CST_LOW (TREE_OPERAND (tree01, 0))
+ == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))
+ && operand_equal_p (tree11, TREE_OPERAND (tree01, 1), 0))
+ return build (code0 != LSHIFT_EXPR ? LROTATE_EXPR : RROTATE_EXPR,
+ type, TREE_OPERAND (arg0, 0), tree11);
+ }
goto associate;
+ }
case BIT_XOR_EXPR:
if (integer_zerop (arg1))