aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorDmitry Melnik <dm@ispras.ru>2010-10-20 12:26:10 +0000
committerAlexander Monakov <amonakov@gcc.gnu.org>2010-10-20 16:26:10 +0400
commit2298ade7e57440cf008e0f7a2114fe37019bc2b0 (patch)
tree9d0beb425c9bd94cb8a4f5097dae4576793c8da4 /gcc/fold-const.c
parentb9121f42a1086a219ab6312b76e920639a0de260 (diff)
downloadgcc-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.c25
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)). */