aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2008-08-28 08:31:37 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2008-08-28 08:31:37 +0000
commit0b45fd7ad2610727101fd43d07cbd8db13ef171a (patch)
treef4a4e7f2ac44132dcb34b9ca2977087e5dd6f259 /gcc/fold-const.c
parent4717882f05433fbd40ad542009015ae669f1d4a6 (diff)
downloadgcc-0b45fd7ad2610727101fd43d07cbd8db13ef171a.zip
gcc-0b45fd7ad2610727101fd43d07cbd8db13ef171a.tar.gz
gcc-0b45fd7ad2610727101fd43d07cbd8db13ef171a.tar.bz2
re PR tree-optimization/37005 (GNAT Bug Box for cd2a24e.adb:37 at tree-vrp.c:392)
2008-08-28 Richard Guenther <rguenther@suse.de> PR middle-end/37005 * fold-const.c (maybe_canonicalize_comparison_1): Require undefined overflow only for canonicalizing A +- CST cmp CST. Make sure to not generate new constants that are not inside their TYPE_MIN/MAX_VALUE range. (maybe_canonicalize_comparison): Remove undefined overflow checking from here. (fold_binary): Remove now duplicate folding. From-SVN: r139702
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c56
1 files changed, 22 insertions, 34 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e6769a6..21142b8 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -8289,9 +8289,14 @@ maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
int sgn0;
bool swap = false;
- /* Match A +- CST code arg1 and CST code arg1. */
- if (!(((code0 == MINUS_EXPR
- || code0 == PLUS_EXPR)
+ /* Match A +- CST code arg1 and CST code arg1. We can change the
+ first form only if overflow is undefined. */
+ if (!((TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
+ /* In principle pointers also have undefined overflow behavior,
+ but that causes problems elsewhere. */
+ && !POINTER_TYPE_P (TREE_TYPE (arg0))
+ && (code0 == MINUS_EXPR
+ || code0 == PLUS_EXPR)
&& TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
|| code0 == INTEGER_CST))
return NULL_TREE;
@@ -8352,9 +8357,21 @@ maybe_canonicalize_comparison_1 (enum tree_code code, tree type,
*strict_overflow_p = true;
}
- /* Now build the constant reduced in magnitude. */
+ /* Now build the constant reduced in magnitude. But not if that
+ would produce one outside of its types range. */
+ if (INTEGRAL_TYPE_P (TREE_TYPE (cst0))
+ && ((sgn0 == 1
+ && TYPE_MIN_VALUE (TREE_TYPE (cst0))
+ && tree_int_cst_equal (cst0, TYPE_MIN_VALUE (TREE_TYPE (cst0))))
+ || (sgn0 == -1
+ && TYPE_MAX_VALUE (TREE_TYPE (cst0))
+ && tree_int_cst_equal (cst0, TYPE_MAX_VALUE (TREE_TYPE (cst0))))))
+ /* We cannot swap the comparison here as that would cause us to
+ endlessly recurse. */
+ return NULL_TREE;
+
t = int_const_binop (sgn0 == -1 ? PLUS_EXPR : MINUS_EXPR,
- cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
+ cst0, build_int_cst (TREE_TYPE (cst0), 1), 0);
if (code0 != INTEGER_CST)
t = fold_build2 (code0, TREE_TYPE (arg0), TREE_OPERAND (arg0, 0), t);
@@ -8380,12 +8397,6 @@ maybe_canonicalize_comparison (enum tree_code code, tree type,
const char * const warnmsg = G_("assuming signed overflow does not occur "
"when reducing constant in comparison");
- /* In principle pointers also have undefined overflow behavior,
- but that causes problems elsewhere. */
- if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
- || POINTER_TYPE_P (TREE_TYPE (arg0)))
- return NULL_TREE;
-
/* Try canonicalization by simplifying arg0. */
strict_overflow_p = false;
t = maybe_canonicalize_comparison_1 (code, type, arg0, arg1,
@@ -12424,29 +12435,6 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
}
}
- /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
- This transformation affects the cases which are handled in later
- optimizations involving comparisons with non-negative constants. */
- if (TREE_CODE (arg1) == INTEGER_CST
- && TREE_CODE (arg0) != INTEGER_CST
- && tree_int_cst_sgn (arg1) > 0)
- {
- if (code == GE_EXPR)
- {
- arg1 = const_binop (MINUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1), 0);
- return fold_build2 (GT_EXPR, type, arg0,
- fold_convert (TREE_TYPE (arg0), arg1));
- }
- if (code == LT_EXPR)
- {
- arg1 = const_binop (MINUS_EXPR, arg1,
- build_int_cst (TREE_TYPE (arg1), 1), 0);
- return fold_build2 (LE_EXPR, type, arg0,
- fold_convert (TREE_TYPE (arg0), arg1));
- }
- }
-
/* Comparisons with the highest or lowest possible integer of
the specified precision will have known values. */
{