diff options
author | Jeff Law <law@redhat.com> | 2016-01-18 23:43:54 -0700 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2016-01-18 23:43:54 -0700 |
commit | 2bedb645f2aef48d7cbb70bf5ddb8bf0a4342019 (patch) | |
tree | 01f06939e38904f487d71de67d847c5e7cc30273 | |
parent | 17c15cb932563bb814865c39abc2b952c7707f79 (diff) | |
download | gcc-2bedb645f2aef48d7cbb70bf5ddb8bf0a4342019.zip gcc-2bedb645f2aef48d7cbb70bf5ddb8bf0a4342019.tar.gz gcc-2bedb645f2aef48d7cbb70bf5ddb8bf0a4342019.tar.bz2 |
re PR tree-optimization/69320 (wrong code generation at -O2 and higher)
2016-01-18 Jeff Law <law@redhat.com>
PR tree-optimization/69320
* tree-ssa-dom.c (record_edge_info): For comparisons against a boolean
ranged object, do nothing if the RHS constant is not [0..1].
(optimize_stmt): Comparing a boolean ranged object against a
constant outside [0..1] results in a compile-time constant.
* tree-ssanames.c (ssa_name_has_boolean_range): Remove unnecessary
test.
PR tree-optimization/69320
* gcc.c-torture/pr69320-1.c: New test.
* gcc.c-torture/pr69320-2.c: New test.
* gcc.c-torture/pr69320-3.c: New test.
* gcc.c-torture/pr69320-4.c: New test.
From-SVN: r232548
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr69320-1.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr69320-2.c | 35 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr69320-3.c | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr69320-4.c | 18 | ||||
-rw-r--r-- | gcc/tree-ssa-dom.c | 38 | ||||
-rw-r--r-- | gcc/tree-ssanames.c | 3 |
8 files changed, 144 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index de6e1ed..b39f864 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2016-01-18 Jeff Law <law@redhat.com> + + PR tree-optimization/69320 + * tree-ssa-dom.c (record_edge_info): For comparisons against a boolean + ranged object, do nothing if the RHS constant is not [0..1]. + (optimize_stmt): Comparing a boolean ranged object against a + constant outside [0..1] results in a compile-time constant. + + * tree-ssanames.c (ssa_name_has_boolean_range): Remove unnecessary + test. + 2016-01-18 Sandra Loosemore <sandra@codesourcery.com> * doc/invoke.texi (Invoking GCC): Add new section to menu. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9245b50..fc476b9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2016-01-15 Jeff Law <law@redhat.com> + + PR tree-optimization/69320 + * gcc.c-torture/pr69320-1.c: New test. + * gcc.c-torture/pr69320-2.c: New test. + * gcc.c-torture/pr69320-3.c: New test. + * gcc.c-torture/pr69320-4.c: New test. + 2016-01-18 Patrick Palka <ppalka@gcc.gnu.org> PR c++/11858 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-1.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-1.c new file mode 100644 index 0000000..0aba2fc --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-1.c @@ -0,0 +1,20 @@ +#include <stdlib.h> +int a, b, d, f; +char c; +static int *e = &d; +int main() { + int g = -1L; + *e = g; + c = 4; + for (; c >= 14; c++) + *e = 1; + f = a == 0; + *e ^= f; + int h = ~d; + if (d) + b = h; + if (h) + exit (0); + abort (); +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-2.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-2.c new file mode 100644 index 0000000..b85672c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-2.c @@ -0,0 +1,35 @@ + +#include <stdlib.h> + +int a, *c, d, e, g, f; +short b; + +int +fn1 () +{ + int h = d != 10; + if (h > g) + asm volatile ("" : : : "memory"); + if (h == 10) + { + int *i = 0; + a = 0; + for (; a < 7; a++) + for (; *i;) + ; + } + else + { + b = e / h; + return f; + } + c = &h; + abort (); +} + +int +main () +{ + fn1 (); + exit (0); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-3.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-3.c new file mode 100644 index 0000000..213c93f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-3.c @@ -0,0 +1,17 @@ +#include <stdlib.h> + +static int a[40] = {7, 5, 3, 3, 0, 0, 3}; +short b; +int c = 5; +int main() { + b = 0; + for (; b <= 3; b++) + if (a[b + 6] ^ (0 || c)) + ; + else + break; + if (b != 4) + abort (); + exit (0); +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/pr69320-4.c b/gcc/testsuite/gcc.c-torture/execute/pr69320-4.c new file mode 100644 index 0000000..356cd0f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr69320-4.c @@ -0,0 +1,18 @@ +#include <stdlib.h> + +int a; +char b, d; +short c; +short fn1(int p1, int p2) { return p2 >= 2 ? p1 : p1 > p2; } + +int main() { + int *e = &a, *f = &a; + b = 1; + for (; b <= 9; b++) { + c = *e != 5 || d; + *f = fn1(c || b, a); + } + if ((long long) a != 1) + abort (); + exit (0); +} diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 8298637..3eeaa9c 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -387,11 +387,16 @@ record_edge_info (basic_block bb) /* Special case comparing booleans against a constant as we know the value of OP0 on both arms of the branch. i.e., we - can record an equivalence for OP0 rather than COND. */ - if ((code == EQ_EXPR || code == NE_EXPR) - && TREE_CODE (op0) == SSA_NAME + can record an equivalence for OP0 rather than COND. + + However, don't do this if the constant isn't zero or one. + Such conditionals will get optimized more thoroughly during + the domwalk. */ + if ((code == EQ_EXPR || code == NE_EXPR) + && TREE_CODE (op0) == SSA_NAME && ssa_name_has_boolean_range (op0) - && is_gimple_min_invariant (op1)) + && is_gimple_min_invariant (op1) + && (integer_zerop (op1) || integer_onep (op1))) { tree true_val = constant_boolean_node (true, TREE_TYPE (op0)); tree false_val = constant_boolean_node (false, TREE_TYPE (op0)); @@ -1828,6 +1833,31 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si, } } + if (gimple_code (stmt) == GIMPLE_COND) + { + tree lhs = gimple_cond_lhs (stmt); + tree rhs = gimple_cond_rhs (stmt); + + /* If the LHS has a range [0..1] and the RHS has a range ~[0..1], + then this conditional is computable at compile time. We can just + shove either 0 or 1 into the LHS, mark the statement as modified + and all the right things will just happen below. + + Note this would apply to any case where LHS has a range + narrower than its type implies and RHS is outside that + narrower range. Future work. */ + if (TREE_CODE (lhs) == SSA_NAME + && ssa_name_has_boolean_range (lhs) + && TREE_CODE (rhs) == INTEGER_CST + && ! (integer_zerop (rhs) || integer_onep (rhs))) + { + gimple_cond_set_lhs (as_a <gcond *> (stmt), + fold_convert (TREE_TYPE (lhs), + integer_zero_node)); + gimple_set_modified (stmt, true); + } + } + update_stmt_if_modified (stmt); eliminate_redundant_computations (&si, const_and_copies, avail_exprs_stack); diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index b6f72e2..ed87f3e 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -437,8 +437,7 @@ ssa_name_has_boolean_range (tree op) only takes on values [0..1] as determined by VRP analysis. */ if (INTEGRAL_TYPE_P (TREE_TYPE (op)) - && (TYPE_PRECISION (TREE_TYPE (op)) > 1 - || TYPE_UNSIGNED (TREE_TYPE (op))) + && (TYPE_PRECISION (TREE_TYPE (op)) > 1) && wi::eq_p (get_nonzero_bits (op), 1)) return true; |