diff mbox

[RFC,2/3] Propagate and save value ranges wrapped information

Message ID 54B9C45B.3010704@linaro.org
State New
Headers show

Commit Message

Kugan Vivekanandarajah Jan. 17, 2015, 2:09 a.m. UTC
This patch propagate value range wrapps attribute and save this to
SSA_NAME.

Thanks,
Kugan

gcc/ChangeLog:

2015-01-16  Kugan Vivekanandarajah  <kuganv@linaro.org>

	* builtins.c (determine_block_size): Use new definition of
	 get_range_info.
	* gimple-pretty-print.c (dump_ssaname_info): Dump new wrapped info.
	* internal-fn.c (get_range_pos_neg): Use new definition of
	 get_range_info.
	(get_min_precision): Likewise.
	* tree-ssa-copy.c (fini_copy_prop): Use new definition of
	 duplicate_ssa_range_info.
	* tree-ssa-loop-im.c
	(move_computations_dom_walker::before_dom_children): Likewise.
	* tree-ssa-pre.c (eliminate_dom_walker::before_dom_children): Likewise.
	* tree-ssa-loop-niter.c (determine_value_range): Use new definition.
	* tree-ssanames.c (set_range_info): Save wrapped information.
	(get_range_info): Retrive wrapped information.
	(set_nonzero_bits): Set wrapped info.
	(duplicate_ssa_name_range_info): Likewise.
	(duplicate_ssa_name_fn): Likewise.
	* tree-ssanames.h: (set_range_info): Update definition.
	(get_range_info): Ditto.
	* tree-vect-patterns.c (vect_recog_divmod_pattern): Use new
	declaration get_range_info.
	* tree-vrp.c (struct value_range_d): Add wrapped field.
	(set_value_range): Calculate and add wrapped field.
	(set_and_canonicalize_value_range): Likewise.
	(copy_value_range): Likewise.
	(set_value_range_to_value): Likewise.
	(set_value_range_to_nonnegative): Likewise.
	(set_value_range_to_nonnull): Likewise.
	(set_value_range_to_truthvalue): Likewise.
	(abs_extent_range): Likewise.
	(get_value_range): Return wrapped info.
	(update_value_range): Save wrapped info.
	(extract_range_from_assert): Extract and update wrapped info.
	(extract_range_from_ssa_name): Likewise.
	(vrp_int_const_binop): Likewise.
	(extract_range_from_multiplicative_op_1): Likewise.
	(extract_range_from_binary_expr_1): Likewise.
	(extract_range_from_binary_expr): Likewise.
	(extract_range_from_unary_expr_1): Likewise.
	(extract_range_from_comparison): Likewise.
	(extract_range_basic): Likewise.
	(adjust_range_with_scev): Likewise.
	(dump_value_range): Dump wrapped info.
	(remove_range_assertions): Update parameters.
	(vrp_intersect_ranges_1): Propagate wrapped info.
	(vrp_meet_1): Likewise.
	(vrp_visit_phi_node): Save wrapped info to SSA.
	(vrp_finalize): Likewise.
	* tree.h (SSA_NAME_ANTI_RANGE_P): Remove.
	(SSA_NAME_RANGE_OVF_P): New.

gcc/testsuite/ChangeLog:

2015-01-16  Kugan Vivekanandarajah  <kuganv@linaro.org>

	* gcc.dg/tree-ssa/vrp92.c: Update scanned pattern.
