From 8236c8eb4f599f95d76aafcdc11720edbce407cf Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 14 Dec 2010 15:09:59 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 13 ++++++ gcc/gimple-fold.c | 45 ++++++++++--------- gcc/testsuite/ChangeLog | 7 +++ .../gcc.c-torture/execute/pr46909-1.c | 22 +++++++++ .../gcc.c-torture/execute/pr46909-2.c | 22 +++++++++ gcc/testsuite/gcc.dg/pr46909.c | 17 +++++++ 6 files changed, 105 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr46909-1.c create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr46909-2.c create mode 100644 gcc/testsuite/gcc.dg/pr46909.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c99b9314785..b4efa6fe7ac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2010-12-14 Jakub Jelinek + + 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 PR middle-end/46667 diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index ba51ee8d853..bf5e80449de 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 33be340e9bb..0d20e5127f9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-12-14 Jakub Jelinek + + 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 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 00000000000..c6c92fcbb1e --- /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 00000000000..33da2189c44 --- /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 00000000000..affedab8676 --- /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" } } */ -- 2.30.2