diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-04-27 07:11:44 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2018-04-27 07:11:44 +0000 |
commit | 060ade2b5c1048c0ca2b4fb3e3f3edf1ac42ba24 (patch) | |
tree | da276185063b789840f972d62b21bed67c9544de | |
parent | e44c38413f28637355fdab2041cf93f1b7ce94ae (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/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr85529-1.c | 28 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr85529-2.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr85529.c | 27 | ||||
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 68 |
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) |