diff mbox

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 9280704..83a0882 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -3150,7 +3150,7 @@  determine_block_size (tree len, rtx len_rtx,
 	*probable_max_size = *max_size = GET_MODE_MASK (GET_MODE (len_rtx));
 
       if (TREE_CODE (len) == SSA_NAME)
-	range_type = get_range_info (len, &min, &max);
+	range_type = get_range_info (len, &min, &max, NULL);
       if (range_type == VR_RANGE)
 	{
 	  if (wi::fits_uhwi_p (min) && *min_size < min.to_uhwi ())
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 21e98c6..4d41bca 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1812,13 +1812,15 @@  dump_ssaname_info (pretty_printer *buffer, tree node, int spc)
       && SSA_NAME_RANGE_INFO (node))
     {
       wide_int min, max, nonzero_bits;
-      value_range_type range_type = get_range_info (node, &min, &max);
+      bool wrapped;
+      value_range_type range_type = get_range_info (node, &min, &max, &wrapped);
 
       if (range_type == VR_VARYING)
 	pp_printf (buffer, "# RANGE VR_VARYING");
       else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE)
 	{
 	  pp_printf (buffer, "# RANGE ");
+	  pp_printf (buffer, "WRAPPED  = %s ", wrapped ? "true" : "false");
 	  pp_printf (buffer, "%s[", range_type == VR_RANGE ? "" : "~");
 	  pp_wide_int (buffer, min, TYPE_SIGN (TREE_TYPE (node)));
 	  pp_printf (buffer, ", ");
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 07a9ec5..8955bb8 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -262,7 +262,7 @@  get_range_pos_neg (tree arg)
   if (TREE_CODE (arg) != SSA_NAME)
     return 3;
   wide_int arg_min, arg_max;
-  while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+  while (get_range_info (arg, &arg_min, &arg_max, NULL) != VR_RANGE)
     {
       gimple g = SSA_NAME_DEF_STMT (arg);
       if (is_gimple_assign (g)
@@ -344,7 +344,7 @@  get_min_precision (tree arg, signop sign)
   if (TREE_CODE (arg) != SSA_NAME)
     return prec + (orig_sign != sign);
   wide_int arg_min, arg_max;
-  while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+  while (get_range_info (arg, &arg_min, &arg_max, NULL) != VR_RANGE)
     {
       gimple g = SSA_NAME_DEF_STMT (arg);
       if (is_gimple_assign (g)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
index a84ba8e..67a2afc 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp92.c
@@ -18,6 +18,6 @@  int foo (int i, int j)
   return j;
 }
 
-/* { dg-final { scan-tree-dump "res_.: \\\[1, 1\\\]" "vrp1" } } */
+/* { dg-final { scan-tree-dump "res_.: NOWRAPP \\\[1, 1\\\]" "vrp1" } } */
 /* { dg-final { scan-tree-dump-not "Threaded" "vrp1" } } */
 /* { dg-final { cleanup-tree-dump "vrp1" } } */
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index 5ae8e6c..637588c 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -574,8 +574,8 @@  fini_copy_prop (void)
 		   && !SSA_NAME_RANGE_INFO (copy_of[i].value)
 		   && var_bb == copy_of_bb)
 	    duplicate_ssa_name_range_info (copy_of[i].value,
-					   SSA_NAME_RANGE_TYPE (var),
-					   SSA_NAME_RANGE_INFO (var));
+					   SSA_NAME_RANGE_INFO (var),
+					   SSA_NAME_RANGE_WRAPPED_P (var));
 	}
     }
 
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 9aba79b..3c97fb2 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1245,7 +1245,6 @@  move_computations_dom_walker::before_dom_children (basic_block bb)
 	{
 	  tree lhs = gimple_assign_lhs (new_stmt);
 	  SSA_NAME_RANGE_INFO (lhs) = NULL;
-	  SSA_NAME_ANTI_RANGE_P (lhs) = 0;
 	}
       gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
       remove_phi_node (&bsi, false);
@@ -1315,7 +1314,6 @@  move_computations_dom_walker::before_dom_children (basic_block bb)
 	{
 	  tree lhs = gimple_get_lhs (stmt);
 	  SSA_NAME_RANGE_INFO (lhs) = NULL;
-	  SSA_NAME_ANTI_RANGE_P (lhs) = 0;
 	}
       /* In case this is a stmt that is not unconditionally executed
          when the target loop header is executed and the stmt may
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 7b0313a..5655e06 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -165,7 +165,7 @@  determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
       gphi_iterator gsi;
 
       /* Either for VAR itself...  */
-      rtype = get_range_info (var, &minv, &maxv);
+      rtype = get_range_info (var, &minv, &maxv, NULL);
       /* Or for PHI results in loop->header where VAR is used as
 	 PHI argument from the loop preheader edge.  */
       for (gsi = gsi_start_phis (loop->header); !gsi_end_p (gsi); gsi_next (&gsi))
@@ -173,7 +173,7 @@  determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
 	  gphi *phi = gsi.phi ();
 	  wide_int minc, maxc;
 	  if (PHI_ARG_DEF_FROM_EDGE (phi, e) == var
-	      && (get_range_info (gimple_phi_result (phi), &minc, &maxc)
+	      && (get_range_info (gimple_phi_result (phi), &minc, &maxc, NULL)
 		  == VR_RANGE))
 	    {
 	      if (rtype != VR_RANGE)
@@ -192,7 +192,7 @@  determine_value_range (struct loop *loop, tree type, tree var, mpz_t off,
 		     involved.  */
 		  if (wi::gt_p (minv, maxv, sgn))
 		    {
-		      rtype = get_range_info (var, &minv, &maxv);
+		      rtype = get_range_info (var, &minv, &maxv, NULL);
 		      break;
 		    }
 		}
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 497890f..6a61232 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -4107,8 +4107,8 @@  eliminate_dom_walker::before_dom_children (basic_block b)
 		       && !SSA_NAME_RANGE_INFO (sprime)
 		       && b == sprime_b)
 		duplicate_ssa_name_range_info (sprime,
-					       SSA_NAME_RANGE_TYPE (lhs),
-					       SSA_NAME_RANGE_INFO (lhs));
+					       SSA_NAME_RANGE_INFO (lhs),
+					       SSA_NAME_RANGE_WRAPPED_P (lhs));
 	    }
 
 	  /* Inhibit the use of an inserted PHI on a loop header when
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 744dc43..6e49616 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -201,7 +201,7 @@  make_ssa_name_fn (struct function *fn, tree var, gimple stmt)
 
 void
 set_range_info (tree name,
-		const wide_int_ref &min, const wide_int_ref &max)
+		const wide_int_ref &min, const wide_int_ref &max, bool is_wrapped)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
@@ -221,6 +221,7 @@  set_range_info (tree name,
   /* Set the values.  */
   ri->set_min (min);
   ri->set_max (max);
+  SSA_NAME_RANGE_WRAPPED_P (name) = is_wrapped;
 
   /* If it is a range, try to improve nonzero_bits from the min/max.  */
   if (wi::cmp (min, max, TYPE_SIGN (TREE_TYPE (name))) < 0)
@@ -238,7 +239,7 @@  set_range_info (tree name,
    is used to determine if MIN and MAX are valid values.  */
 
 enum value_range_type
-get_range_info (const_tree name, wide_int *min, wide_int *max)
+get_range_info (const_tree name, wide_int *min, wide_int *max, bool *is_wrapped)
 {
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   gcc_assert (min && max);
@@ -266,6 +267,8 @@  get_range_info (const_tree name, wide_int *min, wide_int *max)
       *min = ri->get_min ();
       *max = ri->get_max ();
     }
+  if (is_wrapped)
+    *is_wrapped = SSA_NAME_RANGE_WRAPPED_P (name);
   return range_type;
 }
 
@@ -278,7 +281,8 @@  set_nonzero_bits (tree name, const wide_int_ref &mask)
   if (SSA_NAME_RANGE_INFO (name) == NULL)
     set_range_info (name,
 		    TYPE_MIN_VALUE (TREE_TYPE (name)),
-		    TYPE_MAX_VALUE (TREE_TYPE (name)));
+		    TYPE_MAX_VALUE (TREE_TYPE (name)),
+		    false);
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
   ri->set_nonzero_bits (mask);
 }
@@ -505,14 +509,13 @@  duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
    RANGE_TYPE for use by the SSA name NAME.  */
 void
 duplicate_ssa_name_range_info (tree name,
-			       enum value_range_type range_type ATTRIBUTE_UNUSED,
-			       struct range_info_def *range_info)
+			       struct range_info_def *range_info,
+			       bool is_wrapped)
 {
   struct range_info_def *new_range_info;
 
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   gcc_assert (!SSA_NAME_RANGE_INFO (name));
-  gcc_assert (!SSA_NAME_ANTI_RANGE_P (name));
 
   if (!range_info)
     return;
@@ -523,6 +526,7 @@  duplicate_ssa_name_range_info (tree name,
   new_range_info = static_cast<range_info_def *> (ggc_internal_alloc (size));
   memcpy (new_range_info, range_info, size);
 
+  SSA_NAME_RANGE_WRAPPED_P (name) = is_wrapped;
   SSA_NAME_RANGE_INFO (name) = new_range_info;
 }
 
@@ -547,8 +551,9 @@  duplicate_ssa_name_fn (struct function *fn, tree name, gimple stmt)
       struct range_info_def *old_range_info = SSA_NAME_RANGE_INFO (name);
 
       if (old_range_info)
-	duplicate_ssa_name_range_info (new_name, SSA_NAME_RANGE_TYPE (name),
-				       old_range_info);
+	duplicate_ssa_name_range_info (new_name,
+				       old_range_info,
+				       SSA_NAME_RANGE_WRAPPED_P (name));
     }
 
   return new_name;
diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h
index 0d4b212..7bb33db 100644
--- a/gcc/tree-ssanames.h
+++ b/gcc/tree-ssanames.h
@@ -69,10 +69,10 @@  enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING };
 
 /* Sets the value range to SSA.  */
 extern void set_range_info (tree, const wide_int_ref &,
-			    const wide_int_ref &);
+			    const wide_int_ref &, bool);
 /* Gets the value range from SSA.  */
 extern enum value_range_type get_range_info (const_tree, wide_int *,
-					     wide_int *);
+					     wide_int *, bool *);
 extern void set_nonzero_bits (tree, const wide_int_ref &);
 extern wide_int get_nonzero_bits (const_tree);
 extern void init_ssanames (struct function *, int);
@@ -92,8 +92,9 @@  extern struct ptr_info_def *get_ptr_info (tree);
 extern tree copy_ssa_name_fn (struct function *, tree, gimple);
 extern void duplicate_ssa_name_ptr_info (tree, struct ptr_info_def *);
 extern tree duplicate_ssa_name_fn (struct function *, tree, gimple);
-extern void duplicate_ssa_name_range_info (tree, enum value_range_type,
-					   struct range_info_def *);
+extern void duplicate_ssa_name_range_info (tree,
+					   struct range_info_def *,
+					   bool);
 extern void release_defs (gimple);
 extern void replace_ssa_name_symbol (tree, tree);
 
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 814222b..09ca14d 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -2553,7 +2553,7 @@  vect_recog_divmod_pattern (vec<gimple> *stmts,
 
       wide_int oprnd0_min, oprnd0_max;
       int msb = 1;
-      if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE)
+      if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max, NULL) == VR_RANGE)
 	{
 	  if (!wi::neg_p (oprnd0_min, TYPE_SIGN (itype)))
 	    msb = 0;
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 9b7695d..832c35d 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -103,6 +103,9 @@  struct value_range_d
   tree min;
   tree max;
 
+  /* Set to true if values in this value range could wrapp. */
+  bool is_wrapped;
+
   /* Set of SSA names whose value ranges are equivalent to this one.
      This set is only valid when TYPE is VR_RANGE or VR_ANTI_RANGE.  */
   bitmap equiv;
@@ -110,7 +113,7 @@  struct value_range_d
 
 typedef struct value_range_d value_range_t;
 
-#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
+#define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, false, NULL }
 
 /* Set of SSA names found live during the RPO traversal of the function
    for still active basic-blocks.  */
@@ -447,7 +450,7 @@  set_value_range_to_varying (value_range_t *vr)
 
 static void
 set_value_range (value_range_t *vr, enum value_range_type t, tree min,
-		 tree max, bitmap equiv)
+		 tree max, bool is_wrapped, bitmap equiv)
 {
 #if defined ENABLE_CHECKING
   /* Check the validity of the range.  */
@@ -481,6 +484,7 @@  set_value_range (value_range_t *vr, enum value_range_type t, tree min,
   vr->type = t;
   vr->min = min;
   vr->max = max;
+  vr->is_wrapped = is_wrapped;
 
   /* Since updating the equivalence set involves deep copying the
      bitmaps, only do it if absolutely necessary.  */
@@ -509,7 +513,7 @@  set_value_range (value_range_t *vr, enum value_range_type t, tree min,
 
 static void
 set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
-				  tree min, tree max, bitmap equiv)
+				  tree min, tree max, bool is_wrapped, bitmap equiv)
 {
   /* Use the canonical setters for VR_UNDEFINED and VR_VARYING.  */
   if (t == VR_UNDEFINED)
@@ -527,7 +531,7 @@  set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
   if (TREE_CODE (min) != INTEGER_CST
       || TREE_CODE (max) != INTEGER_CST)
     {
-      set_value_range (vr, t, min, max, equiv);
+      set_value_range (vr, t, min, max, is_wrapped, equiv);
       return;
     }
 
@@ -615,7 +619,7 @@  set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
       return;
     }
 
-  set_value_range (vr, t, min, max, equiv);
+  set_value_range (vr, t, min, max, is_wrapped, equiv);
 }
 
 /* Copy value range FROM into value range TO.  */
@@ -623,7 +627,8 @@  set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
 static inline void
 copy_value_range (value_range_t *to, value_range_t *from)
 {
-  set_value_range (to, from->type, from->min, from->max, from->equiv);
+  set_value_range (to, from->type, from->min, from->max,
+		   from->is_wrapped, from->equiv);
 }
 
 /* Set value range VR to a single value.  This function is only called
@@ -637,7 +642,7 @@  set_value_range_to_value (value_range_t *vr, tree val, bitmap equiv)
   gcc_assert (is_gimple_min_invariant (val));
   if (TREE_OVERFLOW_P (val))
     val = drop_tree_overflow (val);
-  set_value_range (vr, VR_RANGE, val, val, equiv);
+  set_value_range (vr, VR_RANGE, val, val, false, equiv);
 }
 
 /* Set value range VR to a non-negative range of type TYPE.
@@ -663,6 +668,7 @@  set_value_range_to_nonnegative (value_range_t *vr, tree type,
 		   (overflow_infinity
 		    ? positive_overflow_infinity (type)
 		    : TYPE_MAX_VALUE (type)),
+		   false,
 		   vr->equiv);
 }
 
@@ -672,7 +678,7 @@  static inline void
 set_value_range_to_nonnull (value_range_t *vr, tree type)
 {
   tree zero = build_int_cst (type, 0);
-  set_value_range (vr, VR_ANTI_RANGE, zero, zero, vr->equiv);
+  set_value_range (vr, VR_ANTI_RANGE, zero, zero, false, vr->equiv);
 }
 
 
@@ -695,6 +701,7 @@  set_value_range_to_truthvalue (value_range_t *vr, tree type)
   else
     set_value_range (vr, VR_RANGE,
 		     build_int_cst (type, 0), build_int_cst (type, 1),
+		     false,
 		     vr->equiv);
 }
 
@@ -731,7 +738,7 @@  abs_extent_range (value_range_t *vr, tree min, tree max)
       set_value_range_to_varying (vr);
       return;
     }
-  set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
+  set_and_canonicalize_value_range (vr, VR_RANGE, min, max, false, NULL);
 }
 
 
@@ -744,7 +751,7 @@  static value_range_t *
 get_value_range (const_tree var)
 {
   static const struct value_range_d vr_const_varying
-    = { VR_VARYING, NULL_TREE, NULL_TREE, NULL };
+    = { VR_VARYING, NULL_TREE, NULL_TREE, false, NULL };
   value_range_t *vr;
   tree sym;
   unsigned ver = SSA_NAME_VERSION (var);
@@ -842,6 +849,7 @@  update_value_range (const_tree var, value_range_t *new_vr)
   is_new = old_vr->type != new_vr->type
 	   || !vrp_operand_equal_p (old_vr->min, new_vr->min)
 	   || !vrp_operand_equal_p (old_vr->max, new_vr->max)
+	   || old_vr->is_wrapped != new_vr->is_wrapped
 	   || !vrp_bitmap_equal_p (old_vr->equiv, new_vr->equiv);
 
   if (is_new)
@@ -856,6 +864,7 @@  update_value_range (const_tree var, value_range_t *new_vr)
 	set_value_range_to_varying (old_vr);
       else
 	set_value_range (old_vr, new_vr->type, new_vr->min, new_vr->max,
+			 new_vr->is_wrapped,
 			 new_vr->equiv);
     }
 
@@ -1745,10 +1754,10 @@  extract_range_from_assert (value_range_t *vr_p, tree expr)
 	 this for us.  */
       if (cond_code == LE_EXPR)
         set_and_canonicalize_value_range (vr_p, VR_RANGE,
-					  min, max, vr_p->equiv);
+					  min, max, false, vr_p->equiv);
       else if (cond_code == GT_EXPR)
         set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE,
-					  min, max, vr_p->equiv);
+					  min, max, false, vr_p->equiv);
       else
 	gcc_unreachable ();
     }
@@ -1769,7 +1778,7 @@  extract_range_from_assert (value_range_t *vr_p, tree expr)
 	  max = limit;
 	}
 
-      set_value_range (vr_p, range_type, min, max, vr_p->equiv);
+      set_value_range (vr_p, range_type, min, max, false, vr_p->equiv);
 
       /* When asserting the equality VAR == LIMIT and LIMIT is another
 	 SSA name, the new range will also inherit the equivalence set
@@ -1821,7 +1830,7 @@  extract_range_from_assert (value_range_t *vr_p, tree expr)
 	min = max = limit;
 
       set_and_canonicalize_value_range (vr_p, VR_ANTI_RANGE,
-					min, max, vr_p->equiv);
+					min, max, false, vr_p->equiv);
     }
   else if (cond_code == LE_EXPR || cond_code == LT_EXPR)
     {
@@ -1860,7 +1869,7 @@  extract_range_from_assert (value_range_t *vr_p, tree expr)
 		TREE_NO_WARNING (max) = 1;
 	    }
 
-	  set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
+	  set_value_range (vr_p, VR_RANGE, min, max, false, vr_p->equiv);
 	}
     }
   else if (cond_code == GE_EXPR || cond_code == GT_EXPR)
@@ -1900,7 +1909,7 @@  extract_range_from_assert (value_range_t *vr_p, tree expr)
 		TREE_NO_WARNING (min) = 1;
 	    }
 
-	  set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
+	  set_value_range (vr_p, VR_RANGE, min, max, false, vr_p->equiv);
 	}
     }
   else
@@ -1932,7 +1941,7 @@  extract_range_from_ssa_name (value_range_t *vr, tree var)
   if (var_vr->type != VR_VARYING)
     copy_value_range (vr, var_vr);
   else
-    set_value_range (vr, VR_RANGE, var, var, NULL);
+    set_value_range (vr, VR_RANGE, var, var, false, NULL);
 
   add_equivalence (&vr->equiv, var);
 }
@@ -1945,11 +1954,13 @@  extract_range_from_ssa_name (value_range_t *vr, tree var)
    the type does not support it.  */
 
 static tree
-vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
+vrp_int_const_binop (enum tree_code code, tree val1, tree val2, bool *is_wrapped)
 {
   tree res;
 
   res = int_const_binop (code, val1, val2);
+  if (is_wrapped)
+    *is_wrapped = false;
 
   /* If we are using unsigned arithmetic, operate symbolically
      on -INF and +INF as int_const_binop only handles signed overflow.  */
@@ -1993,7 +2004,10 @@  vrp_int_const_binop (enum tree_code code, tree val1, tree val2)
   else if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (val1)))
     /* If the singed operation wraps then int_const_binop has done
        everything we want.  */
-    ;
+    {
+      if (is_wrapped)
+	*is_wrapped = true;
+    }
   /* Signed division of -1/0 overflows and by the time it gets here
      returns NULL_TREE.  */
   else if (!res)
@@ -2187,6 +2201,8 @@  extract_range_from_multiplicative_op_1 (value_range_t *vr,
   tree min, max;
   bool sop;
   int cmp;
+  bool is_wrapped = false;
+  bool t_is_wrapped = false;
 
   /* Multiplications, divisions and shifts are a bit tricky to handle,
      depending on the mix of signs we have in the two ranges, we
@@ -2216,35 +2232,43 @@  extract_range_from_multiplicative_op_1 (value_range_t *vr,
 
   /* Compute the 4 cross operations.  */
   sop = false;
-  val[0] = vrp_int_const_binop (code, vr0->min, vr1->min);
+  val[0] = vrp_int_const_binop (code, vr0->min, vr1->min, &t_is_wrapped);
   if (val[0] == NULL_TREE)
     sop = true;
+  if (t_is_wrapped)
+    is_wrapped = true;
 
   if (vr1->max == vr1->min)
     val[1] = NULL_TREE;
   else
     {
-      val[1] = vrp_int_const_binop (code, vr0->min, vr1->max);
+      val[1] = vrp_int_const_binop (code, vr0->min, vr1->max, &t_is_wrapped);
       if (val[1] == NULL_TREE)
 	sop = true;
+      if (t_is_wrapped)
+	is_wrapped = true;
     }
 
   if (vr0->max == vr0->min)
     val[2] = NULL_TREE;
   else
     {
-      val[2] = vrp_int_const_binop (code, vr0->max, vr1->min);
+      val[2] = vrp_int_const_binop (code, vr0->max, vr1->min, &t_is_wrapped);
       if (val[2] == NULL_TREE)
 	sop = true;
+      if (t_is_wrapped)
+	is_wrapped = true;
     }
 
   if (vr0->min == vr0->max || vr1->min == vr1->max)
     val[3] = NULL_TREE;
   else
     {
-      val[3] = vrp_int_const_binop (code, vr0->max, vr1->max);
+      val[3] = vrp_int_const_binop (code, vr0->max, vr1->max, &t_is_wrapped);
       if (val[3] == NULL_TREE)
 	sop = true;
+      if (t_is_wrapped)
+	is_wrapped = true;
     }
 
   if (sop)
@@ -2324,7 +2348,7 @@  extract_range_from_multiplicative_op_1 (value_range_t *vr,
       set_value_range_to_varying (vr);
     }
   else
-    set_value_range (vr, type, min, max, NULL);
+    set_value_range (vr, type, min, max, is_wrapped, NULL);
 }
 
 /* Extract range information from a binary operation CODE based on
@@ -2341,6 +2365,7 @@  extract_range_from_binary_expr_1 (value_range_t *vr,
   enum value_range_type type;
   tree min = NULL_TREE, max = NULL_TREE;
   int cmp;
+  bool vr_is_wrapped = false;
 
   if (!INTEGRAL_TYPE_P (expr_type)
       && !POINTER_TYPE_P (expr_type))
@@ -2640,6 +2665,7 @@  extract_range_from_binary_expr_1 (value_range_t *vr,
 		 range kind and bounds appropriately.  */
 	      wide_int tmin = wide_int::from (wmin, prec, sgn);
 	      wide_int tmax = wide_int::from (wmax, prec, sgn);
+	      vr_is_wrapped = true;
 	      if (min_ovf == max_ovf)
 		{
 		  /* No overflow or both overflow or underflow.  The
@@ -2792,8 +2818,8 @@  extract_range_from_binary_expr_1 (value_range_t *vr,
 	      /* For operations that make the resulting range directly
 		 proportional to the original ranges, apply the operation to
 		 the same end of each range.  */
-	      min = vrp_int_const_binop (code, vr0.min, vr1.min);
-	      max = vrp_int_const_binop (code, vr0.max, vr1.max);
+	      min = vrp_int_const_binop (code, vr0.min, vr1.min, NULL);
+	      max = vrp_int_const_binop (code, vr0.max, vr1.max, NULL);
 	    }
 	  else if (code == MIN_EXPR)
 	    {
@@ -2917,9 +2943,10 @@  extract_range_from_binary_expr_1 (value_range_t *vr,
 
 	  /* The following should handle the wrapping and selecting
 	     VR_ANTI_RANGE for us.  */
+	  vr_is_wrapped = true;
 	  min = wide_int_to_tree (expr_type, prod0);
 	  max = wide_int_to_tree (expr_type, prod3);
-	  set_and_canonicalize_value_range (vr, VR_RANGE, min, max, NULL);
+	  set_and_canonicalize_value_range (vr, VR_RANGE, min, max, vr_is_wrapped, NULL);
 	  return;
 	}
 
@@ -3287,7 +3314,7 @@  extract_range_from_binary_expr_1 (value_range_t *vr,
       set_value_range_to_varying (vr);
     }
   else
-    set_value_range (vr, type, min, max, NULL);
+    set_value_range (vr, type, min, max, vr_is_wrapped, NULL);
 }
 
 /* Extract range information from a binary expression OP0 CODE OP1 based on
@@ -3336,15 +3363,15 @@  extract_range_from_binary_expr (value_range_t *vr,
 
       /* Try with VR0 and [-INF, OP1].  */
       if (is_gimple_min_invariant (minus_p ? vr0.max : vr0.min))
-	set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, NULL);
+	set_value_range (&n_vr1, VR_RANGE, vrp_val_min (expr_type), op1, false, NULL);
 
       /* Try with VR0 and [OP1, +INF].  */
       else if (is_gimple_min_invariant (minus_p ? vr0.min : vr0.max))
-	set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), NULL);
+	set_value_range (&n_vr1, VR_RANGE, op1, vrp_val_max (expr_type), false, NULL);
 
       /* Try with VR0 and [OP1, OP1].  */
       else
-	set_value_range (&n_vr1, VR_RANGE, op1, op1, NULL);
+	set_value_range (&n_vr1, VR_RANGE, op1, op1, false, NULL);
 
       extract_range_from_binary_expr_1 (vr, code, expr_type, &vr0, &n_vr1);
     }
@@ -3360,15 +3387,15 @@  extract_range_from_binary_expr (value_range_t *vr,
 
       /* Try with [-INF, OP0] and VR1.  */
       if (is_gimple_min_invariant (minus_p ? vr1.max : vr1.min))
-	set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, NULL);
+	set_value_range (&n_vr0, VR_RANGE, vrp_val_min (expr_type), op0, false, NULL);
 
       /* Try with [OP0, +INF] and VR1.  */
       else if (is_gimple_min_invariant (minus_p ? vr1.min : vr1.max))
-	set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), NULL);
+	set_value_range (&n_vr0, VR_RANGE, op0, vrp_val_max (expr_type), false, NULL);
 
       /* Try with [OP0, OP0] and VR1.  */
       else
