aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2010-12-14 15:09:59 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2010-12-14 15:09:59 +0100
commit8236c8eb4f599f95d76aafcdc11720edbce407cf (patch)
treee408f2279c770c233318337d4a252ee4b8fb25c6 /gcc/gimple-fold.c
parent2b503136079b6b526bd438b47ae6c5163942b7d0 (diff)
downloadgcc-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
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c45
1 files changed, 24 insertions, 21 deletions
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;
}
}
}