diff mbox

[18/67] Make int_mode_for_mode return an opt_scalar_int_mode

Message ID 87bmwlmexa.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Dec. 9, 2016, 1:04 p.m. UTC
Also use int_mode_for_mode instead of (int_)mode_for_size
in cases where the requested size was the bitsize of an
existing mode.

gcc/
2016-11-24  Richard Sandiford  <richard.sandiford@arm.com>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>

	* machmode.h (opt_mode::else_blk): New function.
	(int_mode_for_mode): Declare.
	* stor-layout.c (int_mode_for_mode): Return an opt_scalar_int_mode.
	* builtins.c (expand_builtin_signbit): Adjust for new int_mode_for_mode
	return type.
	* cfgexpand.c (expand_debug_expr): Likewise.
	* combine.c (gen_lowpart_or_truncate): Likewise.
	(gen_lowpart_for_combine): Likewise.
	* config/aarch64/aarch64.c (aarch64_emit_approx_sqrt): Likewise.
	* config/avr/avr.c (avr_to_int_mode): Likewise.
	(avr_out_plus_1): Likewise.
	(avr_out_plus): Likewise.
	(avr_out_round): Likewise.
	* config/i386/i386.c (ix86_split_to_parts): Likewise.
	* config/spu/spu.c (spu_split_immediate): Likewise.
	(spu_expand_mov): Likewise.
	* dse.c (get_stored_val): Likewise.
	* expmed.c (store_bit_field_1): Likewise.
	(convert_extracted_bit_field): Use int_mode_for_mode instead of
	int_mode_for_size.
	(extract_bit_field_1): Adjust for new int_mode_for_mode return type.
	(extract_low_bits): Likewise.
	* expr.c (emit_group_load_1): Likewise.  Separate out the BLKmode
	handling rather than repeating the check.
	(emit_group_store): Likewise.
	(emit_move_via_integer): Adjust for new int_mode_for_mode return type.
	* optabs.c (expand_absneg_bit): Likewise.
	(expand_copysign_absneg): Likewise.
	(expand_copysign_bit): Likewise.
	* tree-if-conv.c (ifcvt_can_use_mask_load_store): Likewise.
	* tree-vect-slp.c (vect_transform_slp_perm_load): Likewise.
	* tree-vect-stmts.c (vect_gen_perm_mask_any): Likewise.
	* var-tracking.c (prepare_call_arguments):  Likewise.
	* config/rs6000/rs6000.c (rs6000_do_expand_vec_perm): Use
	int_mode_for_mode instead of mode_for_size.
diff mbox

Patch

diff --git a/gcc/builtins.c b/gcc/builtins.c
index 655ae27..00a0a73 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -5258,8 +5258,7 @@  expand_builtin_signbit (tree exp, rtx target)
 
   if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
     {
-      imode = int_mode_for_mode (fmode);
-      gcc_assert (imode != BLKmode);
+      imode = *int_mode_for_mode (fmode);
       temp = gen_lowpart (imode, temp);
     }
   else
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 97dc648..3915c97 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -4827,10 +4827,11 @@  expand_debug_expr (tree exp)
 	    }
 	  else
 	    {
-	      machine_mode ifmode = int_mode_for_mode (mode);
-	      machine_mode ihmode = int_mode_for_mode (imode);
+	      scalar_int_mode ifmode;
+	      scalar_int_mode ihmode;
 	      rtx halfsize;
-	      if (ifmode == BLKmode || ihmode == BLKmode)
+	      if (!int_mode_for_mode (mode).exists (&ifmode)
+		  || !int_mode_for_mode (imode).exists (&ihmode))
 		return NULL;
 	      halfsize = GEN_INT (GET_MODE_BITSIZE (ihmode));
 	      re = op0;
diff --git a/gcc/combine.c b/gcc/combine.c
index ed4f755..573c558 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -8416,8 +8416,8 @@  gen_lowpart_or_truncate (machine_mode mode, rtx x)
     {
       /* Bit-cast X into an integer mode.  */
       if (!SCALAR_INT_MODE_P (GET_MODE (x)))
-	x = gen_lowpart (int_mode_for_mode (GET_MODE (x)), x);
-      x = simplify_gen_unary (TRUNCATE, int_mode_for_mode (mode),
+	x = gen_lowpart (*int_mode_for_mode (GET_MODE (x)), x);
+      x = simplify_gen_unary (TRUNCATE, *int_mode_for_mode (mode),
 			      x, GET_MODE (x));
     }
 
@@ -11459,7 +11459,7 @@  gen_lowpart_for_combine (machine_mode omode, rtx x)
 
       if (imode == VOIDmode)
 	{
-	  imode = int_mode_for_mode (omode);
+	  imode = *int_mode_for_mode (omode);
 	  x = gen_lowpart_common (imode, x);
 	  if (x == NULL)
 	    goto fail;
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index f399514..fc2bcad 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -7867,7 +7867,7 @@  aarch64_emit_approx_sqrt (rtx dst, rtx src, bool recp)
     return false;
 
   machine_mode mmsk = mode_for_vector
-		        (int_mode_for_mode (GET_MODE_INNER (mode)),
+			(*int_mode_for_mode (GET_MODE_INNER (mode)),
 			 GET_MODE_NUNITS (mode));
   bool use_approx_sqrt_p = (!recp
 			    && (flag_mlow_precision_sqrt
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index 732e030..e3a611f 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -279,7 +279,7 @@  avr_to_int_mode (rtx x)
 
   return VOIDmode == mode
     ? x
-    : simplify_gen_subreg (int_mode_for_mode (mode), x, mode, 0);
+    : simplify_gen_subreg (*int_mode_for_mode (mode), x, mode, 0);
 }
 
 namespace {
@@ -7485,7 +7485,7 @@  avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
   machine_mode mode = GET_MODE (xop[0]);
 
   /* INT_MODE of the same size.  */
-  machine_mode imode = int_mode_for_mode (mode);
+  scalar_int_mode imode = *int_mode_for_mode (mode);
 
   /* Number of bytes to operate on.  */
   int n_bytes = GET_MODE_SIZE (mode);
@@ -7988,7 +7988,7 @@  avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
   rtx xdest = SET_DEST (xpattern);
   machine_mode mode = GET_MODE (xdest);
-  machine_mode imode = int_mode_for_mode (mode);
+  scalar_int_mode imode = *int_mode_for_mode (mode);
   int n_bytes = GET_MODE_SIZE (mode);
   enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
   enum rtx_code code
@@ -8923,7 +8923,7 @@  const char*
 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
 {
   machine_mode mode = GET_MODE (xop[0]);
-  machine_mode imode = int_mode_for_mode (mode);
+  scalar_int_mode imode = *int_mode_for_mode (mode);
   // The smallest fractional bit not cleared by the rounding is 2^(-RP).
   int fbit = (int) GET_MODE_FBIT (mode);
   double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 0c58dae..0fbb3ed 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -25267,7 +25267,7 @@  ix86_split_to_parts (rtx operand, rtx *parts, machine_mode mode)
 
   if (GET_CODE (operand) == CONST_VECTOR)
     {
-      machine_mode imode = int_mode_for_mode (mode);
+      scalar_int_mode imode = *int_mode_for_mode (mode);
       /* Caution: if we looked through a constant pool memory above,
 	 the operand may actually have a different mode now.  That's
 	 ok, since we want to pun this all the way back to an integer.  */
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 08a069d..06aae77 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -37185,10 +37185,8 @@  rs6000_do_expand_vec_perm (rtx target, rtx op0, rtx op1,
 
   imode = vmode;
   if (GET_MODE_CLASS (vmode) != MODE_VECTOR_INT)
-    {
-      imode = mode_for_size (GET_MODE_UNIT_BITSIZE (vmode), MODE_INT, 0);
-      imode = mode_for_vector (imode, nelt);
-    }
+    imode = mode_for_vector (*int_mode_for_mode (GET_MODE_INNER (vmode)),
+			     nelt);
 
   x = gen_rtx_CONST_VECTOR (imode, gen_rtvec_v (nelt, perm));
   x = expand_vec_perm (vmode, op0, op1, x, target);
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 4fb6daf..e8fd572 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -1492,10 +1492,9 @@  spu_split_immediate (rtx * ops)
 	unsigned char arrlo[16];
 	rtx to, temp, hi, lo;
 	int i;
-	machine_mode imode = mode;
 	/* We need to do reals as ints because the constant used in the
 	   IOR might not be a legitimate real constant. */
-	imode = int_mode_for_mode (mode);
+	scalar_int_mode imode = *int_mode_for_mode (mode);
 	constant_to_array (mode, ops[1], arrhi);
 	if (imode != mode)
 	  to = simplify_gen_subreg (imode, ops[0], mode, 0);
@@ -1521,10 +1520,9 @@  spu_split_immediate (rtx * ops)
 	unsigned char arr_andbi[16];
 	rtx to, reg_fsmbi, reg_and;
 	int i;
-	machine_mode imode = mode;
 	/* We need to do reals as ints because the constant used in the
 	 * AND might not be a legitimate real constant. */
-	imode = int_mode_for_mode (mode);
+	scalar_int_mode imode = *int_mode_for_mode (mode);
 	constant_to_array (mode, ops[1], arr_fsmbi);
 	if (imode != mode)
 	  to = simplify_gen_subreg(imode, ops[0], GET_MODE (ops[0]), 0);
@@ -4429,7 +4427,7 @@  spu_expand_mov (rtx * ops, machine_mode mode)
   if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1]))
     {
       rtx from = SUBREG_REG (ops[1]);
-      machine_mode imode = int_mode_for_mode (GET_MODE (from));
+      scalar_int_mode imode = *int_mode_for_mode (GET_MODE (from));
 
       gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
 		  && GET_MODE_CLASS (imode) == MODE_INT
diff --git a/gcc/dse.c b/gcc/dse.c
index ef7a5c8..c8e22a7 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1734,12 +1734,12 @@  get_stored_val (store_info *store_info, machine_mode read_mode,
     {
       /* The store is a memset (addr, const_val, const_size).  */
       gcc_assert (CONST_INT_P (store_info->rhs));
-      store_mode = int_mode_for_mode (read_mode);
-      if (store_mode == BLKmode)
+      scalar_int_mode int_store_mode;
+      if (!int_mode_for_mode (read_mode).exists (&int_store_mode))
 	read_reg = NULL_RTX;
       else if (store_info->rhs == const0_rtx)
-	read_reg = extract_low_bits (read_mode, store_mode, const0_rtx);
-      else if (GET_MODE_BITSIZE (store_mode) > HOST_BITS_PER_WIDE_INT
+	read_reg = extract_low_bits (read_mode, int_store_mode, const0_rtx);
+      else if (GET_MODE_BITSIZE (int_store_mode) > HOST_BITS_PER_WIDE_INT
 	       || BITS_PER_UNIT >= HOST_BITS_PER_WIDE_INT)
 	read_reg = NULL_RTX;
       else
@@ -1753,8 +1753,8 @@  get_stored_val (store_info *store_info, machine_mode read_mode,
 	      c |= (c << shift);
 	      shift <<= 1;
 	    }
-	  read_reg = gen_int_mode (c, store_mode);
-	  read_reg = extract_low_bits (read_mode, store_mode, read_reg);
+	  read_reg = gen_int_mode (c, int_store_mode);
+	  read_reg = extract_low_bits (read_mode, int_store_mode, read_reg);
 	}
     }
   else if (store_info->const_rhs
diff --git a/gcc/expmed.c b/gcc/expmed.c
index fea62e6..bc5df87 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -828,19 +828,15 @@  store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
      if we aren't.  This must come after the entire register case above,
      since that case is valid for any mode.  The following cases are only
      valid for integral modes.  */
-  {
-    machine_mode imode = int_mode_for_mode (GET_MODE (op0));
-    if (imode != GET_MODE (op0))
-      {
-	if (MEM_P (op0))
-	  op0 = adjust_bitfield_address_size (op0, imode, 0, MEM_SIZE (op0));
-	else
-	  {
-	    gcc_assert (imode != BLKmode);
-	    op0 = gen_lowpart (imode, op0);
-	  }
-      }
-  }
+  opt_scalar_int_mode imode = int_mode_for_mode (GET_MODE (op0));
+  if (!imode.exists () || *imode != GET_MODE (op0))
+    {
+      if (MEM_P (op0))
+	op0 = adjust_bitfield_address_size (op0, imode.else_blk (),
+					    0, MEM_SIZE (op0));
+      else
+	op0 = gen_lowpart (*imode, op0);
+    }
 
   /* Storing an lsb-aligned field in a register
      can be done with a movstrict instruction.  */
@@ -955,7 +951,7 @@  store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
       && GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
       && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
     {
-      value = gen_reg_rtx (int_mode_for_mode (GET_MODE (value)));
+      value = gen_reg_rtx (*int_mode_for_mode (GET_MODE (value)));
       emit_move_insn (gen_lowpart (GET_MODE (orig_value), value), orig_value);
     }
 
@@ -1419,8 +1415,7 @@  convert_extracted_bit_field (rtx x, machine_mode mode,
      value via a SUBREG.  */
   if (!SCALAR_INT_MODE_P (tmode))
     {
-      scalar_int_mode int_mode
-	= *int_mode_for_size (GET_MODE_BITSIZE (tmode), 0);
+      scalar_int_mode int_mode = *int_mode_for_mode (tmode);
       x = convert_to_mode (int_mode, x, unsignedp);
       x = force_reg (int_mode, x);
       return gen_lowpart (tmode, x);
@@ -1525,7 +1520,6 @@  extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 		     bool reverse, bool fallback_p)
 {
   rtx op0 = str_rtx;
-  machine_mode int_mode;
   machine_mode mode1;
 
   if (tmode == VOIDmode)
@@ -1611,30 +1605,29 @@  extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* Make sure we are playing with integral modes.  Pun with subregs
      if we aren't.  */
-  {
-    machine_mode imode = int_mode_for_mode (GET_MODE (op0));
-    if (imode != GET_MODE (op0))
-      {
-	if (MEM_P (op0))
-	  op0 = adjust_bitfield_address_size (op0, imode, 0, MEM_SIZE (op0));
-	else if (imode != BLKmode)
-	  {
-	    op0 = gen_lowpart (imode, op0);
+  opt_scalar_int_mode imode = int_mode_for_mode (GET_MODE (op0));
+  if (!imode.exists () || *imode != GET_MODE (op0))
+    {
+      if (MEM_P (op0))
+	op0 = adjust_bitfield_address_size (op0, imode.else_blk (),
+					    0, MEM_SIZE (op0));
+      else if (imode.exists ())
+	{
+	  op0 = gen_lowpart (*imode, op0);
 
-	    /* If we got a SUBREG, force it into a register since we
-	       aren't going to be able to do another SUBREG on it.  */
-	    if (GET_CODE (op0) == SUBREG)
-	      op0 = force_reg (imode, op0);
-	  }
-	else
-	  {
-	    HOST_WIDE_INT size = GET_MODE_SIZE (GET_MODE (op0));
-	    rtx mem = assign_stack_temp (GET_MODE (op0), size);
-	    emit_move_insn (mem, op0);
-	    op0 = adjust_bitfield_address_size (mem, BLKmode, 0, size);
-	  }
-      }
-  }
+	  /* If we got a SUBREG, force it into a register since we
+	     aren't going to be able to do another SUBREG on it.  */
+	  if (GET_CODE (op0) == SUBREG)
+	    op0 = force_reg (*imode, op0);
+	}
+      else
+	{
+	  HOST_WIDE_INT size = GET_MODE_SIZE (GET_MODE (op0));
+	  rtx mem = assign_stack_temp (GET_MODE (op0), size);
+	  emit_move_insn (mem, op0);
+	  op0 = adjust_bitfield_address_size (mem, BLKmode, 0, size);
+	}
+    }
 
   /* ??? We currently assume TARGET is at least as big as BITSIZE.
      If that's wrong, the solution is to test for it and set TARGET to 0
@@ -1838,11 +1831,11 @@  extract_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize,
 
   /* Find a correspondingly-sized integer field, so we can apply
      shifts and masks to it.  */
-  int_mode = int_mode_for_mode (tmode);
-  if (int_mode == BLKmode)
-    int_mode = int_mode_for_mode (mode);
-  /* Should probably push op0 out to memory and then do a load.  */
-  gcc_assert (int_mode != BLKmode);
+  scalar_int_mode int_mode;
+  if (!int_mode_for_mode (tmode).exists (&int_mode))
+    /* If this fails, we should probably push op0 out to memory and then
+       do a load.  */
+    int_mode = *int_mode_for_mode (mode);
 
   target = extract_fixed_bit_field (int_mode, op0, bitsize, bitnum, target,
 				    unsignedp, reverse);
@@ -2196,9 +2189,8 @@  extract_low_bits (machine_mode mode, machine_mode src_mode, rtx src)
         return x;
     }
 
-  src_int_mode = int_mode_for_mode (src_mode);
-  int_mode = int_mode_for_mode (mode);
-  if (src_int_mode == BLKmode || int_mode == BLKmode)
+  if (!int_mode_for_mode (src_mode).exists (&src_int_mode)
+      || !int_mode_for_mode (mode).exists (&int_mode))
     return NULL_RTX;
 
   if (!MODES_TIEABLE_P (src_int_mode, src_mode))
diff --git a/gcc/expr.c b/gcc/expr.c
index 19b982c..8141016 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2089,17 +2089,17 @@  emit_group_load_1 (rtx *tmps, rtx dst, rtx orig_src, tree type, int ssize)
       && !MEM_P (orig_src)
       && GET_CODE (orig_src) != CONCAT)
     {
-      machine_mode imode = int_mode_for_mode (GET_MODE (orig_src));
-      if (imode == BLKmode)
-	src = assign_stack_temp (GET_MODE (orig_src), ssize);
+      scalar_int_mode imode;
+      if (int_mode_for_mode (GET_MODE (orig_src)).exists (&imode))
+	{
+	  src = gen_reg_rtx (imode);
+	  emit_move_insn (gen_lowpart (GET_MODE (orig_src), src), orig_src);
+	}
       else
-	src = gen_reg_rtx (imode);
-      if (imode != BLKmode)
-	src = gen_lowpart (GET_MODE (orig_src), src);
-      emit_move_insn (src, orig_src);
-      /* ...and back again.  */
-      if (imode != BLKmode)
-	src = gen_lowpart (imode, src);
+	{
+	  src = assign_stack_temp (GET_MODE (orig_src), ssize);
+	  emit_move_insn (src, orig_src);
+	}
       emit_group_load_1 (tmps, dst, src, type, ssize);
       return;
     }
@@ -2361,14 +2361,18 @@  emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
   if (!SCALAR_INT_MODE_P (m)
       && !MEM_P (orig_dst) && GET_CODE (orig_dst) != CONCAT)
     {
-      machine_mode imode = int_mode_for_mode (GET_MODE (orig_dst));
-      if (imode == BLKmode)
-        dst = assign_stack_temp (GET_MODE (orig_dst), ssize);
+      scalar_int_mode imode;
+      if (int_mode_for_mode (GET_MODE (orig_dst)).exists (&imode))
+	{
+	  dst = gen_reg_rtx (imode);
+	  emit_group_store (dst, src, type, ssize);
+	  dst = gen_lowpart (GET_MODE (orig_dst), dst);
+	}
       else
-        dst = gen_reg_rtx (imode);
-      emit_group_store (dst, src, type, ssize);
-      if (imode != BLKmode)
-        dst = gen_lowpart (GET_MODE (orig_dst), dst);
+	{
+	  dst = assign_stack_temp (GET_MODE (orig_dst), ssize);
+	  emit_group_store (dst, src, type, ssize);
+	}
       emit_move_insn (orig_dst, dst);
       return;
     }
@@ -3276,12 +3280,11 @@  emit_move_change_mode (machine_mode new_mode,
 static rtx_insn *
 emit_move_via_integer (machine_mode mode, rtx x, rtx y, bool force)
 {
-  machine_mode imode;
+  scalar_int_mode imode;
   enum insn_code code;
 
   /* There must exist a mode of the exact size we require.  */
-  imode = int_mode_for_mode (mode);
-  if (imode == BLKmode)
+  if (!int_mode_for_mode (mode).exists (&imode))
     return NULL;
 
   /* The target must support moves in this mode.  */
diff --git a/gcc/machmode.h b/gcc/machmode.h
index db011d3..f1519a8 100644
--- a/gcc/machmode.h
+++ b/gcc/machmode.h
@@ -202,6 +202,7 @@  public:
   ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
   ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
   machine_mode_enum else_void () const;
+  machine_mode_enum else_blk () const;
   T operator * () const;
 
   /* Return true if the object contains a T rather than nothing.  */
@@ -222,6 +223,15 @@  opt_mode<T>::else_void () const
   return m_mode;
 }
 
+/* If the T exists, return its enum value, otherwise return E_BLKmode.  */
+
+template<typename T>
+inline machine_mode_enum
+opt_mode<T>::else_blk () const
+{
+  return m_mode == E_VOIDmode ? E_BLKmode : m_mode;
+}
+
 /* Assert that the object contains a T and return it.  */
 
 template<typename T>
@@ -583,10 +593,9 @@  extern machine_mode smallest_mode_for_size (unsigned int,
 						 enum mode_class);
 
 
-/* Return an integer mode of the exact same size as the input mode,
-   or BLKmode on failure.  */
+/* Return an integer mode of exactly the same size as the input mode.  */
 
-extern machine_mode int_mode_for_mode (machine_mode);
+extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
 
 extern machine_mode bitwise_mode_for_mode (machine_mode);
 
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 58c26e4..b2c8006 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -2574,8 +2574,7 @@  expand_absneg_bit (enum rtx_code code, scalar_float_mode mode,
 
   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
     {
-      imode = int_mode_for_mode (mode);
-      if (imode == BLKmode)
+      if (!int_mode_for_mode (mode).exists (&imode))
 	return NULL_RTX;
       word = 0;
       nwords = 1;
@@ -3267,8 +3266,7 @@  expand_copysign_absneg (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
     {
       if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
 	{
-	  imode = int_mode_for_mode (mode);
-	  if (imode == BLKmode)
+	  if (!int_mode_for_mode (mode).exists (&imode))
 	    return NULL_RTX;
 	  op1 = gen_lowpart (imode, op1);
 	}
@@ -3330,15 +3328,14 @@  static rtx
 expand_copysign_bit (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
 		     int bitpos, bool op0_is_abs)
 {
-  machine_mode imode;
+  scalar_int_mode imode;
   int word, nwords, i;
   rtx temp;
   rtx_insn *insns;
 
   if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
     {
-      imode = int_mode_for_mode (mode);
-      if (imode == BLKmode)
+      if (!int_mode_for_mode (mode).exists (&imode))
 	return NULL_RTX;
       word = 0;
       nwords = 1;
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 49cce57..6337764 100644
--- a/gcc/stor-layout.c
+++ b/gcc/stor-layout.c
@@ -364,16 +364,16 @@  smallest_mode_for_size (unsigned int size, enum mode_class mclass)
   return mode;
 }
 
-/* Find an integer mode of the exact same size, or BLKmode on failure.  */
+/* Return an integer mode of exactly the same size as MODE, if one exists.  */
 
-machine_mode
+opt_scalar_int_mode
 int_mode_for_mode (machine_mode mode)
 {
   switch (GET_MODE_CLASS (mode))
     {
     case MODE_INT:
     case MODE_PARTIAL_INT:
-      break;
+      return as_a <scalar_int_mode> (mode);
 
     case MODE_COMPLEX_INT:
     case MODE_COMPLEX_FLOAT:
@@ -390,12 +390,11 @@  int_mode_for_mode (machine_mode mode)
     case MODE_VECTOR_UFRACT:
     case MODE_VECTOR_UACCUM:
     case MODE_POINTER_BOUNDS:
-      mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
-      break;
+      return int_mode_for_size (GET_MODE_BITSIZE (mode), 0);
 
     case MODE_RANDOM:
       if (mode == BLKmode)
-	break;
+	return opt_scalar_int_mode ();
 
       /* fall through */
 
@@ -403,8 +402,6 @@  int_mode_for_mode (machine_mode mode)
     default:
       gcc_unreachable ();
     }
-
-  return mode;
 }
 
 /* Find a mode that can be used for efficient bitwise operations on MODE.
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 5716deb..ed6a8b7 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -933,8 +933,7 @@  ifcvt_can_use_mask_load_store (gimple *stmt)
   /* Mask should be integer mode of the same size as the load/store
      mode.  */
   mode = TYPE_MODE (TREE_TYPE (lhs));
-  if (int_mode_for_mode (mode) == BLKmode
-      || VECTOR_MODE_P (mode))
+  if (!int_mode_for_mode (mode).exists () || VECTOR_MODE_P (mode))
     return false;
 
   if (can_vec_mask_load_store_p (mode, VOIDmode, is_load))
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 8d54768..de5c2c0 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -3471,7 +3471,7 @@  vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
   /* The generic VEC_PERM_EXPR code always uses an integral type of the
      same size as the vector element being permuted.  */
   mask_element_type = lang_hooks.types.type_for_mode
-		(int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
+		(*int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
   mask_type = get_vectype_for_scalar_type (mask_element_type);
   nunits = TYPE_VECTOR_SUBPARTS (vectype);
   mask = XALLOCAVEC (unsigned char, nunits);
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 1690cec..d6b281d 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -6417,7 +6417,7 @@  vect_gen_perm_mask_any (tree vectype, const unsigned char *sel)
   nunits = TYPE_VECTOR_SUBPARTS (vectype);
 
   mask_elt_type = lang_hooks.types.type_for_mode
-		    (int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
+		    (*int_mode_for_mode (TYPE_MODE (TREE_TYPE (vectype))), 1);
   mask_type = get_vectype_for_scalar_type (mask_elt_type);
 
   mask_elts = XALLOCAVEC (tree, nunits);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index cd29dc6..a187794 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -6347,8 +6347,9 @@  prepare_call_arguments (basic_block bb, rtx_insn *insn)
 	      {
 		/* For non-integer stack argument see also if they weren't
 		   initialized by integers.  */
-		machine_mode imode = int_mode_for_mode (GET_MODE (mem));
-		if (imode != GET_MODE (mem) && imode != BLKmode)
+		scalar_int_mode imode;
+		if (int_mode_for_mode (GET_MODE (mem)).exists (&imode)
+		    && imode != GET_MODE (mem))
 		  {
 		    val = cselib_lookup (adjust_address_nv (mem, imode, 0),
 					 imode, 0, VOIDmode);