Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2017-07-13 09:18:51.646771977 +0100
+++ gcc/emit-rtl.c	2017-07-13 09:18:54.682546579 +0100
@@ -599,7 +599,8 @@ lookup_const_wide_int (rtx wint)
 immed_wide_int_const (const wide_int_ref &v, machine_mode mode)
 {
   unsigned int len = v.get_len ();
-  unsigned int prec = GET_MODE_PRECISION (mode);
+  /* Not scalar_int_mode because we also allow pointer bound modes.  */
+  unsigned int prec = GET_MODE_PRECISION (as_a <scalar_mode> (mode));
 
   /* Allow truncation but not extension since we do not know if the
      number is signed or unsigned.  */
@@ -659,18 +660,10 @@ immed_double_const (HOST_WIDE_INT i0, HO
         (i.e., i1 consists only from copies of the sign bit, and sign
 	of i0 and i1 are the same), then we return a CONST_INT for i0.
      3) Otherwise, we create a CONST_DOUBLE for i0 and i1.  */
-  if (mode != VOIDmode)
-    {
-      gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
-		  || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT
-		  /* We can get a 0 for an error mark.  */
-		  || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
-		  || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
-		  || GET_MODE_CLASS (mode) == MODE_POINTER_BOUNDS);
-
-      if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
-	return gen_int_mode (i0, mode);
-    }
+  scalar_mode smode;
+  if (is_a <scalar_mode> (mode, &smode)
+      && GET_MODE_BITSIZE (smode) <= HOST_BITS_PER_WIDE_INT)
+    return gen_int_mode (i0, mode);
 
   /* If this integer fits in one word, return a CONST_INT.  */
   if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0))
Index: gcc/explow.c
===================================================================
--- gcc/explow.c	2017-07-13 09:18:51.647771901 +0100
+++ gcc/explow.c	2017-07-13 09:18:54.682546579 +0100
@@ -49,14 +49,16 @@ static rtx break_out_memory_refs (rtx);
 HOST_WIDE_INT
 trunc_int_for_mode (HOST_WIDE_INT c, machine_mode mode)
 {
-  int width = GET_MODE_PRECISION (mode);
+  /* Not scalar_int_mode because we also allow pointer bound modes.  */
+  scalar_mode smode = as_a <scalar_mode> (mode);
+  int width = GET_MODE_PRECISION (smode);
 
   /* You want to truncate to a _what_?  */
   gcc_assert (SCALAR_INT_MODE_P (mode)
 	      || POINTER_BOUNDS_MODE_P (mode));
 
   /* Canonicalize BImode to 0 and STORE_FLAG_VALUE.  */
-  if (mode == BImode)
+  if (smode == BImode)
     return c & 1 ? STORE_FLAG_VALUE : 0;
 
   /* Sign-extend for the requested mode.  */
Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2017-07-13 09:18:51.662770770 +0100
+++ gcc/rtl.h	2017-07-13 09:18:54.682546579 +0100
@@ -2120,8 +2120,7 @@ typedef std::pair <rtx, machine_mode> rt
 inline unsigned int
 wi::int_traits <rtx_mode_t>::get_precision (const rtx_mode_t &x)
 {
-  gcc_checking_assert (x.second != BLKmode && x.second != VOIDmode);
-  return GET_MODE_PRECISION (x.second);
+  return GET_MODE_PRECISION (as_a <scalar_mode> (x.second));
 }
 
 inline wi::storage_ref
@@ -2166,7 +2165,7 @@ wi::int_traits <rtx_mode_t>::decompose (
 inline wi::hwi_with_prec
 wi::shwi (HOST_WIDE_INT val, machine_mode mode)
 {
-  return shwi (val, GET_MODE_PRECISION (mode));
+  return shwi (val, GET_MODE_PRECISION (as_a <scalar_mode> (mode)));
 }
 
 /* Produce the smallest number that is represented in MODE.  The precision
@@ -2174,7 +2173,7 @@ wi::shwi (HOST_WIDE_INT val, machine_mod
 inline wide_int
 wi::min_value (machine_mode mode, signop sgn)
 {
-  return min_value (GET_MODE_PRECISION (mode), sgn);
+  return min_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
 }
 
 /* Produce the largest number that is represented in MODE.  The precision
@@ -2182,7 +2181,7 @@ wi::min_value (machine_mode mode, signop
 inline wide_int
 wi::max_value (machine_mode mode, signop sgn)
 {
-  return max_value (GET_MODE_PRECISION (mode), sgn);
+  return max_value (GET_MODE_PRECISION (as_a <scalar_mode> (mode)), sgn);
 }
 
 extern void init_rtlanal (void);
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c	2017-07-13 09:18:51.644772127 +0100
+++ gcc/dwarf2out.c	2017-07-13 09:18:54.681546653 +0100
@@ -15781,10 +15781,11 @@ loc_descriptor (rtx rtl, machine_mode mo
 	     or a floating-point constant.  A CONST_DOUBLE is used whenever
 	     the constant requires more than one word in order to be
 	     adequately represented.  We output CONST_DOUBLEs as blocks.  */
+	  scalar_mode smode = as_a <scalar_mode> (mode);
 	  loc_result = new_loc_descr (DW_OP_implicit_value,
-				      GET_MODE_SIZE (mode), 0);
+				      GET_MODE_SIZE (smode), 0);
 #if TARGET_SUPPORTS_WIDE_INT == 0
-	  if (!SCALAR_FLOAT_MODE_P (mode))
+	  if (!SCALAR_FLOAT_MODE_P (smode))
 	    {
 	      loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double;
 	      loc_result->dw_loc_oprnd2.v.val_double
@@ -15793,7 +15794,7 @@ loc_descriptor (rtx rtl, machine_mode mo
 	  else
 #endif
 	    {
-	      unsigned int length = GET_MODE_SIZE (mode);
+	      unsigned int length = GET_MODE_SIZE (smode);
 	      unsigned char *array = ggc_vec_alloc<unsigned char> (length);
 
 	      insert_float (rtl, array);
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c	2017-07-13 09:18:53.276650175 +0100
+++ gcc/simplify-rtx.c	2017-07-13 09:18:54.683546506 +0100
@@ -5785,7 +5785,7 @@ simplify_immed_subreg (machine_mode oute
 
 	case CONST_WIDE_INT:
 	  {
-	    rtx_mode_t val = rtx_mode_t (el, innermode);
+	    rtx_mode_t val = rtx_mode_t (el, GET_MODE_INNER (innermode));
 	    unsigned char extend = wi::sign_mask (val);
 	    int prec = wi::get_precision (val);
 
