* common.opt: Add fstrict-overflow.
* opts.c (decode_options): Set flag_strict_overflow if -O2.
* flags.h (TYPE_OVERFLOW_WRAPS): Define.
(TYPE_OVERFLOW_UNDEFINED): Define.
(TYPE_OVERFLOW_TRAPS): Define. This replaces TYPE_TRAP_SIGNED.
Replace all uses.
* tree.h (TYPE_TRAP_SIGNED): Don't define.
* fold-const.c (negate_expr_p): Use TYPE_OVERFLOW_UNDEFINED.
(fold_negate_expr): Likewise.
(make_range): Likewise.
(extract_muldiv_1): Likewise.
(maybe_canonicalize_comparison): Likewise.
(fold_comparison): Likewise.
(fold_binary): Likewise.
(tree_expr_nonnegative_p): Likewise.
(tree_expr_nonzero_p): Likewise.
* tree-vrp.c (compare_values): Likewise.
(extract_range_from_binary_expr): Likewise.
(extract_range_from_unary_expr): Likewise.
* tree-ssa-loop-niter.c (infer_loop_bounds_from_signedness):
Likewise.
(nowrap_type_p): Likewise.
* tree-scalar-evolution.c (simple_iv): Likewise.
* fold-const.c (negate_expr_p): Use TYPE_OVERFLOW_WRAPS.
(build_range_check): Likewise.
(extract_muldiv_1): Likewise.
(fold_comparison): Likewise.
* tree-vrp.c (vrp_int_const_binop): Likewise.
(extract_range_from_unary_expr): Likewise.
* convert.c (convert_to_integer): Likewise.
* fold-const.c (fold_negate_expr): Use TYPE_OVERFLOW_TRAPS.
(fold_comparison): Likewise.
(fold_binary): Likewise.
* optabs.c (optab_for_tree_code): Likewise.
* tree-vectorizer.c (vect_is_simple_reduction): Likewise.
* simplify-rtx.c (simplify_const_relational_operation): Check
flag_strict_overflow and flag_trapv.
(simplify_const_relational_operation): Likewise.
* doc/invoke.texi (Option Summary): Mention -fstrict-overflow.
(Optimize Options): Add -fstrict-overflow to -O2 list. Document
-fstrict-overflow.
testsuite/:
* gcc.dg/strict-overflow-1.c: New test.
* gcc.dg/no-strict-overflow-1.c: New test.
* gcc.dg/strict-overflow-2.c: New test.
* gcc.dg/no-strict-overflow-2.c: New test.
* gcc.dg/strict-overflow-3.c: New test.
* gcc.dg/no-strict-overflow-3.c: New test.
* gcc.dg/strict-overflow-4.c: New test.
* gcc.dg/no-strict-overflow-4.c: New test.
* gcc.dg/fold-mod-1.c: Add -fstrict-overflow option.
* gcc.dg/pr15784-1.c: Likewise.
* gcc.dg/pr20922-1.c: Likewise.
* gcc.dg/pr20922-3.c: Likewise.
* gcc.dg/pr20922-4.c: Likewise.
* gcc.dg/pr20922-6.c: Likewise.
* gcc.dg/compare-4.c: Likewise.
* gcc.dg/torture/pr26898-1.c: Likewise.
* gcc.dg/tree-ssa/divide-1.c: Likewise.
* gcc.dg/tree-ssa/divide-2.c: Likewise.
* gcc.dg/tree-ssa/divide-3.c: Likewise.
* gcc.dg/tree-ssa/divide-4.c: Likewise.
* gcc.dg/tree-ssa/pr14490-1.c: Likewise.
* gcc.dg/tree-ssa/pr14490-3.c: Likewise.
* gcc.dg/tree-ssa/pr21082.c: Likewise.
* gcc.dg/tree-ssa/pr26899.c: Likewise.
* g++.dg/tree-ssa/pr21082.C: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121254
138bc75d-0d04-0410-961f-
82ee72b054a4
+2007-01-27 Ian Lance Taylor <iant@google.com>
+
+ * common.opt: Add fstrict-overflow.
+ * opts.c (decode_options): Set flag_strict_overflow if -O2.
+ * flags.h (TYPE_OVERFLOW_WRAPS): Define.
+ (TYPE_OVERFLOW_UNDEFINED): Define.
+ (TYPE_OVERFLOW_TRAPS): Define. This replaces TYPE_TRAP_SIGNED.
+ Replace all uses.
+ * tree.h (TYPE_TRAP_SIGNED): Don't define.
+ * fold-const.c (negate_expr_p): Use TYPE_OVERFLOW_UNDEFINED.
+ (fold_negate_expr): Likewise.
+ (make_range): Likewise.
+ (extract_muldiv_1): Likewise.
+ (maybe_canonicalize_comparison): Likewise.
+ (fold_comparison): Likewise.
+ (fold_binary): Likewise.
+ (tree_expr_nonnegative_p): Likewise.
+ (tree_expr_nonzero_p): Likewise.
+ * tree-vrp.c (compare_values): Likewise.
+ (extract_range_from_binary_expr): Likewise.
+ (extract_range_from_unary_expr): Likewise.
+ * tree-ssa-loop-niter.c (infer_loop_bounds_from_signedness):
+ Likewise.
+ (nowrap_type_p): Likewise.
+ * tree-scalar-evolution.c (simple_iv): Likewise.
+ * fold-const.c (negate_expr_p): Use TYPE_OVERFLOW_WRAPS.
+ (build_range_check): Likewise.
+ (extract_muldiv_1): Likewise.
+ (fold_comparison): Likewise.
+ * tree-vrp.c (vrp_int_const_binop): Likewise.
+ (extract_range_from_unary_expr): Likewise.
+ * convert.c (convert_to_integer): Likewise.
+ * fold-const.c (fold_negate_expr): Use TYPE_OVERFLOW_TRAPS.
+ (fold_comparison): Likewise.
+ (fold_binary): Likewise.
+ * optabs.c (optab_for_tree_code): Likewise.
+ * tree-vectorizer.c (vect_is_simple_reduction): Likewise.
+ * simplify-rtx.c (simplify_const_relational_operation): Check
+ flag_strict_overflow and flag_trapv.
+ (simplify_const_relational_operation): Likewise.
+ * doc/invoke.texi (Option Summary): Mention -fstrict-overflow.
+ (Optimize Options): Add -fstrict-overflow to -O2 list. Document
+ -fstrict-overflow.
+
2007-01-27 Roger Sayle <roger@eyesopen.com>
* tree.c (tree_fold_gcd): Delete.
Common Report Var(flag_strict_aliasing)
Assume strict aliasing rules apply
+fstrict-overflow
+Common Report Var(flag_strict_overflow)
+Treat signed overflow as undefined
+
fsyntax-only
Common Report Var(flag_syntax_only)
Check for syntax errors, then stop
PLUS_EXPR or MINUS_EXPR in an unsigned
type. Otherwise, we would introduce
signed-overflow undefinedness. */
- || (!flag_wrapv
+ || ((!TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
+ || !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1)))
&& (ex_form == PLUS_EXPR
- || ex_form == MINUS_EXPR)
- && (!TYPE_UNSIGNED (TREE_TYPE (arg0))
- || !TYPE_UNSIGNED (TREE_TYPE (arg1)))))
+ || ex_form == MINUS_EXPR)))
typex = lang_hooks.types.unsigned_type (typex);
else
typex = lang_hooks.types.signed_type (typex);
-fsched2-use-traces -fsee -freschedule-modulo-scheduled-loops @gol
-fsection-anchors -fsignaling-nans -fsingle-precision-constant @gol
-fstack-protector -fstack-protector-all @gol
--fstrict-aliasing -ftracer -fthread-jumps @gol
+-fstrict-aliasing -fstrict-overflow -ftracer -fthread-jumps @gol
-funroll-all-loops -funroll-loops -fpeel-loops @gol
-fsplit-ivs-in-unroller -funswitch-loops @gol
-fvariable-expansion-in-unroller @gol
-fschedule-insns -fschedule-insns2 @gol
-fsched-interblock -fsched-spec @gol
-fregmove @gol
--fstrict-aliasing @gol
+-fstrict-aliasing -fstrict-overflow @gol
-fdelete-null-pointer-checks @gol
-freorder-blocks -freorder-functions @gol
-falign-functions -falign-jumps @gol
Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+@item -fstrict-overflow
+@opindex fstrict-overflow
+Allow the compiler to assume strict signed overflow rules, depending
+on the language being compiled. For C (and C++) this means that
+overflow when doing arithmetic with signed numbers is undefined, which
+means that the compiler may assume that it will not happen. This
+permits various optimizations. For example, the compiler will assume
+that an expression like @code{i + 10 > i} will always be true for
+signed @code{i}. This assumption is only valid if signed overflow is
+undefined, as the expression is false if @code{i + 10} overflows when
+using twos complement arithmetic. When this option is in effect any
+attempt to determine whether an operation on signed numbers will
+overflow must be written carefully to not actually involve overflow.
+
+See also the @option{-fwrapv} option. Using @option{-fwrapv} means
+that signed overflow is fully defined: it wraps. When
+@option{-fwrapv} is used, there is no difference between
+@option{-fstrict-overflow} and @option{-fno-strict-overflow}. With
+@option{-fwrapv} certain types of overflow are permitted. For
+example, if the compiler gets an overflow when doing arithmetic on
+constants, the overflowed value can still be used with
+@option{-fwrapv}, but not otherwise.
+
+The @option{-fstrict-overflow} option is enabled at levels
+@option{-O2}, @option{-O3}, @option{-Os}.
+
@item -falign-functions
@itemx -falign-functions=@var{n}
@opindex falign-functions
/* Compilation switch flag definitions for GCC.
Copyright (C) 1987, 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002,
- 2003, 2004, 2005
+ 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
#define HONOR_SIGN_DEPENDENT_ROUNDING(MODE) \
(MODE_HAS_SIGN_DEPENDENT_ROUNDING (MODE) && flag_rounding_math)
+/* True if overflow wraps around for the given integral type. That
+ is, TYPE_MAX + 1 == TYPE_MIN. */
+#define TYPE_OVERFLOW_WRAPS(TYPE) \
+ (TYPE_UNSIGNED (TYPE) || flag_wrapv)
+
+/* True if overflow is undefined for the given integral type. We may
+ optimize on the assumption that values in the type never
+ overflow. */
+#define TYPE_OVERFLOW_UNDEFINED(TYPE) \
+ (!TYPE_UNSIGNED (TYPE) && !flag_wrapv && !flag_trapv && flag_strict_overflow)
+
+/* True if overflow for the given integral type should issue a
+ trap. */
+#define TYPE_OVERFLOW_TRAPS(TYPE) \
+ (!TYPE_UNSIGNED (TYPE) && flag_trapv)
+
#endif /* ! GCC_FLAGS_H */
switch (TREE_CODE (t))
{
case INTEGER_CST:
- if (TYPE_UNSIGNED (type)
- || (flag_wrapv && ! flag_trapv))
+ if (TYPE_OVERFLOW_WRAPS (type))
return true;
/* Check that -CST will not overflow type. */
return may_negate_without_overflow_p (t);
case BIT_NOT_EXPR:
- return INTEGRAL_TYPE_P (type)
- && (TYPE_UNSIGNED (type)
- || (flag_wrapv && !flag_trapv));
+ return (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_WRAPS (type));
case REAL_CST:
case NEGATE_EXPR:
case FLOOR_DIV_EXPR:
case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
- if (TYPE_UNSIGNED (TREE_TYPE (t)) || flag_wrapv)
+ if (INTEGRAL_TYPE_P (TREE_TYPE (t))
+ && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)))
break;
return negate_expr_p (TREE_OPERAND (t, 1))
|| negate_expr_p (TREE_OPERAND (t, 0));
case INTEGER_CST:
tem = fold_negate_const (t, type);
if (!TREE_OVERFLOW (tem)
- || TYPE_UNSIGNED (type)
- || !flag_trapv)
+ || !TYPE_OVERFLOW_TRAPS (type))
return tem;
break;
case FLOOR_DIV_EXPR:
case CEIL_DIV_EXPR:
case EXACT_DIV_EXPR:
- if (!TYPE_UNSIGNED (type) && !flag_wrapv)
+ if (!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
{
tem = TREE_OPERAND (t, 1);
if (negate_expr_p (tem))
/* If flag_wrapv and ARG0_TYPE is signed, then we cannot
move a constant to the other side. */
- if (flag_wrapv && !TYPE_UNSIGNED (arg0_type))
+ if (!TYPE_UNSIGNED (arg0_type)
+ && !TYPE_OVERFLOW_UNDEFINED (arg0_type))
break;
/* If EXP is signed, any overflow in the computation is undefined,
/* If we don't have wrap-around arithmetics upfront, try to force it. */
if (TREE_CODE (etype) == INTEGER_TYPE
- && !TYPE_UNSIGNED (etype) && !flag_wrapv)
+ && !TYPE_OVERFLOW_WRAPS (etype))
{
tree utype, minv, maxv;
fold_convert (ctype, c), 0);
/* We allow the constant to overflow with wrapping semantics. */
if (op1 == 0
- || (TREE_OVERFLOW (op1) && ! flag_wrapv))
+ || (TREE_OVERFLOW (op1) && !TYPE_OVERFLOW_WRAPS (ctype)))
break;
}
else
If we have an unsigned type that is not a sizetype, we cannot do
this since it will change the result if the original computation
overflowed. */
- if ((! TYPE_UNSIGNED (ctype)
+ if ((TYPE_OVERFLOW_UNDEFINED (ctype)
|| (TREE_CODE (ctype) == INTEGER_TYPE && TYPE_IS_SIZETYPE (ctype)))
- && ! flag_wrapv
&& ((code == MULT_EXPR && tcode == EXACT_DIV_EXPR)
|| (tcode == MULT_EXPR
&& code != TRUNC_MOD_EXPR && code != CEIL_MOD_EXPR
/* In principle pointers also have undefined overflow behavior,
but that causes problems elsewhere. */
- if ((flag_wrapv || flag_trapv)
- || (TYPE_UNSIGNED (TREE_TYPE (arg0))
- || POINTER_TYPE_P (TREE_TYPE (arg0))))
+ if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
+ || POINTER_TYPE_P (TREE_TYPE (arg0)))
return NULL_TREE;
/* Try canonicalization by simplifying arg0. */
if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1))
- && !TYPE_UNSIGNED (TREE_TYPE (arg1))
- && !(flag_wrapv || flag_trapv))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))
&& (TREE_CODE (arg1) == INTEGER_CST
&& !TREE_OVERFLOW (arg1)))
{
same object, then we can fold this to a comparison of the two offsets in
signed size type. This is possible because pointer arithmetic is
restricted to retain within an object and overflow on pointer differences
- is undefined as of 6.5.6/8 and /9 with respect to the signed ptrdiff_t. */
+ is undefined as of 6.5.6/8 and /9 with respect to the signed ptrdiff_t.
+
+ We check flag_wrapv directly because pointers types are unsigned,
+ and therefore TYPE_OVERFLOW_WRAPS returns true for them. That is
+ normally what we want to avoid certain odd overflow cases, but
+ not here. */
if (POINTER_TYPE_P (TREE_TYPE (arg0))
- && !flag_wrapv && !flag_trapv)
+ && !flag_wrapv
+ && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (arg0)))
{
tree base0, offset0, base1, offset1;
X CMP Y +- C2 +- C1 for signed X, Y. This is valid if
the resulting offset is smaller in absolute value than the
original one. */
- if (!(flag_wrapv || flag_trapv)
- && !TYPE_UNSIGNED (TREE_TYPE (arg0))
+ if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
&& (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
signed arithmetic case. That form is created by the compiler
often enough for folding it to be of value. One example is in
computing loop trip counts after Operator Strength Reduction. */
- if (!(flag_wrapv || flag_trapv)
- && !TYPE_UNSIGNED (TREE_TYPE (arg0))
+ if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg0))
&& TREE_CODE (arg0) == MULT_EXPR
&& (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
&& !TREE_OVERFLOW (TREE_OPERAND (arg0, 1)))
/* ~X + X is -1. */
if (TREE_CODE (arg0) == BIT_NOT_EXPR
&& operand_equal_p (TREE_OPERAND (arg0, 0), arg1, 0)
- && !TYPE_TRAP_SIGNED (type))
+ && !TYPE_OVERFLOW_TRAPS (type))
{
t1 = build_int_cst_type (type, -1);
return omit_one_operand (type, t1, arg1);
/* X + ~X is -1. */
if (TREE_CODE (arg1) == BIT_NOT_EXPR
&& operand_equal_p (arg0, TREE_OPERAND (arg1, 0), 0)
- && !TYPE_TRAP_SIGNED (type))
+ && !TYPE_OVERFLOW_TRAPS (type))
{
t1 = build_int_cst_type (type, -1);
return omit_one_operand (type, t1, arg0);
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (arg0) == NEGATE_EXPR
&& integer_onep (arg1)
- && !TYPE_TRAP_SIGNED (type))
+ && !TYPE_OVERFLOW_TRAPS (type))
return fold_build1 (BIT_NOT_EXPR, type,
fold_convert (type, TREE_OPERAND (arg0, 0)));
/* Convert -A / -B to A / B when the type is signed and overflow is
undefined. */
- if (!TYPE_UNSIGNED (type) && !flag_wrapv
+ if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
&& TREE_CODE (arg0) == NEGATE_EXPR
&& negate_expr_p (arg1))
return fold_build2 (code, type, TREE_OPERAND (arg0, 0),
negate_expr (arg1));
- if (!TYPE_UNSIGNED (type) && !flag_wrapv
+ if ((!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
&& TREE_CODE (arg1) == NEGATE_EXPR
&& negate_expr_p (arg0))
return fold_build2 (code, type, negate_expr (arg0),
&& TREE_CODE (arg1) == INTEGER_CST
&& !TREE_OVERFLOW (arg1)
&& TREE_INT_CST_HIGH (arg1) < 0
- && !flag_trapv
+ && !TYPE_OVERFLOW_TRAPS (type)
/* Avoid this transformation if C is INT_MIN, i.e. C == -C. */
&& !sign_bit_p (arg1, arg1))
return fold_build2 (code, type, fold_convert (type, arg0),
if (code == TRUNC_MOD_EXPR
&& !TYPE_UNSIGNED (type)
&& TREE_CODE (arg1) == NEGATE_EXPR
- && !flag_trapv)
+ && !TYPE_OVERFLOW_TRAPS (type))
return fold_build2 (code, type, fold_convert (type, arg0),
fold_convert (type, TREE_OPERAND (arg1, 0)));
&& ((TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
&& !HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))))
|| (TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && !TYPE_UNSIGNED (TREE_TYPE (arg1))
- && !(flag_wrapv || flag_trapv))))
+ && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (arg1)))))
{
tree arg01 = TREE_OPERAND (arg0, 1);
enum tree_code code0 = TREE_CODE (arg0);
case ABS_EXPR:
/* We can't return 1 if flag_wrapv is set because
ABS_EXPR<INT_MIN> = INT_MIN. */
- if (!(flag_wrapv && INTEGRAL_TYPE_P (TREE_TYPE (t))))
- return true;
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
+ return true;
+ if (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)))
+ return true;
break;
case INTEGER_CST:
return !integer_zerop (t);
case PLUS_EXPR:
- if (!TYPE_UNSIGNED (type) && !flag_wrapv)
+ if (TYPE_OVERFLOW_UNDEFINED (type))
{
/* With the presence of negative values it is hard
to say something. */
break;
case MULT_EXPR:
- if (!TYPE_UNSIGNED (type) && !flag_wrapv)
+ if (TYPE_OVERFLOW_UNDEFINED (type))
{
return (tree_expr_nonzero_p (TREE_OPERAND (t, 0))
&& tree_expr_nonzero_p (TREE_OPERAND (t, 1)));
/* Expand the basic unary and binary arithmetic operations, for GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
break;
}
- trapv = flag_trapv && INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type);
+ trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
switch (code)
{
case PLUS_EXPR:
/* Command line option handling.
- Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Neil Booth.
This file is part of GCC.
#endif
flag_regmove = 1;
flag_strict_aliasing = 1;
+ flag_strict_overflow = 1;
flag_delete_null_pointer_checks = 1;
flag_reorder_blocks = 1;
flag_reorder_functions = 1;
/* RTL simplification functions for GNU compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
/* Optimize abs(x) < 0.0. */
if (trueop1 == CONST0_RTX (mode)
&& !HONOR_SNANS (mode)
- && !(flag_wrapv && INTEGRAL_MODE_P (mode)))
+ && (!INTEGRAL_MODE_P (mode)
+ || (!flag_wrapv && !flag_trapv && flag_strict_overflow)))
{
tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
: trueop0;
/* Optimize abs(x) >= 0.0. */
if (trueop1 == CONST0_RTX (mode)
&& !HONOR_NANS (mode)
- && !(flag_wrapv && INTEGRAL_MODE_P (mode)))
+ && (!INTEGRAL_MODE_P (mode)
+ || (!flag_wrapv && !flag_trapv && flag_strict_overflow)))
{
tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
: trueop0;
+2007-01-27 Ian Lance Taylor <iant@google.com>
+
+ * gcc.dg/strict-overflow-1.c: New test.
+ * gcc.dg/no-strict-overflow-1.c: New test.
+ * gcc.dg/strict-overflow-2.c: New test.
+ * gcc.dg/no-strict-overflow-2.c: New test.
+ * gcc.dg/strict-overflow-3.c: New test.
+ * gcc.dg/no-strict-overflow-3.c: New test.
+ * gcc.dg/strict-overflow-4.c: New test.
+ * gcc.dg/no-strict-overflow-4.c: New test.
+ * gcc.dg/fold-mod-1.c: Add -fstrict-overflow option.
+ * gcc.dg/pr15784-1.c: Likewise.
+ * gcc.dg/pr20922-1.c: Likewise.
+ * gcc.dg/pr20922-3.c: Likewise.
+ * gcc.dg/pr20922-4.c: Likewise.
+ * gcc.dg/pr20922-6.c: Likewise.
+ * gcc.dg/compare-4.c: Likewise.
+ * gcc.dg/torture/pr26898-1.c: Likewise.
+ * gcc.dg/tree-ssa/divide-1.c: Likewise.
+ * gcc.dg/tree-ssa/divide-2.c: Likewise.
+ * gcc.dg/tree-ssa/divide-3.c: Likewise.
+ * gcc.dg/tree-ssa/divide-4.c: Likewise.
+ * gcc.dg/tree-ssa/pr14490-1.c: Likewise.
+ * gcc.dg/tree-ssa/pr14490-3.c: Likewise.
+ * gcc.dg/tree-ssa/pr21082.c: Likewise.
+ * gcc.dg/tree-ssa/pr26899.c: Likewise.
+ * g++.dg/tree-ssa/pr21082.C: Likewise.
+
2007-01-27 Roger Sayle <roger@eyesopen.com>
* gcc-dg/large-size-array-3.c: New test case.
/* { dg-do link } */
+/* { dg-options "-fstrict-overflow" } */
void link_error();
Origin: Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 5/13/2001. */
/* { dg-do compile } */
-/* { dg-options "-Wsign-compare" } */
+/* { dg-options "-Wsign-compare -fstrict-overflow" } */
extern void bar(void);
if ((x ? 10 : (bar(),bar(),bar(),bar(),x==y)) < u)
return x;
- /* Test an ABS_EXPR, which is by definition non-negative. */
+ /* Test an ABS_EXPR, which is by definition non-negative when
+ -fstrict-overflow is used. */
if (u < __builtin_abs(x))
return x;
if (__builtin_abs(x) < u)
/* { dg-do compile } */
/* { dg-require-effective-target int32plus } */
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fdump-tree-gimple -fstrict-overflow" } */
#define ABS(x) (x > 0 ? x : -x)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of strict-overflow-1.c. */
+
+/* We can only simplify the conditional when using strict overflow
+ semantics. */
+
+int
+foo (int i)
+{
+ return i - 5 < 10;
+}
+
+/* { dg-final { scan-tree-dump "-[ ]*5" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of strict-overflow-2.c. */
+
+/* We can only simplify the division when using strict overflow
+ semantics. */
+
+int
+foo (int i)
+{
+ return (i * 100) / 10;
+}
+
+/* { dg-final { scan-tree-dump "100" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of strict-overflow-3.c. */
+
+/* We can only simplify the conditional when using strict overflow
+ semantics. */
+
+int
+foo (int i, int j)
+{
+ return i + 100 < j + 1000;
+}
+
+/* { dg-final { scan-tree-dump "1000" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fno-strict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of strict-overflow-4.c. */
+
+/* We can only simplify the conditional when using strict overflow
+ semantics. */
+
+int
+foo (int i)
+{
+ return i + 1 > i;
+}
+
+/* We expect to see "<bb N>"; confirm that, so that we know to count
+ it in the real test. */
+/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 1 "final_cleanup" } } */
+/* { dg-final { scan-tree-dump-times ">|<" 3 "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
/* { dg-do compile } */
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */
/* Test for folding abs(x) where appropriate. */
#define abs(x) x > 0 ? x : -x
extern double fabs (double);
/* { dg-do compile } */
-/* { dg-options "-fno-wrapv -fdump-tree-gimple" } */
+/* { dg-options "-fno-wrapv -fstrict-overflow -fdump-tree-gimple" } */
int f(int i)
{
return (i - 2) > i;
/* { dg-do compile } */
-/* { dg-options "-ffast-math -fno-wrapv -fdump-tree-gimple" } */
+/* { dg-options "-ffast-math -fno-wrapv -fstrict-overflow -fdump-tree-gimple" } */
int f(int i)
{
return (i - 2) <= i;
/* { dg-do compile } */
-/* { dg-options "-fno-wrapv -fdump-tree-gimple" } */
+/* { dg-options "-fno-wrapv -fstrict-overflow -fdump-tree-gimple" } */
int f(int i)
{
return i < (i - 2);
/* { dg-do compile } */
-/* { dg-options "-ffast-math -fno-wrapv -fdump-tree-gimple" } */
+/* { dg-options "-ffast-math -fno-wrapv -fstrict-overflow -fdump-tree-gimple" } */
int f(int i)
{
return i >= (i - 2);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of no-strict-overflow-1.c. */
+
+/* We can only simplify the conditional when using strict overflow
+ semantics. */
+
+int
+foo (int i)
+{
+ return i - 5 < 10;
+}
+
+/* { dg-final { scan-tree-dump-not "-[ ]*5" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of no-strict-overflow-2.c. */
+
+/* We can only simplify the division when using strict overflow
+ semantics. */
+
+int
+foo (int i)
+{
+ return (i * 100) / 10;
+}
+
+/* { dg-final { scan-tree-dump-not "100" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of no-strict-overflow-3.c. */
+
+/* We can only simplify the conditional when using strict overflow
+ semantics. */
+
+int
+foo (int i, int j)
+{
+ return i + 100 < j + 1000;
+}
+
+/* { dg-final { scan-tree-dump-not "1000" "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-fstrict-overflow -O2 -fdump-tree-final_cleanup" } */
+
+/* Source: Ian Lance Taylor. Dual of no-strict-overflow-4.c. */
+
+/* We can only simplify the conditional when using strict overflow
+ semantics. */
+
+int
+foo (int i)
+{
+ return i + 1 > i;
+}
+
+/* We expect to see "<bb N>"; confirm that, so that we know to count
+ it in the real test. */
+/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 1 "final_cleanup" } } */
+/* { dg-final { scan-tree-dump-times ">|<" 2 "final_cleanup" } } */
+/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
/* { dg-do link } */
+/* { dg-options "-fstrict-overflow" } */
#include <limits.h>
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
int f(int a)
{
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
int f(int a)
{
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
int f(int a)
{
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
int f(int a)
{
/* { dg-do compile } */
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */
int g(int x)
{
return (x - 10) < 0;
/* { dg-do compile } */
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */
int g(int x)
{
return (x + 10) < 0;
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */
int foo (int i, int j)
{
/* Exception handling semantics and decomposition for trees.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
honor_nans = flag_trapping_math && !flag_finite_math_only;
honor_snans = flag_signaling_nans != 0;
}
- else if (INTEGRAL_TYPE_P (t) && TYPE_TRAP_SIGNED (t))
+ else if (INTEGRAL_TYPE_P (t) && TYPE_OVERFLOW_TRAPS (t))
honor_trapv = true;
}
/* Scalar evolution detector.
- Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Sebastian Pop <s.pop@laposte.net>
This file is part of GCC.
|| chrec_contains_symbols_defined_in_loop (iv->base, loop->num))
return false;
- iv->no_overflow = (!folded_casts
- && !flag_wrapv
- && !TYPE_UNSIGNED (type));
+ iv->no_overflow = !folded_casts && TYPE_OVERFLOW_UNDEFINED (type);
+
return true;
}
/* Functions to determine/estimate number of iterations of a loop.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
{
tree def, base, step, scev, type, low, high;
- if (flag_wrapv || TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
+ if (TREE_CODE (stmt) != GIMPLE_MODIFY_STMT)
return;
def = GIMPLE_STMT_OPERAND (stmt, 0);
type = TREE_TYPE (def);
if (!INTEGRAL_TYPE_P (type)
- || TYPE_UNSIGNED (type))
+ || !TYPE_OVERFLOW_UNDEFINED (type))
return;
scev = instantiate_parameters (loop, analyze_scalar_evolution (loop, def));
bool
nowrap_type_p (tree type)
{
- if (!flag_wrapv
- && INTEGRAL_TYPE_P (type)
- && !TYPE_UNSIGNED (type))
+ if (INTEGRAL_TYPE_P (type)
+ && TYPE_OVERFLOW_UNDEFINED (type))
return true;
if (POINTER_TYPE_P (type))
/* Lower vector operations to scalar operations.
- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
{
case PLUS_EXPR:
case MINUS_EXPR:
- if (!TYPE_TRAP_SIGNED (type))
+ if (!TYPE_OVERFLOW_TRAPS (type))
return expand_vector_addition (bsi, do_binop, do_plus_minus, type,
TREE_OPERAND (rhs, 0),
TREE_OPERAND (rhs, 1), code);
break;
case NEGATE_EXPR:
- if (!TYPE_TRAP_SIGNED (type))
+ if (!TYPE_OVERFLOW_TRAPS (type))
return expand_vector_addition (bsi, do_unop, do_negate, type,
TREE_OPERAND (rhs, 0),
NULL_TREE, code);
/* Loop Vectorization
- Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Dorit Naishlos <dorit@il.ibm.com>
This file is part of GCC.
}
return NULL_TREE;
}
- else if (INTEGRAL_TYPE_P (type) && !TYPE_UNSIGNED (type) && flag_trapv)
+ else if (INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type))
{
/* Changing the order of operations changes the semantics. */
if (vect_print_dump_info (REPORT_DETAILS))
/* Support routines for Value Range Propagation (VRP).
- Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+ Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Diego Novillo <dnovillo@redhat.com>.
This file is part of GCC.
return 0;
/* If overflow is defined we cannot simplify more. */
- if (TYPE_UNSIGNED (TREE_TYPE (val1))
- || flag_wrapv)
+ if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (val1)))
return -2;
if (code1 == SSA_NAME)
/* If we are not using wrapping arithmetic, operate symbolically
on -INF and +INF. */
- if (TYPE_UNSIGNED (TREE_TYPE (val1))
- || flag_wrapv)
+ if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (val1)))
{
int checkz = compare_values (res, val1);
bool overflow = false;
point. */
if (code == MULT_EXPR
&& vr0.type == VR_ANTI_RANGE
- && (flag_wrapv || TYPE_UNSIGNED (TREE_TYPE (op0))))
+ && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))
{
set_value_range_to_varying (vr);
return;
? TYPE_MIN_VALUE (TREE_TYPE (expr))
: fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
- max = vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))
- ? (vr0.type == VR_ANTI_RANGE || flag_wrapv
- ? TYPE_MIN_VALUE (TREE_TYPE (expr))
- : TYPE_MAX_VALUE (TREE_TYPE (expr)))
- : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
+ max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr))
+ ? ((vr0.type == VR_ANTI_RANGE
+ || TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)))
+ ? TYPE_MIN_VALUE (TREE_TYPE (expr))
+ : TYPE_MAX_VALUE (TREE_TYPE (expr)))
+ : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min));
}
else if (code == NEGATE_EXPR
{
/* -TYPE_MIN_VALUE = TYPE_MIN_VALUE with flag_wrapv so we can't get a
useful range. */
- if (flag_wrapv
+ if (!TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (expr))
&& ((vr0.type == VR_RANGE
&& vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
|| (vr0.type == VR_ANTI_RANGE
or ~[-INF + 1, min (abs(MIN), abs(MAX))] when
flag_wrapv is set and the original anti-range doesn't include
TYPE_MIN_VALUE, remember -TYPE_MIN_VALUE = TYPE_MIN_VALUE. */
- min = (flag_wrapv && vr0.min != type_min_value
+ min = ((TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))
+ && vr0.min != type_min_value)
? int_const_binop (PLUS_EXPR,
type_min_value,
integer_one_node, 0)
/* In integral and pointer types, means an unsigned type. */
#define TYPE_UNSIGNED(NODE) (TYPE_CHECK (NODE)->base.unsigned_flag)
-#define TYPE_TRAP_SIGNED(NODE) \
- (flag_trapv && ! TYPE_UNSIGNED (NODE))
-
/* Nonzero in a VAR_DECL means assembler code has been written.
Nonzero in a FUNCTION_DECL means that the function has been compiled.
This is interesting in an inline function, since it might not need