diff options
author | James A. Morrison <phython@gcc.gnu.org> | 2005-06-12 08:03:23 +0000 |
---|---|---|
committer | James A. Morrison <phython@gcc.gnu.org> | 2005-06-12 08:03:23 +0000 |
commit | e3d025cb0d1ff48a9c6b34fd134350368105e695 (patch) | |
tree | 341f5a35ba0116afe7ce890b2b5c25eed5beff64 /gcc | |
parent | 4ae234b0a1972354d8f6e526cfca999a82ade2e6 (diff) | |
download | gcc-e3d025cb0d1ff48a9c6b34fd134350368105e695.zip gcc-e3d025cb0d1ff48a9c6b34fd134350368105e695.tar.gz gcc-e3d025cb0d1ff48a9c6b34fd134350368105e695.tar.bz2 |
re PR tree-optimization/14796 ([tree-ssa] combine two shifts into one)
2005-06-12 James A. Morrison <phython@gcc.gnu.org>
PR tree-optimization/14796
* fold-const.c (fold_binary): Transform (A >> C) << C into
one BIT_AND_EXPR.
<shift>: Transform (A OP c1) OP c2 into A OP (c1 + c2).
From-SVN: r100853
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/fold-const.c | 53 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr14796-1.c | 14 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr14796-2.c | 22 |
5 files changed, 101 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4a6d731..6582d71 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-06-12 James A. Morrison <phython@gcc.gnu.org> + + PR tree-optimization/14796 + * fold-const.c (fold_binary): Transform (A >> C) << C into + one BIT_AND_EXPR. + <shift>: Transform (A OP c1) OP c2 into A OP (c1 + c2). + 2005-06-11 Geoffrey Keating <geoffk@apple.com> * config/rs6000/predicates.md (reg_or_arith_cint_operand): Delete. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 96fffe9..1994410 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -8742,6 +8742,59 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1) don't try to compute it in the compiler. */ if (TREE_CODE (arg1) == INTEGER_CST && tree_int_cst_sgn (arg1) < 0) return NULL_TREE; + + /* Turn (a OP c1) OP c2 into a OP (c1+c2). */ + if (TREE_CODE (arg0) == code && host_integerp (arg1, false) + && TREE_INT_CST_LOW (arg1) < TYPE_PRECISION (type) + && host_integerp (TREE_OPERAND (arg0, 1), false) + && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < TYPE_PRECISION (type)) + { + HOST_WIDE_INT low = (TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) + + TREE_INT_CST_LOW (arg1)); + + /* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2 + being well defined. */ + if (low >= TYPE_PRECISION (type)) + { + if (code == LROTATE_EXPR || code == RROTATE_EXPR) + low = low % TYPE_PRECISION (type); + else if (TYPE_UNSIGNED (type) || code == LSHIFT_EXPR) + return build_int_cst (type, 0); + else + low = TYPE_PRECISION (type) - 1; + } + + return fold_build2 (code, type, TREE_OPERAND (arg0, 0), + build_int_cst (type, low)); + } + + /* Transform (x >> c) << c into x & (-1<<c) */ + if (code == LSHIFT_EXPR && TREE_CODE (arg0) == RSHIFT_EXPR + && host_integerp (arg1, false) + && TREE_INT_CST_LOW (arg1) < TYPE_PRECISION (type) + && host_integerp (TREE_OPERAND (arg0, 1), false) + && TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)) < TYPE_PRECISION (type)) + { + HOST_WIDE_INT low0 = TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)); + HOST_WIDE_INT low1 = TREE_INT_CST_LOW (arg1); + unsigned HOST_WIDE_INT low; + HOST_WIDE_INT high; + tree lshift; + tree arg00; + + if (low0 == low1) + { + arg00 = fold_convert (type, TREE_OPERAND (arg0, 0)); + + lshift_double (-1, -1, low0 < low1 ? low0 : low1, + TYPE_PRECISION (type), &low, &high, 1); + lshift = build_int_cst_wide (type, low, high); + + return fold_build2 (BIT_AND_EXPR, type, arg00, lshift); + } + } + + /* Rewrite an LROTATE_EXPR by a constant into an RROTATE_EXPR by a new constant. */ if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6140b21..e890f80 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2005-06-12 James A. Morrison <phython@gcc.gnu.org> + + * gcc.dg/pr14796-1.c: New. + * gcc.dg/pr14796-2.c: New. + 2005-06-11 Steven G. Kargl <kargls@comcast.net> PR fortran/17792 diff --git a/gcc/testsuite/gcc.dg/pr14796-1.c b/gcc/testsuite/gcc.dg/pr14796-1.c new file mode 100644 index 0000000..c927e2b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr14796-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +int f (int a) { + return (a << 3) << 6; +} + +int g (int b) { + return (b >> 5) << 5; +} + +/* { dg-final { scan-tree-dump "a << 9" "gimple" } } */ +/* { dg-final { scan-tree-dump "b & -32" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/pr14796-2.c b/gcc/testsuite/gcc.dg/pr14796-2.c new file mode 100644 index 0000000..de4ec27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr14796-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +int f (int a) { + return (a << 31) << 6; +} + +unsigned int g (unsigned int a) { + return (a >> 7) >> 25; +} + +int h (int b) { + return (b >> 30) >> 30; +} + +long long j (long long c) { + return (c >> 35) << 35; +} +/* { dg-final { scan-tree-dump-times "= 0" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump "b >> 31" "gimple" } } */ +/* { dg-final { scan-tree-dump "c & -34359738368" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ |