diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index a90f708..1733073 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -916,7 +916,11 @@ ccp_finalize (void)
 	  unsigned int precision = TYPE_PRECISION (TREE_TYPE (val->value));
 	  wide_int nonzero_bits = wide_int::from (val->mask, precision,
 						  UNSIGNED) | val->value;
-	  nonzero_bits &= get_nonzero_bits (name);
+	  wide_int nonzero_bits_name = get_nonzero_bits (name);
+	  if (precision != nonzero_bits_name.get_precision ())
+	    nonzero_bits = wi::shwi (*nonzero_bits.get_val (),
+				     nonzero_bits_name.get_precision ());
+	  nonzero_bits &= nonzero_bits_name;
 	  set_nonzero_bits (name, nonzero_bits);
 	}
     }
@@ -1852,6 +1856,8 @@ evaluate_stmt (gimple stmt)
     {
       tree lhs = gimple_get_lhs (stmt);
       wide_int nonzero_bits = get_nonzero_bits (lhs);
+      if (TYPE_PRECISION (TREE_TYPE (lhs)) != nonzero_bits.get_precision ())
+	  nonzero_bits = wide_int_to_tree (TREE_TYPE (lhs), nonzero_bits);
       if (nonzero_bits != -1)
 	{
 	  if (!is_constant)
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 3af80a0..459c669 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -192,7 +192,7 @@ set_range_info (tree name, enum value_range_type range_type,
   gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name)));
   gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
   range_info_def *ri = SSA_NAME_RANGE_INFO (name);
-  unsigned int precision = TYPE_PRECISION (TREE_TYPE (name));
+  unsigned int precision = min.get_precision ();
 
   /* Allocate if not available.  */
   if (ri == NULL)
@@ -204,6 +204,15 @@ set_range_info (tree name, enum value_range_type range_type,
       SSA_NAME_RANGE_INFO (name) = ri;
       ri->set_nonzero_bits (wi::shwi (-1, precision));
     }
+  else if (ri->get_min ().get_precision () != precision)
+    {
+      size_t size = (sizeof (range_info_def)
+		     + trailing_wide_ints <3>::extra_size (precision));
+      ri = static_cast<range_info_def *> (ggc_realloc (ri, size));
+      ri->ints.set_precision (precision);
+      SSA_NAME_RANGE_INFO (name) = ri;
+      ri->set_nonzero_bits (wi::shwi (-1, precision));
+    }
 
   /* Record the range type.  */
   if (SSA_NAME_RANGE_TYPE (name) != range_type)
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index d16fd8a..772676a 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "optabs.h"
 #include "tree-ssa-threadedge.h"
 #include "wide-int.h"
+#include "langhooks.h"
 
 
 
@@ -424,6 +425,23 @@ set_value_range_to_varying (value_range_t *vr)
     bitmap_clear (vr->equiv);
 }
 
+/* Normalize min and max to promoted_type if their precision differs.  */
+
+static void
+normalize_int_cst_precision (tree *min, tree *max)
+{
+  if (TREE_CODE (*min) != INTEGER_CST
+	      || TREE_CODE (*max) != INTEGER_CST)
+    return;
+  if (TYPE_PRECISION (TREE_TYPE (*min)) != TYPE_PRECISION (TREE_TYPE (*max)))
+    {
+      tree type = TREE_TYPE (*min);
+      if (TYPE_PRECISION (TREE_TYPE (*min)) < TYPE_PRECISION (TREE_TYPE (*max)))
+	type = TREE_TYPE (*max);
+      *min = wide_int_to_tree (type, *min);
+      *max = wide_int_to_tree (type, *max);
+    }
+}
 
 /* Set value range VR to {T, MIN, MAX, EQUIV}.  */
 
@@ -438,6 +456,8 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min,
       int cmp;
 
       gcc_assert (min && max);
+      gcc_assert (TYPE_PRECISION (TREE_TYPE (min))
+		  == TYPE_PRECISION (TREE_TYPE (max)));
 
       gcc_assert ((!TREE_OVERFLOW_P (min) || is_overflow_infinity (min))
 		  && (!TREE_OVERFLOW_P (max) || is_overflow_infinity (max)));
@@ -597,6 +617,8 @@ set_and_canonicalize_value_range (value_range_t *vr, enum value_range_type t,
       return;
     }
 
+  if (min != NULL_TREE && max != NULL_TREE)
+    normalize_int_cst_precision (&min, &max);
   set_value_range (vr, t, min, max, equiv);
 }
 
@@ -951,6 +973,66 @@ usable_range_p (value_range_t *vr, bool *strict_overflow_p)
   return true;
 }
 
+/* Return the promoted type as defined by PROMOTE_MODE of the target.  */
+
+static tree
+promoted_type (tree type)
+{
+#ifdef PROMOTE_MODE
+  tree new_type;
+  if (!POINTER_TYPE_P (type)
+      && (TREE_CODE (type) != ENUMERAL_TYPE)
+      && INTEGRAL_TYPE_P (type))
+    {
+      enum machine_mode mode = TYPE_MODE (type);
+      int uns = TYPE_SIGN (type);
+      PROMOTE_MODE (mode, uns, type);
+      uns = TYPE_SIGN (type);
+      new_type = lang_hooks.types.type_for_mode (mode, uns);
+      if (TYPE_PRECISION (new_type) > TYPE_PRECISION (type))
+	type = new_type;
+    }
+#endif
+  return type;
+}
+
+/* Promote VRO to promoted_type if their precision differ and
+   return the new type.  */
+
+static tree
+promote_unary_vr (tree type, value_range_t *vr0)
+{
+  tree expr_type = type;
+
+  if (!range_int_cst_p (vr0))
+    return expr_type;
+  if ((TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (vr0->min)))
+      || (TYPE_PRECISION (type) != TYPE_PRECISION (TREE_TYPE (vr0->max))))
+    {
+      expr_type = promoted_type (type);
+      vr0->min = wide_int_to_tree (expr_type, vr0->min);
+      vr0->max = wide_int_to_tree (expr_type, vr0->max);
+    }
+  return expr_type;
+}
+
+/* Promote VRO and VR1 to promoted_type if their precision differ and
+   return the new type.  */
+
+static tree
+promote_binary_vr (tree type, value_range_t *vr0, value_range_t *vr1)
+{
+  tree expr_type0 = promote_unary_vr (type, vr0);
+  tree expr_type1 = promote_unary_vr (type, vr1);
+
+  if (TYPE_PRECISION (expr_type0) == TYPE_PRECISION (expr_type1))
+    return expr_type0;
+  if (TYPE_PRECISION (expr_type0) < TYPE_PRECISION (expr_type1))
+    return promote_unary_vr (expr_type1, vr0);
+  else
+    return promote_unary_vr (expr_type0, vr1);
+}
+
 
 /* Return true if the result of assignment STMT is know to be non-negative.
    If the return value is based on the assumption that signed overflow is
@@ -1741,6 +1823,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
 		TREE_NO_WARNING (max) = 1;
 	    }
 
+	  normalize_int_cst_precision (&min, &max);
 	  set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
 	}
     }
@@ -1781,6 +1864,7 @@ extract_range_from_assert (value_range_t *vr_p, tree expr)
 		TREE_NO_WARNING (min) = 1;
 	    }
 
+	  normalize_int_cst_precision (&min, &max);
 	  set_value_range (vr_p, VR_RANGE, min, max, vr_p->equiv);
 	}
     }
@@ -2376,6 +2460,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
      range and see what we end up with.  */
   if (code == PLUS_EXPR || code == MINUS_EXPR)
     {
+      /* If any of the value range is in promoted type, promote them all
+	 including the type.  */
+      expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
       /* If we have a PLUS_EXPR with two VR_RANGE integer constant
          ranges compute the precise range for such case if possible.  */
       if (range_int_cst_p (&vr0)
@@ -2562,6 +2649,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == MIN_EXPR
 	   || code == MAX_EXPR)
     {
+      /* If any of the value range is in promoted type, promote them all
+	 including the type.  */
+      expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
       if (vr0.type == VR_RANGE
 	  && !symbolic_range_p (&vr0))
 	{
@@ -2625,6 +2715,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
              <wi::extended_tree <WIDE_INT_MAX_PRECISION * 2> > vrp_int_cst;
 	  vrp_int sizem1 = wi::mask <vrp_int> (prec, false);
 	  vrp_int size = sizem1 + 1;
+	  vrp_int type_min = vrp_int_cst (TYPE_MIN_VALUE (expr_type));
+	  vrp_int type_max = vrp_int_cst (TYPE_MAX_VALUE (expr_type));
 
 	  /* Extend the values using the sign of the result to PREC2.
 	     From here on out, everthing is just signed math no matter
@@ -2697,8 +2789,17 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
 
 	  /* The following should handle the wrapping and selecting
 	     VR_ANTI_RANGE for us.  */
-	  min = wide_int_to_tree (expr_type, prod0);
-	  max = wide_int_to_tree (expr_type, prod3);
+	  if (wi::lts_p (prod0, type_min)
+	      || wi::gts_p (prod3, type_max))
+	    {
+	      min = wide_int_to_tree (promoted_type (expr_type), prod0);
+	      max = wide_int_to_tree (promoted_type (expr_type), prod3);
+	    }
+	  else
+	    {
+	      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);
 	  return;
 	}
@@ -2724,6 +2825,8 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
   else if (code == RSHIFT_EXPR
 	   || code == LSHIFT_EXPR)
     {
+      /* If value range is in promoted type, promote the type as well.  */
+      expr_type = promote_unary_vr (expr_type, &vr0);
       /* If we have a RSHIFT_EXPR with any shift values outside [0..prec-1],
 	 then drop to VR_VARYING.  Outside of this range we get undefined
 	 behavior from the shift operation.  We cannot even trust
@@ -2946,6 +3049,9 @@ extract_range_from_binary_expr_1 (value_range_t *vr,
       wide_int may_be_nonzero0, may_be_nonzero1;
       wide_int must_be_nonzero0, must_be_nonzero1;
 
+      /* If any of the value range is in promoted type, promote them all
+	 including the type.  */
+      expr_type = promote_binary_vr (expr_type, &vr0, &vr1);
       int_cst_range0 = zero_nonzero_bits_from_vr (expr_type, &vr0,
 						  &may_be_nonzero0,
 						  &must_be_nonzero0);
@@ -3224,14 +3330,22 @@ extract_range_from_unary_expr_1 (value_range_t *vr,
 	  tree new_min, new_max;
 	  if (is_overflow_infinity (vr0.min))
 	    new_min = negative_overflow_infinity (outer_type);
-	  else
+	  else if (int_fits_type_p (vr0.min, outer_type))
 	    new_min = force_fit_type (outer_type, wi::to_widest (vr0.min),
 				      0, false);
+	  else
+	    new_min = force_fit_type (promoted_type (outer_type),
+				      wi::to_widest (vr0.min),
+				      0, false);
 	  if (is_overflow_infinity (vr0.max))
 	    new_max = positive_overflow_infinity (outer_type);
-	  else
+	  else if (int_fits_type_p (vr0.min, outer_type))
 	    new_max = force_fit_type (outer_type, wi::to_widest (vr0.max),
 				      0, false);
+	  else
+	    new_max = force_fit_type (promoted_type (outer_type),
+				      wi::to_widest (vr0.max),
+				      0, false);
 	  set_and_canonicalize_value_range (vr, vr0.type,
 					    new_min, new_max, NULL);
 	  return;
@@ -3940,6 +4054,8 @@ adjust_range_with_scev (value_range_t *vr, struct loop *loop,
 	  && is_positive_overflow_infinity (max)))
     return;
 
+  if (min != NULL_TREE && max != NULL_TREE)
+    normalize_int_cst_precision (&min, &max);
   set_value_range (vr, VR_RANGE, min, max, vr->equiv);
 }
 
@@ -6668,6 +6784,8 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p)
       else
 	extract_range_from_assignment (&new_vr, stmt);
 
+      if (range_int_cst_p (&new_vr))
+	normalize_int_cst_precision (&new_vr.min, &new_vr.max);
       if (update_value_range (lhs, &new_vr))
 	{
 	  *output_p = lhs;
@@ -8399,6 +8517,8 @@ vrp_visit_phi_node (gimple phi)
   /* If the new range is different than the previous value, keep
      iterating.  */
 update_range:
+  if (range_int_cst_p (&vr_result))
+    normalize_int_cst_precision (&vr_result.min, &vr_result.max);
   if (update_value_range (lhs, &vr_result))
     {
       if (dump_file && (dump_flags & TDF_DETAILS))
@@ -8655,9 +8775,19 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
   if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr0, &may_be_nonzero0,
 				  &must_be_nonzero0))
     return false;
-  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op1), &vr1, &may_be_nonzero1,
+  if (!zero_nonzero_bits_from_vr (TREE_TYPE (op0), &vr1, &may_be_nonzero1,
 				  &must_be_nonzero1))
     return false;
