Commit 8236c8eb by Jakub Jelinek Committed by Jakub Jelinek

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
parent 2b503136
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> 2010-12-14 Jan Hubicka <jh@suse.cz>
PR middle-end/46667 PR middle-end/46667
...@@ -2008,14 +2008,11 @@ and_var_with_comparison_1 (gimple stmt, ...@@ -2008,14 +2008,11 @@ and_var_with_comparison_1 (gimple stmt,
/* Handle the OR case, where we are redistributing: /* Handle the OR case, where we are redistributing:
(inner1 OR inner2) AND (op2a code2 op2b) (inner1 OR inner2) AND (op2a code2 op2b)
=> (t OR (inner2 AND (op2a code2 op2b))) */ => (t OR (inner2 AND (op2a code2 op2b))) */
else else if (integer_onep (t))
{ return boolean_true_node;
if (integer_onep (t))
return boolean_true_node; /* Save partial result for later. */
else partial = t;
/* Save partial result for later. */
partial = t;
}
} }
/* Compute the second partial result, (inner2 AND (op2a code op2b)) */ /* Compute the second partial result, (inner2 AND (op2a code op2b)) */
...@@ -2036,6 +2033,10 @@ and_var_with_comparison_1 (gimple stmt, ...@@ -2036,6 +2033,10 @@ and_var_with_comparison_1 (gimple stmt,
return inner1; return inner1;
else if (integer_zerop (t)) else if (integer_zerop (t))
return boolean_false_node; 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: /* Handle the OR case. where we are redistributing:
...@@ -2445,7 +2446,7 @@ or_var_with_comparison_1 (gimple stmt, ...@@ -2445,7 +2446,7 @@ or_var_with_comparison_1 (gimple stmt,
=> (t OR inner2) => (t OR inner2)
If the partial result t is a constant, we win. Otherwise If the partial result t is a constant, we win. Otherwise
continue on to try reassociating with the other inner test. */ continue on to try reassociating with the other inner test. */
if (innercode == TRUTH_OR_EXPR) if (is_or)
{ {
if (integer_onep (t)) if (integer_onep (t))
return boolean_true_node; return boolean_true_node;
...@@ -2456,14 +2457,11 @@ or_var_with_comparison_1 (gimple stmt, ...@@ -2456,14 +2457,11 @@ or_var_with_comparison_1 (gimple stmt,
/* Handle the AND case, where we are redistributing: /* Handle the AND case, where we are redistributing:
(inner1 AND inner2) OR (op2a code2 op2b) (inner1 AND inner2) OR (op2a code2 op2b)
=> (t AND (inner2 OR (op2a code op2b))) */ => (t AND (inner2 OR (op2a code op2b))) */
else else if (integer_zerop (t))
{ return boolean_false_node;
if (integer_zerop (t))
return boolean_false_node; /* Save partial result for later. */
else partial = t;
/* Save partial result for later. */
partial = t;
}
} }
/* Compute the second partial result, (inner2 OR (op2a code op2b)) */ /* Compute the second partial result, (inner2 OR (op2a code op2b)) */
...@@ -2477,13 +2475,18 @@ or_var_with_comparison_1 (gimple stmt, ...@@ -2477,13 +2475,18 @@ or_var_with_comparison_1 (gimple stmt,
{ {
/* Handle the OR case, where we are reassociating: /* Handle the OR case, where we are reassociating:
(inner1 OR inner2) OR (op2a code2 op2b) (inner1 OR inner2) OR (op2a code2 op2b)
=> (inner1 OR t) */ => (inner1 OR t)
if (innercode == TRUTH_OR_EXPR) => (t OR partial) */
if (is_or)
{ {
if (integer_zerop (t)) if (integer_zerop (t))
return inner1; return inner1;
else if (integer_onep (t)) else if (integer_onep (t))
return boolean_true_node; 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: /* Handle the AND case, where we are redistributing:
...@@ -2500,13 +2503,13 @@ or_var_with_comparison_1 (gimple stmt, ...@@ -2500,13 +2503,13 @@ or_var_with_comparison_1 (gimple stmt,
operand to the redistributed AND expression. The operand to the redistributed AND expression. The
interesting case is when at least one is true. interesting case is when at least one is true.
Or, if both are the same, we can apply the identity Or, if both are the same, we can apply the identity
(x AND x) == true. */ (x AND x) == x. */
if (integer_onep (partial)) if (integer_onep (partial))
return t; return t;
else if (integer_onep (t)) else if (integer_onep (t))
return partial; return partial;
else if (same_bool_result_p (t, partial)) else if (same_bool_result_p (t, partial))
return boolean_true_node; return t;
} }
} }
} }
......
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> 2010-12-14 Alexander Monakov <amonakov@ispras.ru>
PR rtl-optimization/46875 PR rtl-optimization/46875
......
/* 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;
}
/* 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;
}
/* 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" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment