summaryrefslogtreecommitdiffstats
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-09 13:29:11 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2007-02-09 13:29:11 +0000
commita9995c228c997c1440d149c0701222db187204d0 (patch)
treea7c503e98956c6e5d624c17e6ed753cc613964aa /gcc/fold-const.c
parentbbd74a204aee79bc299885935e4f43f09a0e75e9 (diff)
downloadppe42-gcc-a9995c228c997c1440d149c0701222db187204d0.tar.gz
ppe42-gcc-a9995c228c997c1440d149c0701222db187204d0.zip
2007-02-09 Zdenek Dvorak <dvorakz@suse.cz>
Richard Guenther <rguenther@suse.de> PR middle-end/23361 * fold-const.c (fold_comparison): Handle obfuscated comparisons against INT_MIN/INT_MAX. * tree-ssa-loop-ivcanon.c (remove_empty_loop): Print to dump file if a loop is removed. * gcc.dg/fold-compare-3.c: New testcase. * gcc.dg/tree-ssa/loop-24.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121742 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 0b37a0f9437..d20d78f5956 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8043,6 +8043,40 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
TREE_TYPE (arg1), const2, const1);
+
+ /* If the constant operation overflowed this can be
+ simplified as a comparison against INT_MAX/INT_MIN. */
+ if (TREE_CODE (lhs) == INTEGER_CST
+ && TREE_OVERFLOW (lhs))
+ {
+ int const1_sgn = tree_int_cst_sgn (const1);
+ enum tree_code code2 = code;
+
+ /* Get the sign of the constant on the lhs if the
+ operation were VARIABLE + CONST1. */
+ if (TREE_CODE (arg0) == MINUS_EXPR)
+ const1_sgn = -const1_sgn;
+
+ /* The sign of the constant determines if we overflowed
+ INT_MAX (const1_sgn == -1) or INT_MIN (const1_sgn == 1).
+ Canonicalize to the INT_MIN overflow by swapping the comparison
+ if necessary. */
+ if (const1_sgn == -1)
+ code2 = swap_tree_comparison (code);
+
+ /* We now can look at the canonicalized case
+ VARIABLE + 1 CODE2 INT_MIN
+ and decide on the result. */
+ if (code2 == LT_EXPR
+ || code2 == LE_EXPR
+ || code2 == EQ_EXPR)
+ return omit_one_operand (type, boolean_false_node, variable);
+ else if (code2 == NE_EXPR
+ || code2 == GE_EXPR
+ || code2 == GT_EXPR)
+ return omit_one_operand (type, boolean_true_node, variable);
+ }
+
if (TREE_CODE (lhs) == TREE_CODE (arg1)
&& (TREE_CODE (lhs) != INTEGER_CST
|| !TREE_OVERFLOW (lhs)))
OpenPOWER on IntegriCloud