This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH RFC: -fstrict-overflow


"Richard Guenther" <richard.guenther@gmail.com> writes:

> Maybe I'm overlooking some detail, but it looks like -fno-strict-overflow
> basically enables the same behavior as -fwrapv does at the places you
> changed.  So I assume there are places you didn't touch - which are they,
> how did you categorize the cases?

Using -fwrapv means that signed overflow is fully defined: it wraps.
Using -fno-strict-overflow means that signed overflow does not invoke
undefined behaviour, but is otherwise unspecified.  The difference is
that with -fwrapv certain types of overflow are permitted.  For
example, if we get an overflow when computing a constant, we can still
use it.  When VRP does range computations, the values are permitted to
wrap around.

You are correct that -fno-strict-overflow is the same as -fwrapv in
the places where I changed.  That should be clearer with the new
predicates.  This is because -fwrapv overrides -fstrict-overflow.  The
difference between -fno-strict-overflow and -fstrict-overflow only
exists when -fwrapv is not used.

This does mean that we could simplify the predicates if we force the
options.  For example, -fwrapv could force -fno-strict-overflow.  That
would simplify the TYPE_OVERFLOW_UNDEFINED predicate.  I think I would
prefer to put the patch in without that and add that later.

> The question that comes up is why do we need -f[no-]strict-overflow if
> we have -fwrapv?  Why don't we enable -fwrapv for -O0 and -O1?  Is
> this because -fwrapv is a stronger statement than -fno-strict-overflow?
> But if it is, does -fno-strict-overflow do anything good about all this
> discussion?

Yes, as described, -fwrapv is stronger.  Still, I believe that
-fno-strict-overflow is meaningful.  It gives people the C language
semantics--signed overflow is undefined--while preventing the compiler
from exploiting that fact to break naive code.


> I see with the new predicates all is well hidden in implementation details,
> and I like this.  So maybe split the patch into the (certainly
> non-controversical)
> predicate introduction part and the part introducing the new flag?

I don't see any advantage to splitting the patch like that.  It seems
like unnecessary makework.  Given the new predicates, the only
difference will be to TYPE_OVERFLOW_UNDEFINED.


That said, my version of the patch with the predicates was incomplete,
because I did not carry TYPE_OVERFLOW_WRAPS and TYPE_OVERFLOW_TRAPS
forward into all the places where they should be used.  Here is a
third version of the patch which does that.

In this version of the patch, you can consider the differences between
TYPE_OVERFLOW_UNDEFINED and TYPE_OVERFLOW_WRAPS to see the differences
between -fwrapv and -fno-strict-overflow.  TYPE_OVERFLOW_WRAPS
corresponds to -fwrapv.  TYPE_OVERFLOW_UNDEFINED corresponds to
-fstrict-overflow (and thus -fno-wrapv).

I apologize for all the iterations of this patch.  I will be checking
the final patch very carefully before I commit it.

Ian


gcc/ChangeLog:
2007-01-24  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.

gcc/testsuite/ChangeLog:
2007-01-23  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.


Index: gcc/tree-vrp.c
===================================================================
--- gcc/tree-vrp.c	(revision 121077)
+++ gcc/tree-vrp.c	(working copy)
@@ -1,5 +1,5 @@
 /* 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.
@@ -570,8 +570,7 @@ compare_values (tree val1, tree val2)
 	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)
@@ -1215,8 +1214,7 @@ vrp_int_const_binop (enum tree_code code
 
   /* 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;
@@ -1503,7 +1501,7 @@ extract_range_from_binary_expr (value_ra
 	 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;
@@ -1799,11 +1797,12 @@ extract_range_from_unary_expr (value_ran
 	    ? 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
@@ -1828,7 +1827,7 @@ extract_range_from_unary_expr (value_ran
     {
       /* -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
@@ -1865,7 +1864,8 @@ extract_range_from_unary_expr (value_ran
 	         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)
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 121077)
+++ gcc/doc/invoke.texi	(working copy)
@@ -341,7 +341,7 @@ Objective-C and Objective-C++ Dialects}.
 -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
@@ -4616,7 +4616,7 @@ also turns on the following optimization
 -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
@@ -5446,6 +5446,24 @@ int f() @{
 
 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.
+
+Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}.
+
 @item -falign-functions
 @itemx -falign-functions=@var{n}
 @opindex falign-functions
Index: gcc/flags.h
===================================================================
--- gcc/flags.h	(revision 121077)
+++ gcc/flags.h	(working copy)
@@ -1,6 +1,6 @@
 /* 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.
@@ -288,4 +288,20 @@ extern const char *flag_random_seed;
 #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 */
Index: gcc/tree-ssa-loop-niter.c
===================================================================
--- gcc/tree-ssa-loop-niter.c	(revision 121077)
+++ gcc/tree-ssa-loop-niter.c	(working copy)
@@ -1,5 +1,5 @@
 /* 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.
    
@@ -1874,7 +1874,7 @@ infer_loop_bounds_from_signedness (struc
 {
   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);
@@ -1884,7 +1884,7 @@ infer_loop_bounds_from_signedness (struc
 
   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));
@@ -2094,9 +2094,8 @@ n_of_executions_at_most (tree stmt,
 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))
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	(revision 121077)
+++ gcc/optabs.c	(working copy)
@@ -341,7 +341,7 @@ optab_for_tree_code (enum tree_code code
       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:
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 121077)
+++ gcc/tree.h	(working copy)
@@ -1237,9 +1237,6 @@ extern void omp_clause_range_check_faile
 /* 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
Index: gcc/tree-scalar-evolution.c
===================================================================
--- gcc/tree-scalar-evolution.c	(revision 121077)
+++ gcc/tree-scalar-evolution.c	(working copy)
@@ -1,5 +1,5 @@
 /* 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.
@@ -2837,9 +2837,8 @@ simple_iv (struct loop *loop, tree stmt,
       || 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;
 }
 
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 121077)
+++ gcc/fold-const.c	(working copy)
@@ -985,16 +985,14 @@ negate_expr_p (tree t)
   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:
@@ -1040,7 +1038,8 @@ negate_expr_p (tree t)
     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));
@@ -1102,8 +1101,7 @@ fold_negate_expr (tree t)
     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;
 
@@ -1188,7 +1186,7 @@ fold_negate_expr (tree t)
     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))
@@ -3962,7 +3960,8 @@ make_range (tree exp, int *pin_p, tree *
 
 	  /* 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,
@@ -4212,7 +4211,7 @@ build_range_check (tree type, tree exp, 
 
   /* 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;
 
@@ -5611,7 +5610,7 @@ extract_muldiv_1 (tree t, tree c, enum t
 			     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
@@ -5685,9 +5684,8 @@ extract_muldiv_1 (tree t, tree c, enum t
 	 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
@@ -7910,9 +7908,8 @@ maybe_canonicalize_comparison (enum tree
 
   /* 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.  */
@@ -7957,8 +7954,7 @@ fold_comparison (enum tree_code code, tr
   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)))
     {
@@ -8087,7 +8083,8 @@ fold_comparison (enum tree_code code, tr
      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.  */
   if (POINTER_TYPE_P (TREE_TYPE (arg0))
-      && !flag_wrapv && !flag_trapv)
+      && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))
+      && !TYPE_OVERFLOW_TRAPS (TREE_TYPE (arg0)))
     {
       tree base0, offset0, base1, offset1;
 
@@ -8120,8 +8117,7 @@ fold_comparison (enum tree_code code, tr
      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)))
@@ -8162,8 +8158,7 @@ fold_comparison (enum tree_code code, tr
      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)))