-	set_value_range (&n_vr0, VR_RANGE, op0, op0, NULL);
+	set_value_range (&n_vr0, VR_RANGE, op0, op0, false, NULL);
 
       extract_range_from_binary_expr_1 (vr, code, expr_type, &n_vr0, &vr1);
     }
@@ -3384,6 +3411,7 @@  extract_range_from_unary_expr_1 (value_range_t *vr,
 				 value_range_t *vr0_, tree op0_type)
 {
   value_range_t vr0 = *vr0_, vrtem0 = VR_INITIALIZER, vrtem1 = VR_INITIALIZER;
+  bool vr_is_wrapped = false;
 
   /* VRP only operates on integral and pointer types.  */
   if (!(INTEGRAL_TYPE_P (op0_type)
@@ -3504,15 +3532,23 @@  extract_range_from_unary_expr_1 (value_range_t *vr,
 	  if (is_overflow_infinity (vr0.min))
 	    new_min = negative_overflow_infinity (outer_type);
 	  else
-	    new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
-				      0, false);
+	    {
+	      if (!int_fits_type_p (vr0.min, outer_type))
+		  vr_is_wrapped = true;
+	      new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
+					0, false);
+	    }
 	  if (is_overflow_infinity (vr0.max))
 	    new_max = positive_overflow_infinity (outer_type);
 	  else
-	    new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
-				      0, false);
+	    {
+	      if (!int_fits_type_p (vr0.max, outer_type))
+		  vr_is_wrapped = true;
+	      new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
+					0, false);
+	    }
 	  set_and_canonicalize_value_range (vr, vr0.type,
-					    new_min, new_max, NULL);
+					    new_min, new_max, vr_is_wrapped, NULL);
 	  return;
 	}
 
@@ -3626,6 +3662,7 @@  extract_range_from_unary_expr_1 (value_range_t *vr,
 	         anti-range.  */
 	      vr0.type = VR_RANGE;
 	      min = build_int_cst (type, 0);
+	      vr_is_wrapped = true;
 	      if (needs_overflow_infinity (type))
 		{
 		  if (supports_overflow_infinity (type))
@@ -3669,7 +3706,7 @@  extract_range_from_unary_expr_1 (value_range_t *vr,
 	  set_value_range_to_varying (vr);
 	}
       else
-	set_value_range (vr, vr0.type, min, max, NULL);
+	set_value_range (vr, vr0.type, min, max, vr_is_wrapped, NULL);
       return;
     }
 
@@ -3763,7 +3800,7 @@  extract_range_from_comparison (value_range_t *vr, enum tree_code code,
       if (is_gimple_min_invariant (val))
 	set_value_range_to_value (vr, val, vr->equiv);
       else
-	set_value_range (vr, VR_RANGE, val, val, vr->equiv);
+	set_value_range (vr, VR_RANGE, val, val, false, vr->equiv);
     }
   else
     /* The result of a comparison is always true or false.  */
@@ -4060,7 +4097,7 @@  extract_range_basic (value_range_t *vr, gimple stmt)
 	  goto bitop_builtin;
 	bitop_builtin:
 	  set_value_range (vr, VR_RANGE, build_int_cst (type, mini),
-			   build_int_cst (type, maxi), NULL);
+			   build_int_cst (type, maxi), false, NULL);
 	  return;
 	default:
 	  break;
@@ -4150,7 +4187,7 @@  extract_range_basic (value_range_t *vr, gimple stmt)
 						  NULL);
 		      else
 			set_value_range (vr, VR_RANGE, build_int_cst (type, 0),
-					 build_int_cst (type, 1), NULL);
+					 build_int_cst (type, 1), false, NULL);
 		    }
 		  else if (types_compatible_p (type, TREE_TYPE (op0))
 			   && types_compatible_p (type, TREE_TYPE (op1)))
