aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2018-04-27 07:11:44 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2018-04-27 07:11:44 +0000
commit060ade2b5c1048c0ca2b4fb3e3f3edf1ac42ba24 (patch)
treeda276185063b789840f972d62b21bed67c9544de
parente44c38413f28637355fdab2041cf93f1b7ce94ae (diff)
PR tree-optimization/85529
* tree-ssa-reassoc.c (optimize_range_tests_var_bound): Add FIRST_BB argument. Don't call get_nonzero_bits if opcode is ERROR_MARK_NODE, rhs2 def stmt's bb is dominated by first_bb and it isn't an obvious zero extension or masking of the MSB bit. (optimize_range_tests): Add FIRST_BB argument, pass it through to optimize_range_tests_var_bound. (maybe_optimize_range_tests, reassociate_bb): Adjust optimize_range_tests callers. * gcc.c-torture/execute/pr85529-1.c: New test. * gcc.c-torture/execute/pr85529-2.c: New test. * gcc.dg/pr85529.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-8-branch@259697 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr85529-1.c28
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr85529-2.c25
-rw-r--r--gcc/testsuite/gcc.dg/pr85529.c27
-rw-r--r--gcc/tree-ssa-reassoc.c68
6 files changed, 161 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6520a69f9e4..b862fcddbca 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2018-04-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/85529
+ * tree-ssa-reassoc.c (optimize_range_tests_var_bound): Add FIRST_BB
+ argument. Don't call get_nonzero_bits if opcode is ERROR_MARK_NODE,
+ rhs2 def stmt's bb is dominated by first_bb and it isn't an obvious
+ zero extension or masking of the MSB bit.
+ (optimize_range_tests): Add FIRST_BB argument, pass it through
+ to optimize_range_tests_var_bound.
+ (maybe_optimize_range_tests, reassociate_bb): Adjust
+ optimize_range_tests callers.
+
2018-04-26 Richard Biener <rguenther@suse.de>
Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 24e338e7d0a..8b5cd7311db 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2018-04-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/85529
+ * gcc.c-torture/execute/pr85529-1.c: New test.
+ * gcc.c-torture/execute/pr85529-2.c: New test.
+ * gcc.dg/pr85529.c: New test.
+
2018-04-25 H.J. Lu <hongjiu.lu@intel.com>
Backport from mainline
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr85529-1.c b/gcc/testsuite/gcc.c-torture/execute/pr85529-1.c
new file mode 100644
index 00000000000..83d5cdd997e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr85529-1.c
@@ -0,0 +1,28 @@
+/* PR tree-optimization/85529 */
+
+struct S { int a; };
+
+int b, c = 1, d, e, f;
+static int g;
+volatile struct S s;
+
+signed char
+foo (signed char i, int j)
+{
+ return i < 0 ? i : i << j;
+}
+
+int
+main ()
+{
+ signed char k = -83;
+ if (!d)
+ goto L;
+ k = e || f;
+L:
+ for (; b < 1; b++)
+ s.a != (k < foo (k, 2) && (c = k = g));
+ if (c != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr85529-2.c b/gcc/testsuite/gcc.c-torture/execute/pr85529-2.c
new file mode 100644
index 00000000000..5de30844c2f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr85529-2.c
@@ -0,0 +1,25 @@
+/* PR tree-optimization/85529 */
+
+__attribute__((noipa)) int
+foo (int x)
+{
+ x &= 63;
+ x -= 50;
+ x |= 1;
+ if (x < 0)
+ return 1;
+ int y = x >> 2;
+ if (x >= y)
+ return 1;
+ return 0;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 63; i++)
+ if (foo (i) != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr85529.c b/gcc/testsuite/gcc.dg/pr85529.c
new file mode 100644
index 00000000000..0b732284749
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr85529.c
@@ -0,0 +1,27 @@
+/* PR tree-optimization/85529 */
+/* { dg-do run } */
+/* { dg-options "-O2 -fno-ssa-phiopt" } */
+
+__attribute__((noinline, noclone)) int
+foo (int x)
+{
+ x &= 31;
+ x -= 25;
+ x *= 2;
+ if (x < 0)
+ return 1;
+ int y = x >> 2;
+ if (x >= y)
+ return 1;
+ return 0;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 63; i++)
+ if (foo (i) != 1)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 0e59bb595ea..38bae77ddbc 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -3035,7 +3035,8 @@ optimize_range_tests_cmp_bitwise (enum tree_code opcode, int first, int length,
static bool
optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
vec<operand_entry *> *ops,
- struct range_entry *ranges)
+ struct range_entry *ranges,
+ basic_block first_bb)
{
int i;
bool any_changes = false;
@@ -3143,6 +3144,60 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
if (idx == NULL)
continue;
+ /* maybe_optimize_range_tests allows statements without side-effects
+ in the basic blocks as long as they are consumed in the same bb.
+ Make sure rhs2's def stmt is not among them, otherwise we can't
+ use safely get_nonzero_bits on it. E.g. in:
+ # RANGE [-83, 1] NONZERO 173
+ # k_32 = PHI <k_47(13), k_12(9)>
+ ...
+ if (k_32 >= 0)
+ goto <bb 5>; [26.46%]
+ else
+ goto <bb 9>; [73.54%]
+
+ <bb 5> [local count: 140323371]:
+ # RANGE [0, 1] NONZERO 1
+ _5 = (int) k_32;
+ # RANGE [0, 4] NONZERO 4
+ _21 = _5 << 2;
+ # RANGE [0, 4] NONZERO 4
+ iftmp.0_44 = (char) _21;
+ if (k_32 < iftmp.0_44)
+ goto <bb 6>; [84.48%]
+ else
+ goto <bb 9>; [15.52%]
+ the ranges on _5/_21/iftmp.0_44 are flow sensitive, assume that
+ k_32 >= 0. If we'd optimize k_32 >= 0 to true and k_32 < iftmp.0_44
+ to (unsigned) k_32 < (unsigned) iftmp.0_44, then we would execute
+ those stmts even for negative k_32 and the value ranges would be no
+ longer guaranteed and so the optimization would be invalid. */
+ if (opcode == ERROR_MARK)
+ {
+ gimple *g = SSA_NAME_DEF_STMT (rhs2);
+ basic_block bb2 = gimple_bb (g);
+ if (bb2
+ && bb2 != first_bb
+ && dominated_by_p (CDI_DOMINATORS, bb2, first_bb))
+ {
+ /* As an exception, handle a few common cases. */
+ if (gimple_assign_cast_p (g)
+ && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (g)))
+ && TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)))
+ && (TYPE_PRECISION (TREE_TYPE (rhs2))
+ > TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (g)))))
+ /* Zero-extension is always ok. */ ;
+ else if (is_gimple_assign (g)
+ && gimple_assign_rhs_code (g) == BIT_AND_EXPR
+ && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
+ && !wi::neg_p (wi::to_wide (gimple_assign_rhs2 (g))))
+ /* Masking with INTEGER_CST with MSB clear is always ok
+ too. */ ;
+ else
+ continue;
+ }
+ }
+
wide_int nz = get_nonzero_bits (rhs2);
if (wi::neg_p (nz))
continue;
@@ -3269,11 +3324,12 @@ optimize_range_tests_var_bound (enum tree_code opcode, int first, int length,
maybe_optimize_range_tests for inter-bb range optimization.
In that case if oe->op is NULL, oe->id is bb->index whose
GIMPLE_COND is && or ||ed into the test, and oe->rank says
- the actual opcode. */
+ the actual opcode.
+ FIRST_BB is the first basic block if OPCODE is ERROR_MARK. */
static bool
optimize_range_tests (enum tree_code opcode,
- vec<operand_entry *> *ops)
+ vec<operand_entry *> *ops, basic_block first_bb)
{
unsigned int length = ops->length (), i, j, first;
operand_entry *oe;
@@ -3353,7 +3409,7 @@ optimize_range_tests (enum tree_code opcode,
any_changes |= optimize_range_tests_cmp_bitwise (opcode, first, length,
ops, ranges);
any_changes |= optimize_range_tests_var_bound (opcode, first, length, ops,
- ranges);
+ ranges, first_bb);
if (any_changes && opcode != ERROR_MARK)
{
@@ -4100,7 +4156,7 @@ maybe_optimize_range_tests (gimple *stmt)
break;
}
if (ops.length () > 1)
- any_changes = optimize_range_tests (ERROR_MARK, &ops);
+ any_changes = optimize_range_tests (ERROR_MARK, &ops, first_bb);
if (any_changes)
{
unsigned int idx, max_idx = 0;
@@ -5855,7 +5911,7 @@ reassociate_bb (basic_block bb)
if (is_vector)
optimize_vec_cond_expr (rhs_code, &ops);
else
- optimize_range_tests (rhs_code, &ops);
+ optimize_range_tests (rhs_code, &ops, NULL);
}
if (rhs_code == MULT_EXPR && !is_vector)