diff options
author | Jakub Jelinek <jakub@redhat.com> | 2010-12-14 15:09:59 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2010-12-14 15:09:59 +0100 |
commit | 8236c8eb4f599f95d76aafcdc11720edbce407cf (patch) | |
tree | e408f2279c770c233318337d4a252ee4b8fb25c6 | |
parent | 2b503136079b6b526bd438b47ae6c5163942b7d0 (diff) | |
download | gcc-8236c8eb4f599f95d76aafcdc11720edbce407cf.zip gcc-8236c8eb4f599f95d76aafcdc11720edbce407cf.tar.gz gcc-8236c8eb4f599f95d76aafcdc11720edbce407cf.tar.bz2 |
re PR tree-optimization/46909 (Logical OR expressions are miscompiled)
PR tree-optimization/46909
* gimple-fold.c (and_var_with_comparison_1): Save partial
result even in the is_and case, if both partial results
are the same, return it.
(or_var_with_comparison_1): Use is_or predicate instead of
innercode == TRUTH_OR_EXPR test. Save partial result
even in the is_or case, if both partial results are the
same, return it. In the !is_or case when both partial
results are the same, return the partial result instead
of boolean_true_node.
* gcc.c-torture/execute/pr46909-1.c: New test.
* gcc.c-torture/execute/pr46909-2.c: New test.
* gcc.dg/pr46909.c: New test.
From-SVN: r167800
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/gimple-fold.c | 45 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr46909-1.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr46909-2.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr46909.c | 17 |
6 files changed, 105 insertions, 21 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c99b931..b4efa6f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2010-12-14 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/46909 + * gimple-fold.c (and_var_with_comparison_1): Save partial + result even in the is_and case, if both partial results + are the same, return it. + (or_var_with_comparison_1): Use is_or predicate instead of + innercode == TRUTH_OR_EXPR test. Save partial result + even in the is_or case, if both partial results are the + same, return it. In the !is_or case when both partial + results are the same, return the partial result instead + of boolean_true_node. + 2010-12-14 Jan Hubicka <jh@suse.cz> PR middle-end/46667 diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index ba51ee8..bf5e804 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2008,14 +2008,11 @@ and_var_with_comparison_1 (gimple stmt, /* Handle the OR case, where we are redistributing: (inner1 OR inner2) AND (op2a code2 op2b) => (t OR (inner2 AND (op2a code2 op2b))) */ - else - { - if (integer_onep (t)) - return boolean_true_node; - else - /* Save partial result for later. */ - partial = t; - } + else if (integer_onep (t)) + return boolean_true_node; + + /* Save partial result for later. */ + partial = t; } /* Compute the second partial result, (inner2 AND (op2a code op2b)) */ @@ -2036,6 +2033,10 @@ and_var_with_comparison_1 (gimple stmt, return inner1; else if (integer_zerop (t)) return boolean_false_node; + /* If both are the same, we can apply the identity + (x AND x) == x. */ + else if (partial && same_bool_result_p (t, partial)) + return t; } /* Handle the OR case. where we are redistributing: @@ -2445,7 +2446,7 @@ or_var_with_comparison_1 (gimple stmt, => (t OR inner2) If the partial result t is a constant, we win. Otherwise continue on to try reassociating with the other inner test. */ - if (innercode == TRUTH_OR_EXPR) + if (is_or) { if (integer_onep (t)) return boolean_true_node; @@ -2456,14 +2457,11 @@ or_var_with_comparison_1 (gimple stmt, /* Handle the AND case, where we are redistributing: (inner1 AND inner2) OR (op2a code2 op2b) => (t AND (inner2 OR (op2a code op2b))) */ - else - { - if (integer_zerop (t)) - return boolean_false_node; - else - /* Save partial result for later. */ - partial = t; - } + else if (integer_zerop (t)) + return boolean_false_node; + + /* Save partial result for later. */ + partial = t; } /* Compute the second partial result, (inner2 OR (op2a code op2b)) */ @@ -2477,13 +2475,18 @@ or_var_with_comparison_1 (gimple stmt, { /* Handle the OR case, where we are reassociating: (inner1 OR inner2) OR (op2a code2 op2b) - => (inner1 OR t) */ - if (innercode == TRUTH_OR_EXPR) + => (inner1 OR t) + => (t OR partial) */ + if (is_or) { if (integer_zerop (t)) return inner1; else if (integer_onep (t)) return boolean_true_node; + /* If both are the same, we can apply the identity + (x OR x) == x. */ + else if (partial && same_bool_result_p (t, partial)) + return t; } /* Handle the AND case, where we are redistributing: @@ -2500,13 +2503,13 @@ or_var_with_comparison_1 (gimple stmt, operand to the redistributed AND expression. The interesting case is when at least one is true. Or, if both are the same, we can apply the identity - (x AND x) == true. */ + (x AND x) == x. */ if (integer_onep (partial)) return t; else if (integer_onep (t)) return partial; else if (same_bool_result_p (t, partial)) - return boolean_true_node; + return t; } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 33be340..0d20e51 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-12-14 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/46909 + * gcc.c-torture/execute/pr46909-1.c: New test. + * gcc.c-torture/execute/pr46909-2.c: New test. + * gcc.dg/pr46909.c: New test. + 2010-12-14 Alexander Monakov <amonakov@ispras.ru> PR rtl-optimization/46875 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c b/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c new file mode 100644 index 0000000..c6c92fc --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/46909 */ + +extern void abort (); + +int +__attribute__ ((__noinline__)) +foo (unsigned int x) +{ + if (! (x == 4 || x == 6) || (x == 2 || x == 6)) + return 1; + return -1; +} + +int +main () +{ + int i; + for (i = -10; i < 10; i++) + if (foo (i) != 1 - 2 * (i == 4)) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c b/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c new file mode 100644 index 0000000..33da218 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/46909 */ + +extern void abort (void); + +int +__attribute__((noinline)) +foo (int x) +{ + if ((x != 0 && x != 13) || x == 5 || x == 20) + return 1; + return -1; +} + +int +main (void) +{ + int i; + for (i = -10; i < 30; i++) + if (foo (i) != 1 - 2 * (i == 0) - 2 * (i == 13)) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr46909.c b/gcc/testsuite/gcc.dg/pr46909.c new file mode 100644 index 0000000..affedab --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr46909.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/46909 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ifcombine" } */ + +extern void abort (); + +int +__attribute__ ((__noinline__)) +foo (unsigned int x) +{ + if (! (x == 4 || x == 6) || (x == 2 || x == 6)) + return 1; + return -1; +} + +/* { dg-final { scan-tree-dump "optimizing two comparisons to x_\[0-9\]+\\(D\\) != 4" "ifcombine" } } */ +/* { dg-final { cleanup-tree-dump "ifcombine" } } */ |