+  if (TYPE_PRECISION (TREE_TYPE (op0)) != may_be_nonzero0.get_precision ())
+    {
+      may_be_nonzero0 = wide_int_to_tree (TREE_TYPE (op0), may_be_nonzero0);
+      must_be_nonzero0 = wide_int_to_tree (TREE_TYPE (op0), must_be_nonzero0);
+    }
+  if (TYPE_PRECISION (TREE_TYPE (op0)) != may_be_nonzero1.get_precision ())
+    {
+      may_be_nonzero1 = wide_int_to_tree (TREE_TYPE (op1), may_be_nonzero0);
+      must_be_nonzero1 = wide_int_to_tree (TREE_TYPE (op1), must_be_nonzero0);
+    }
 
   switch (gimple_assign_rhs_code (stmt))
     {
@@ -8752,9 +8882,9 @@ test_for_singularity (enum tree_code cond_code, tree op0,
   if (min && max)
     {
       if (compare_values (vr->min, min) == 1)
-	min = vr->min;
+	min = wide_int_to_tree (TREE_TYPE (op0), vr->min);
       if (compare_values (vr->max, max) == -1)
-	max = vr->max;
+	max = wide_int_to_tree (TREE_TYPE (op0), vr->max);
 
       /* If the new min/max values have converged to a single value,
 	 then there is only one value which can satisfy the condition,
@@ -9474,7 +9604,7 @@ simplify_stmt_for_jump_threading (gimple stmt, gimple within_stmt)
 	{
 	  extract_range_from_assignment (&new_vr, stmt);
 	  if (range_int_cst_singleton_p (&new_vr))
-	    return new_vr.min;
+	    return wide_int_to_tree (TREE_TYPE (lhs), new_vr.min);
 	}
     }
 