@@ -4244,6 +4281,7 @@  adjust_range_with_scev (value_range_t *vr, struct loop *loop,
 {
   tree init, step, chrec, tmin, tmax, min, max, type, tem;
   enum ev_direction dir;
+  bool t_is_wrapped = false, is_wrapped = false;
 
   /* TODO.  Don't adjust anti-ranges.  An anti-range may provide
      better opportunities than a regular range, but I'm not sure.  */
@@ -4339,6 +4377,7 @@  adjust_range_with_scev (value_range_t *vr, struct loop *loop,
 	      /* Likewise if the addition did.  */
 	      if (maxvr.type == VR_RANGE)
 		{
+		  t_is_wrapped = maxvr.is_wrapped;
 		  tmin = maxvr.min;
 		  tmax = maxvr.max;
 		}
@@ -4350,6 +4389,7 @@  adjust_range_with_scev (value_range_t *vr, struct loop *loop,
     {
       min = tmin;
       max = tmax;
+      is_wrapped = t_is_wrapped;
 
       /* For VARYING or UNDEFINED ranges, just about anything we get
 	 from scalar evolutions should be better.  */
@@ -4403,7 +4443,7 @@  adjust_range_with_scev (value_range_t *vr, struct loop *loop,
 	  && is_positive_overflow_infinity (max)))
     return;
 
-  set_value_range (vr, VR_RANGE, min, max, vr->equiv);
+  set_value_range (vr, VR_RANGE, min, max, is_wrapped, vr->equiv);
 }
 
 
@@ -4722,7 +4762,8 @@  dump_value_range (FILE *file, value_range_t *vr)
     {
       tree type = TREE_TYPE (vr->min);
 
-      fprintf (file, "%s[", (vr->type == VR_ANTI_RANGE) ? "~" : "");
+      fprintf (file, "%s %s[", vr->is_wrapped ? "WRAPP" : "NOWRAPP",
+	       (vr->type == VR_ANTI_RANGE) ? "~" : "");
 
       if (is_negative_overflow_infinity (vr->min))
 	fprintf (file, "-INF(OVF)");
@@ -6917,7 +6958,8 @@  remove_range_assertions (void)
 		  {
 		    set_range_info (var,
 				    SSA_NAME_RANGE_INFO (lhs)->get_min (),
-				    SSA_NAME_RANGE_INFO (lhs)->get_max ());
+				    SSA_NAME_RANGE_INFO (lhs)->get_max (),
+				    SSA_NAME_RANGE_WRAPPED_P (lhs));
 		    maybe_set_nonzero_bits (bb, var);
 		  }
 	      }
@@ -8584,7 +8626,9 @@  vrp_intersect_ranges_1 (value_range_t *vr0, value_range_t *vr1)
   /* Make sure to canonicalize the result though as the inversion of a
      VR_RANGE can still be a VR_RANGE.  */
   set_and_canonicalize_value_range (vr0, vr0->type,
-				    vr0->min, vr0->max, vr0->equiv);
+				    vr0->min, vr0->max,
+				    vr0->is_wrapped && vr1->is_wrapped,
+				    vr0->equiv);
   /* If that failed, use the saved original VR0.  */
   if (vr0->type == VR_VARYING)
     {
@@ -8635,7 +8679,7 @@  vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
 
   if (vr0->type == VR_UNDEFINED)
     {
-      set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->equiv);
+      set_value_range (vr0, vr1->type, vr1->min, vr1->max, vr1->is_wrapped, vr1->equiv);
       return;
     }
 
@@ -8689,6 +8733,7 @@  vrp_meet_1 (value_range_t *vr0, value_range_t *vr1)
       return;
     }
   set_and_canonicalize_value_range (vr0, vr0->type, vr0->min, vr0->max,
+				    vr0->is_wrapped && vr1->is_wrapped,
 				    vr0->equiv);
   if (vr0->type == VR_VARYING)
     return;
@@ -8747,6 +8792,7 @@  vrp_visit_phi_node (gphi *phi)
   for (i = 0; i < gimple_phi_num_args (phi); i++)
     {
       edge e = gimple_phi_arg_edge (phi, i);
+      bool is_wrapped = false;
 
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
@@ -8792,6 +8838,7 @@  vrp_visit_phi_node (gphi *phi)
 		      vr_arg.type = VR_RANGE;
 		      vr_arg.min = arg;
 		      vr_arg.max = arg;
+		      vr_arg.is_wrapped = is_wrapped;
 		      vr_arg.equiv = NULL;
 		    }
 		}
@@ -8804,6 +8851,7 @@  vrp_visit_phi_node (gphi *phi)
 	      vr_arg.type = VR_RANGE;
 	      vr_arg.min = arg;
 	      vr_arg.max = arg;
+	      vr_arg.is_wrapped = is_wrapped;
 	      vr_arg.equiv = NULL;
 	    }
 
@@ -10244,7 +10292,7 @@  vrp_finalize (void)
 	      || vr_value[i]->type == VR_ANTI_RANGE))
 	{
 	  if (vr_value[i]->type == VR_RANGE)
-	   set_range_info (name, vr_value[i]->min, vr_value[i]->max);
+	   set_range_info (name, vr_value[i]->min, vr_value[i]->max, vr_value[i]->is_wrapped);
 	  else if (vr_value[i]->type == VR_ANTI_RANGE)
 	    {
 	      /* VR_ANTI_RANGE
@@ -10259,11 +10307,13 @@  vrp_finalize (void)
 		/* ~[0,0] anti-range is represented as range.  */
 		set_range_info (name,
 				build_int_cst (TREE_TYPE (name), 1),
-				TYPE_MAXVAL (TREE_TYPE (name)));
+				TYPE_MAXVAL (TREE_TYPE (name)),
+				vr_value[i]->is_wrapped);
 	      else
 		set_range_info (name,
 				wi::add (vr_value[i]->max, 1),
-				wi::sub (vr_value[i]->min, 1));
+				wi::sub (vr_value[i]->min, 1),
+				vr_value[i]->is_wrapped);
 	    }
 	}
 
diff --git a/gcc/tree.h b/gcc/tree.h
index ac27268..946321a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1467,7 +1467,7 @@  extern void protected_set_expr_location (tree, location_t);
    SSA_NAME_CHECK (N)->ssa_name.info.ptr_info
 
 /* True if SSA_NAME_RANGE_INFO describes an anti-range.  */
-#define SSA_NAME_ANTI_RANGE_P(N) \
+#define SSA_NAME_RANGE_WRAPPED_P(N) \
     SSA_NAME_CHECK (N)->base.static_flag
 
 /* The type of range described by SSA_NAME_RANGE_INFO.  */