@@ -8783,7 +8778,7 @@ fold_binary (enum tree_code code, tree t
 	  /* ~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);
@@ -8792,7 +8787,7 @@ fold_binary (enum tree_code code, tree t
 	  /* 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);
@@ -9139,7 +9134,7 @@ fold_binary (enum tree_code code, tree t
       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)));
 
@@ -10258,12 +10253,12 @@ fold_binary (enum tree_code code, tree t
 
       /* 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),
@@ -10338,7 +10333,7 @@ fold_binary (enum tree_code code, tree t
 	  && 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),
@@ -10348,7 +10343,7 @@ fold_binary (enum tree_code code, tree t
       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)));
 
@@ -11168,8 +11163,7 @@ fold_binary (enum tree_code code, tree t
 	  && ((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);
@@ -12537,8 +12531,10 @@ tree_expr_nonnegative_p (tree t)
     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:
@@ -12844,7 +12840,7 @@ tree_expr_nonzero_p (tree t)
       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.  */
@@ -12858,7 +12854,7 @@ tree_expr_nonzero_p (tree t)
       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)));
Index: gcc/testsuite/gcc.dg/strict-overflow-2.c
===================================================================
--- gcc/testsuite/gcc.dg/strict-overflow-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/strict-overflow-2.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/strict-overflow-4.c
===================================================================
--- gcc/testsuite/gcc.dg/strict-overflow-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/strict-overflow-4.c	(revision 0)
@@ -0,0 +1,19 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/pr20922-4.c
===================================================================
--- gcc/testsuite/gcc.dg/pr20922-4.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/pr20922-4.c	(working copy)
@@ -1,5 +1,5 @@
 /* { 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);
Index: gcc/testsuite/gcc.dg/pr20922-6.c
===================================================================
--- gcc/testsuite/gcc.dg/pr20922-6.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/pr20922-6.c	(working copy)
@@ -1,5 +1,5 @@
 /* { 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);
Index: gcc/testsuite/gcc.dg/no-strict-overflow-1.c
===================================================================
--- gcc/testsuite/gcc.dg/no-strict-overflow-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/no-strict-overflow-1.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/no-strict-overflow-3.c
===================================================================
--- gcc/testsuite/gcc.dg/no-strict-overflow-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/no-strict-overflow-3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/torture/pr26898-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/pr26898-1.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/torture/pr26898-1.c	(working copy)
@@ -1,4 +1,5 @@
 /* { dg-do link } */
+/* { dg-options "-fstrict-overflow" } */
 
 #include <limits.h>
 
Index: gcc/testsuite/gcc.dg/compare4.c
===================================================================
--- gcc/testsuite/gcc.dg/compare4.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/compare4.c	(working copy)
@@ -2,7 +2,7 @@
    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);
 
@@ -21,7 +21,8 @@ int foo(int x, int y, unsigned u)
   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)
