aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-05-05 09:23:31 +0000
committerRichard Biener <rguenther@suse.de>2014-05-05 09:23:31 +0000
commit354b6cf1f10a4f8d2b5d4031c4e4bdd8c2c3532b (patch)
treef757276d245dcc7de0472ece3f970911675fca65
parentb9017f665a28f7e8da6c3d72c1a8d06117c5fda9 (diff)
2014-05-05 Richard Biener <rguenther@suse.de>
PR middle-end/61010 * fold-const.c (fold_binary_loc): Consistently avoid canonicalizing X & CST away from a CST that is the mask of a mode. * gcc.dg/torture/pr61010.c: New testcase. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@210066 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c33
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr61010.c8
4 files changed, 34 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a3cd478d5b7..18959f6eacb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2014-05-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61010
+ * fold-const.c (fold_binary_loc): Consistently avoid
+ canonicalizing X & CST away from a CST that is the mask
+ of a mode.
+
2014-05-05 Jan-Benedict Glaw <jbglaw@lug-owl.de>
* config/picochip/picochip-protos.h (picochip_regno_nregs): Change
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5c2bf256c2a..65051a12c2a 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -11426,7 +11426,6 @@ fold_binary_loc (location_t loc,
{
double_int c1, c2, c3, msk;
int width = TYPE_PRECISION (type), w;
- bool try_simplify = true;
c1 = tree_to_double_int (TREE_OPERAND (arg0, 1));
c2 = tree_to_double_int (arg1);
@@ -11463,20 +11462,7 @@ fold_binary_loc (location_t loc,
}
}
- /* If X is a tree of the form (Y * K1) & K2, this might conflict
- with that optimization from the BIT_AND_EXPR optimizations.
- This could end up in an infinite recursion. */
- if (TREE_CODE (TREE_OPERAND (arg0, 0)) == MULT_EXPR
- && TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1))
- == INTEGER_CST)
- {
- tree t = TREE_OPERAND (TREE_OPERAND (arg0, 0), 1);
- double_int masked = mask_with_tz (type, c3, tree_to_double_int (t));
-
- try_simplify = (masked != c1);
- }
-
- if (try_simplify && c3 != c1)
+ if (c3 != c1)
return fold_build2_loc (loc, BIT_IOR_EXPR, type,
fold_build2_loc (loc, BIT_AND_EXPR, type,
TREE_OPERAND (arg0, 0),
@@ -11866,16 +11852,25 @@ fold_binary_loc (location_t loc,
&& TREE_CODE (arg0) == MULT_EXPR
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
{
+ double_int darg1 = tree_to_double_int (arg1);
double_int masked
- = mask_with_tz (type, tree_to_double_int (arg1),
+ = mask_with_tz (type, darg1,
tree_to_double_int (TREE_OPERAND (arg0, 1)));
if (masked.is_zero ())
return omit_two_operands_loc (loc, type, build_zero_cst (type),
arg0, arg1);
- else if (masked != tree_to_double_int (arg1))
- return fold_build2_loc (loc, code, type, op0,
- double_int_to_tree (type, masked));
+ else if (masked != darg1)
+ {
+ /* Avoid the transform if arg1 is a mask of some
+ mode which allows further optimizations. */
+ int pop = darg1.popcount ();
+ if (!(pop >= BITS_PER_UNIT
+ && exact_log2 (pop) != -1
+ && double_int::mask (pop) == darg1))
+ return fold_build2_loc (loc, code, type, op0,
+ double_int_to_tree (type, masked));
+ }
}
/* For constants M and N, if M == (1LL << cst) - 1 && (N & M) == M,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ce105724f69..1c9d4d31c66 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2014-05-05 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/61010
+ * gcc.dg/torture/pr61010.c: New testcase.
+
2014-05-05 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* gcc.target/s390/leaf-profile.c: New testcase.
diff --git a/gcc/testsuite/gcc.dg/torture/pr61010.c b/gcc/testsuite/gcc.dg/torture/pr61010.c
new file mode 100644
index 00000000000..ed5653982cb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr61010.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+int main (void)
+{
+ int a = 0;
+ unsigned b = (a * 64 & 192) | 63U;
+ return 0;
+}