2010-12-14 Sandra Loosemore Backport from mainline: 2010-12-14 Jakub Jelinek PR tree-optimization/46909 gcc/ * tree-ssa-ccp.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/testsuite/ * gcc.c-torture/execute/pr46909-1.c: New test. * gcc.c-torture/execute/pr46909-2.c: New test. * gcc.dg/pr46909.c: New test. === added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-1.c' --- old/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c 1970-01-01 00:00:00 +0000 +++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c 2011-01-05 11:27:00 +0000 @@ -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; +} === added file 'gcc/testsuite/gcc.c-torture/execute/pr46909-2.c' --- old/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c 1970-01-01 00:00:00 +0000 +++ new/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c 2011-01-05 11:27:00 +0000 @@ -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; +} === added file 'gcc/testsuite/gcc.dg/pr46909.c' --- old/gcc/testsuite/gcc.dg/pr46909.c 1970-01-01 00:00:00 +0000 +++ new/gcc/testsuite/gcc.dg/pr46909.c 2011-01-05 11:27:00 +0000 @@ -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" } } */ === modified file 'gcc/tree-ssa-ccp.c' --- old/gcc/tree-ssa-ccp.c 2010-09-16 09:15:46 +0000 +++ new/gcc/tree-ssa-ccp.c 2011-01-05 11:27:00 +0000 @@ -3508,14 +3508,11 @@ /* 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)) */ @@ -3536,6 +3533,10 @@ 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: @@ -3945,7 +3946,7 @@ => (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; @@ -3956,14 +3957,11 @@ /* 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)) */ @@ -3977,13 +3975,18 @@ { /* 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: @@ -4000,13 +4003,13 @@ 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; } } }