Index: gcc/testsuite/gcc.dg/tree-ssa/divide-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/divide-1.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/tree-ssa/divide-1.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
 
 int f(int a)
 {
Index: gcc/testsuite/gcc.dg/tree-ssa/pr26899.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/pr26899.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr26899.c	(working copy)
@@ -1,4 +1,4 @@
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */
 
 int foo (int i, int j)
 {
Index: gcc/testsuite/gcc.dg/tree-ssa/divide-2.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/divide-2.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/tree-ssa/divide-2.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
 
 int f(int a)
 {
Index: gcc/testsuite/gcc.dg/tree-ssa/pr14490-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/pr14490-1.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr14490-1.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */
 int g(int x)
 {
    return (x - 10) < 0;
Index: gcc/testsuite/gcc.dg/tree-ssa/divide-3.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/divide-3.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/tree-ssa/divide-3.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
 
 int f(int a)
 {
Index: gcc/testsuite/gcc.dg/tree-ssa/divide-4.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/divide-4.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/tree-ssa/divide-4.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized" } */
+/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */
 
 int f(int a)
 {
Index: gcc/testsuite/gcc.dg/tree-ssa/pr14490-3.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/pr14490-3.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr14490-3.c	(working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fdump-tree-gimple" } */
+/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */
 int g(int x)
 {
    return (x + 10) < 0;
Index: gcc/testsuite/gcc.dg/strict-overflow-1.c
===================================================================
--- gcc/testsuite/gcc.dg/strict-overflow-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/strict-overflow-1.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/strict-overflow-3.c
===================================================================
--- gcc/testsuite/gcc.dg/strict-overflow-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/strict-overflow-3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/pr20922-1.c
===================================================================
--- gcc/testsuite/gcc.dg/pr20922-1.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/pr20922-1.c	(working copy)
@@ -1,5 +1,5 @@
 /* { 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;
Index: gcc/testsuite/gcc.dg/pr20922-3.c
===================================================================
--- gcc/testsuite/gcc.dg/pr20922-3.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/pr20922-3.c	(working copy)
@@ -1,5 +1,5 @@
 /* { 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;
Index: gcc/testsuite/gcc.dg/no-strict-overflow-2.c
===================================================================
--- gcc/testsuite/gcc.dg/no-strict-overflow-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/no-strict-overflow-2.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/no-strict-overflow-4.c
===================================================================
--- gcc/testsuite/gcc.dg/no-strict-overflow-4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/no-strict-overflow-4.c	(revision 0)
@@ -0,0 +1,19 @@
+/* { 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" } } */
Index: gcc/testsuite/gcc.dg/pr15784-1.c
===================================================================
--- gcc/testsuite/gcc.dg/pr15784-1.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/pr15784-1.c	(working copy)
@@ -1,5 +1,5 @@
 /* { 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);
Index: gcc/testsuite/gcc.dg/fold-mod-1.c
===================================================================
--- gcc/testsuite/gcc.dg/fold-mod-1.c	(revision 121077)
+++ gcc/testsuite/gcc.dg/fold-mod-1.c	(working copy)
@@ -1,6 +1,6 @@
 /* { 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)
 
Index: gcc/testsuite/g++.dg/tree-ssa/pr21082.C
===================================================================
--- gcc/testsuite/g++.dg/tree-ssa/pr21082.C	(revision 121077)
+++ gcc/testsuite/g++.dg/tree-ssa/pr21082.C	(working copy)
@@ -1,4 +1,5 @@
 /* { dg-do link } */
+/* { dg-options "-fstrict-overflow" } */
 
 void link_error();
 
Index: gcc/opts.c
===================================================================
--- gcc/opts.c	(revision 121077)
+++ gcc/opts.c	(working copy)
@@ -1,5 +1,6 @@
 /* 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.
@@ -487,6 +488,7 @@ decode_options (unsigned int argc, const
 #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;
Index: gcc/tree-eh.c
===================================================================
--- gcc/tree-eh.c	(revision 121077)
+++ gcc/tree-eh.c	(working copy)
@@ -1853,7 +1853,7 @@ tree_could_trap_p (tree expr)
 	  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;
     }
 
Index: gcc/tree-vectorizer.c
===================================================================
--- gcc/tree-vectorizer.c	(revision 121077)
+++ gcc/tree-vectorizer.c	(working copy)
@@ -2033,7 +2033,7 @@ vect_is_simple_reduction (struct loop *l
         }
       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))
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	(revision 121077)
+++ gcc/simplify-rtx.c	(working copy)
@@ -1,6 +1,7 @@
 /* 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.
 
@@ -3939,7 +3940,8 @@ simplify_const_relational_operation (enu
 	  /* 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;
@@ -3952,7 +3954,8 @@ simplify_const_relational_operation (enu
 	  /* 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;
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 121077)
+++ gcc/common.opt	(working copy)
@@ -898,6 +898,10 @@ fstrict-aliasing
 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
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 121077)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -301,14 +301,14 @@ expand_vector_operation (block_stmt_iter
       {
       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);
Index: gcc/convert.c
===================================================================
--- gcc/convert.c	(revision 121077)
+++ gcc/convert.c	(working copy)
@@ -661,11 +661,10 @@ convert_to_integer (tree type, tree expr
 			   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);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]