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
This commit is contained in:
Jakub Jelinek 2010-12-14 15:09:59 +01:00 committed by Jakub Jelinek
parent 2b50313607
commit 8236c8eb4f
6 changed files with 105 additions and 21 deletions

View File

@ -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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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" } } */