diff options
author | Dmitry Melnik <dm@ispras.ru> | 2010-10-20 12:26:10 +0000 |
---|---|---|
committer | Alexander Monakov <amonakov@gcc.gnu.org> | 2010-10-20 16:26:10 +0400 |
commit | 2298ade7e57440cf008e0f7a2114fe37019bc2b0 (patch) | |
tree | 9d0beb425c9bd94cb8a4f5097dae4576793c8da4 /gcc/fold-const.c | |
parent | b9121f42a1086a219ab6312b76e920639a0de260 (diff) | |
download | gcc-2298ade7e57440cf008e0f7a2114fe37019bc2b0.zip gcc-2298ade7e57440cf008e0f7a2114fe37019bc2b0.tar.gz gcc-2298ade7e57440cf008e0f7a2114fe37019bc2b0.tar.bz2 |
fold-const.c (fold_binary_loc): New transformation.
2010-10-20 Dmitry Melnik <dm@ispras.ru>
gcc/
* fold-const.c (fold_binary_loc): New transformation.
gcc/testsuite/
* gcc.dg/20101013-1.c: New test.
From-SVN: r165720
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 808f491..decb0fb 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11599,6 +11599,31 @@ fold_binary_loc (location_t loc, return NULL_TREE; case TRUNC_DIV_EXPR: + /* Optimize (X & (-A)) / A where A is a power of 2, + to X >> log2(A) */ + if (TREE_CODE (arg0) == BIT_AND_EXPR + && !TYPE_UNSIGNED (type) && TREE_CODE (arg1) == INTEGER_CST + && integer_pow2p (arg1) && tree_int_cst_sgn (arg1) > 0) + { + tree sum = fold_binary_loc (loc, PLUS_EXPR, TREE_TYPE (arg1), + arg1, TREE_OPERAND (arg0, 1)); + if (sum && integer_zerop (sum)) { + unsigned long pow2; + + if (TREE_INT_CST_LOW (arg1)) + pow2 = exact_log2 (TREE_INT_CST_LOW (arg1)); + else + pow2 = exact_log2 (TREE_INT_CST_HIGH (arg1)) + + HOST_BITS_PER_WIDE_INT; + + return fold_build2_loc (loc, RSHIFT_EXPR, type, + TREE_OPERAND (arg0, 0), + build_int_cst (NULL_TREE, pow2)); + } + } + + /* Fall thru */ + case FLOOR_DIV_EXPR: /* Simplify A / (B << N) where A and B are positive and B is a power of 2, to A >> (N + log2(B)). */ |