[71/77] Use opt_scalar_mode for mode iterators
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 30 Aug 2017 11:20:19 +0000 (11:20 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 30 Aug 2017 11:20:19 +0000 (11:20 +0000)
This patch uses opt_scalar_mode when iterating over scalar modes.

2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* coretypes.h (opt_scalar_mode): New typedef.
* gdbhooks.py (build_pretty_printers): Handle it.
* machmode.h (mode_iterator::get_2xwider): Add overload for
opt_mode<T>.
* emit-rtl.c (init_emit_once): Use opt_scalar_mode when iterating
over scalar modes.
* expr.c (convert_mode_scalar): Likewise.
* omp-low.c (omp_clause_aligned_alignment): Likewise.
* optabs.c (expand_float): Likewise.
(expand_fix): Likewise.
* tree-vect-stmts.c (vectorizable_conversion): Likewise.

gcc/c-family/
* c-common.c (c_common_fixed_point_type_for_size): Use opt_scalar_mode
for the mode iterator.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r251522

gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/coretypes.h
gcc/emit-rtl.c
gcc/expr.c
gcc/gdbhooks.py
gcc/machmode.h
gcc/omp-low.c
gcc/optabs.c
gcc/tree-vect-stmts.c

index c4407d6852d90abaec601bb02dc8db680aa4099d..1f5302a704e122b43b635d536d7f012d07085c62 100644 (file)
@@ -1,3 +1,19 @@
+2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * coretypes.h (opt_scalar_mode): New typedef.
+       * gdbhooks.py (build_pretty_printers): Handle it.
+       * machmode.h (mode_iterator::get_2xwider): Add overload for
+       opt_mode<T>.
+       * emit-rtl.c (init_emit_once): Use opt_scalar_mode when iterating
+       over scalar modes.
+       * expr.c (convert_mode_scalar): Likewise.
+       * omp-low.c (omp_clause_aligned_alignment): Likewise.
+       * optabs.c (expand_float): Likewise.
+       (expand_fix): Likewise.
+       * tree-vect-stmts.c (vectorizable_conversion): Likewise.
+
 2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index a715b57f5e97a6c8b8a5395cbdd43f152b1d98bf..a294404ec2efcf1a331791b0e80706d5ad1576ee 100644 (file)
@@ -1,3 +1,10 @@
+2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * c-common.c (c_common_fixed_point_type_for_size): Use opt_scalar_mode
+       for the mode iterator.
+
 2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 18b2d1acc4ff22882467a6f49ec1406ec2b02982..d959dbc25bbbf8c4246ca11f8913e957ec8160f6 100644 (file)
@@ -2155,12 +2155,16 @@ c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit,
   else
     mclass = unsignedp ? MODE_UACCUM : MODE_ACCUM;
 
-  machine_mode mode;
-  FOR_EACH_MODE_IN_CLASS (mode, mclass)
-    if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit)
-      break;
+  opt_scalar_mode opt_mode;
+  scalar_mode mode;
+  FOR_EACH_MODE_IN_CLASS (opt_mode, mclass)
+    {
+      mode = opt_mode.require ();
+      if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit)
+       break;
+    }
 
-  if (mode == VOIDmode || !targetm.scalar_mode_supported_p (mode))
+  if (!opt_mode.exists (&mode) || !targetm.scalar_mode_supported_p (mode))
     {
       sorry ("GCC cannot support operators with integer types and "
             "fixed-point types that have too many integral and "
index a9f105ceeef8e0083659828988694f3476119321..ffe793e409d8ec0647564e62009e083ce2366b8f 100644 (file)
@@ -59,6 +59,7 @@ class scalar_mode;
 class scalar_int_mode;
 class scalar_float_mode;
 template<typename> class opt_mode;
+typedef opt_mode<scalar_mode> opt_scalar_mode;
 typedef opt_mode<scalar_int_mode> opt_scalar_int_mode;
 typedef opt_mode<scalar_float_mode> opt_scalar_float_mode;
 template<typename> class pod_mode;
index 15c25ec4b4c8910ed5e479cd7dec19d03ade22bf..3954648027c7a429b4f9ef9002766ed48808cd8f 100644 (file)
@@ -5885,6 +5885,7 @@ init_emit_once (void)
   int i;
   machine_mode mode;
   scalar_float_mode double_mode;
+  opt_scalar_mode smode_iter;
 
   /* Initialize the CONST_INT, CONST_WIDE_INT, CONST_DOUBLE,
      CONST_FIXED, and memory attribute hash tables.  */
@@ -5999,62 +6000,66 @@ init_emit_once (void)
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_FRACT)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_FRACT)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-                                     FCONST0 (mode), mode);
+      scalar_mode smode = smode_iter.require ();
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+       = CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_UFRACT)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_UFRACT)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-                                     FCONST0 (mode), mode);
+      scalar_mode smode = smode_iter.require ();
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+       = CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_ACCUM)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_ACCUM)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-                                     FCONST0 (mode), mode);
+      scalar_mode smode = smode_iter.require ();
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+       = CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
 
       /* We store the value 1.  */
-      FCONST1 (mode).data.high = 0;
-      FCONST1 (mode).data.low = 0;
-      FCONST1 (mode).mode = mode;
-      FCONST1 (mode).data
-       = double_int_one.lshift (GET_MODE_FBIT (mode),
+      FCONST1 (smode).data.high = 0;
+      FCONST1 (smode).data.low = 0;
+      FCONST1 (smode).mode = smode;
+      FCONST1 (smode).data
+       = double_int_one.lshift (GET_MODE_FBIT (smode),
                                 HOST_BITS_PER_DOUBLE_INT,
-                                SIGNED_FIXED_POINT_MODE_P (mode));
-      const_tiny_rtx[1][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-                                     FCONST1 (mode), mode);
+                                SIGNED_FIXED_POINT_MODE_P (smode));
+      const_tiny_rtx[1][(int) smode]
+       = CONST_FIXED_FROM_FIXED_VALUE (FCONST1 (smode), smode);
     }
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_UACCUM)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_UACCUM)
     {
-      FCONST0 (mode).data.high = 0;
-      FCONST0 (mode).data.low = 0;
-      FCONST0 (mode).mode = mode;
-      const_tiny_rtx[0][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-                                     FCONST0 (mode), mode);
+      scalar_mode smode = smode_iter.require ();
+      FCONST0 (smode).data.high = 0;
+      FCONST0 (smode).data.low = 0;
+      FCONST0 (smode).mode = smode;
+      const_tiny_rtx[0][(int) smode]
+       = CONST_FIXED_FROM_FIXED_VALUE (FCONST0 (smode), smode);
 
       /* We store the value 1.  */
-      FCONST1 (mode).data.high = 0;
-      FCONST1 (mode).data.low = 0;
-      FCONST1 (mode).mode = mode;
-      FCONST1 (mode).data
-       = double_int_one.lshift (GET_MODE_FBIT (mode),
+      FCONST1 (smode).data.high = 0;
+      FCONST1 (smode).data.low = 0;
+      FCONST1 (smode).mode = smode;
+      FCONST1 (smode).data
+       = double_int_one.lshift (GET_MODE_FBIT (smode),
                                 HOST_BITS_PER_DOUBLE_INT,
-                                SIGNED_FIXED_POINT_MODE_P (mode));
-      const_tiny_rtx[1][(int) mode] = CONST_FIXED_FROM_FIXED_VALUE (
-                                     FCONST1 (mode), mode);
+                                SIGNED_FIXED_POINT_MODE_P (smode));
+      const_tiny_rtx[1][(int) smode]
+       = CONST_FIXED_FROM_FIXED_VALUE (FCONST1 (smode), smode);
     }
 
   FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FRACT)
@@ -6087,10 +6092,11 @@ init_emit_once (void)
   if (STORE_FLAG_VALUE == 1)
     const_tiny_rtx[1][(int) BImode] = const1_rtx;
 
-  FOR_EACH_MODE_IN_CLASS (mode, MODE_POINTER_BOUNDS)
+  FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_POINTER_BOUNDS)
     {
-      wide_int wi_zero = wi::zero (GET_MODE_PRECISION (mode));
-      const_tiny_rtx[0][mode] = immed_wide_int_const (wi_zero, mode);
+      scalar_mode smode = smode_iter.require ();
+      wide_int wi_zero = wi::zero (GET_MODE_PRECISION (smode));
+      const_tiny_rtx[0][smode] = immed_wide_int_const (wi_zero, smode);
     }
 
   pc_rtx = gen_rtx_fmt_ (PC, VOIDmode);
index 7e67f3dd8cae4ccc6ef0b3f422c058056a7a5445..8656f07299934e86bec8812af0d30d4b464d41de 100644 (file)
@@ -559,23 +559,28 @@ convert_mode_scalar (rtx to, rtx from, int unsignedp)
        }
       else
        {
-         machine_mode intermediate;
+         scalar_mode intermediate;
          rtx tmp;
          int shift_amount;
 
          /* Search for a mode to convert via.  */
-         FOR_EACH_MODE_FROM (intermediate, from_mode)
-           if (((can_extend_p (to_mode, intermediate, unsignedp)
-                 != CODE_FOR_nothing)
-                || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
-                    && TRULY_NOOP_TRUNCATION_MODES_P (to_mode, intermediate)))
-               && (can_extend_p (intermediate, from_mode, unsignedp)
-                   != CODE_FOR_nothing))
-             {
-               convert_move (to, convert_to_mode (intermediate, from,
-                                                  unsignedp), unsignedp);
-               return;
-             }
+         opt_scalar_mode intermediate_iter;
+         FOR_EACH_MODE_FROM (intermediate_iter, from_mode)
+           {
+             scalar_mode intermediate = intermediate_iter.require ();
+             if (((can_extend_p (to_mode, intermediate, unsignedp)
+                   != CODE_FOR_nothing)
+                  || (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (intermediate)
+                      && TRULY_NOOP_TRUNCATION_MODES_P (to_mode,
+                                                        intermediate)))
+                 && (can_extend_p (intermediate, from_mode, unsignedp)
+                     != CODE_FOR_nothing))
+               {
+                 convert_move (to, convert_to_mode (intermediate, from,
+                                                    unsignedp), unsignedp);
+                 return;
+               }
+           }
 
          /* No suitable intermediate mode.
             Generate what we need with shifts.  */
index 8799e3fbfd9153436ca0d7d2cc973af533a44517..e5f0cf6f31b9cc1257e366b50a461f1db91534c8 100644 (file)
@@ -543,7 +543,8 @@ def build_pretty_printer():
     pp.add_printer_for_regex(r'opt_mode<(\S+)>',
                              'opt_mode', OptMachineModePrinter)
     pp.add_printer_for_types(['opt_scalar_int_mode',
-                              'opt_scalar_float_mode'],
+                              'opt_scalar_float_mode',
+                              'opt_scalar_mode'],
                              'opt_mode', OptMachineModePrinter)
     pp.add_printer_for_regex(r'pod_mode<(\S+)>',
                              'pod_mode', MachineModePrinter)
index 4586d62b81a29260042bd4c5ccda308b9de714cf..5d84a2eca583ec7181bacfaecd2629f032cceef2 100644 (file)
@@ -835,6 +835,13 @@ namespace mode_iterator
   /* Set mode iterator *ITER to the mode that is two times wider than the
      current one, if such a mode exists.  */
 
+  template<typename T>
+  inline void
+  get_2xwider (opt_mode<T> *iter)
+  {
+    *iter = GET_MODE_2XWIDER_MODE (iter->require ());
+  }
+
   inline void
   get_2xwider (machine_mode *iter)
   {
index 5deb5398c75308441eb91a9e73cbddf62d1621e6..080f2f4a9941f716a24f5538111bb7da57ee29df 100644 (file)
@@ -3442,16 +3442,18 @@ omp_clause_aligned_alignment (tree clause)
 
   /* Otherwise return implementation defined alignment.  */
   unsigned int al = 1;
-  machine_mode mode, vmode;
+  opt_scalar_mode mode_iter;
   int vs = targetm.vectorize.autovectorize_vector_sizes ();
   if (vs)
     vs = 1 << floor_log2 (vs);
   static enum mode_class classes[]
     = { MODE_INT, MODE_VECTOR_INT, MODE_FLOAT, MODE_VECTOR_FLOAT };
   for (int i = 0; i < 4; i += 2)
-    FOR_EACH_MODE_IN_CLASS (mode, classes[i])
+    /* The for loop above dictates that we only walk through scalar classes.  */
+    FOR_EACH_MODE_IN_CLASS (mode_iter, classes[i])
       {
-       vmode = targetm.vectorize.preferred_simd_mode (mode);
+       scalar_mode mode = mode_iter.require ();
+       machine_mode vmode = targetm.vectorize.preferred_simd_mode (mode);
        if (GET_MODE_CLASS (vmode) != classes[i + 1])
          continue;
        while (vs
index d3ceabab8f05c9373ace0193683b348714f8ed7c..d30e4c6233f996b355bf5456cbabfa14b658ffaa 100644 (file)
@@ -4692,6 +4692,7 @@ expand_float (rtx to, rtx from, int unsignedp)
       && is_a <scalar_mode> (GET_MODE (to), &to_mode)
       && is_a <scalar_mode> (GET_MODE (from), &from_mode))
     {
+      opt_scalar_mode fmode_iter;
       rtx_code_label *label = gen_label_rtx ();
       rtx temp;
       REAL_VALUE_TYPE offset;
@@ -4700,12 +4701,15 @@ expand_float (rtx to, rtx from, int unsignedp)
         least as wide as the target.  Using FMODE will avoid rounding woes
         with unsigned values greater than the signed maximum value.  */
 
-      FOR_EACH_MODE_FROM (fmode, to_mode)
-       if (GET_MODE_PRECISION (from_mode) < GET_MODE_BITSIZE (fmode)
-           && can_float_p (fmode, from_mode, 0) != CODE_FOR_nothing)
-         break;
+      FOR_EACH_MODE_FROM (fmode_iter, to_mode)
+       {
+         scalar_mode fmode = fmode_iter.require ();
+         if (GET_MODE_PRECISION (from_mode) < GET_MODE_BITSIZE (fmode)
+             && can_float_p (fmode, from_mode, 0) != CODE_FOR_nothing)
+           break;
+       }
 
-      if (fmode == VOIDmode)
+      if (!fmode_iter.exists (&fmode))
        {
          /* There is no such mode.  Pretend the target is wide enough.  */
          fmode = to_mode;
@@ -4840,6 +4844,7 @@ expand_fix (rtx to, rtx from, int unsignedp)
   enum insn_code icode;
   rtx target = to;
   machine_mode fmode, imode;
+  opt_scalar_mode fmode_iter;
   bool must_trunc = false;
 
   /* We first try to find a pair of modes, one real and one integer, at
@@ -4911,66 +4916,70 @@ expand_fix (rtx to, rtx from, int unsignedp)
   if (unsignedp
       && is_a <scalar_int_mode> (GET_MODE (to), &to_mode)
       && HWI_COMPUTABLE_MODE_P (to_mode))
-    FOR_EACH_MODE_FROM (fmode, GET_MODE (from))
-      if (CODE_FOR_nothing != can_fix_p (to_mode, fmode, 0, &must_trunc)
-         && (!DECIMAL_FLOAT_MODE_P (fmode)
-             || GET_MODE_BITSIZE (fmode) > GET_MODE_PRECISION (to_mode)))
-       {
-         int bitsize;
-         REAL_VALUE_TYPE offset;
-         rtx limit;
-         rtx_code_label *lab1, *lab2;
-         rtx_insn *insn;
-
-         bitsize = GET_MODE_PRECISION (to_mode);
-         real_2expN (&offset, bitsize - 1, fmode);
-         limit = const_double_from_real_value (offset, fmode);
-         lab1 = gen_label_rtx ();
-         lab2 = gen_label_rtx ();
-
-         if (fmode != GET_MODE (from))
-           from = convert_to_mode (fmode, from, 0);
-
-         /* See if we need to do the subtraction.  */
-         do_pending_stack_adjust ();
-         emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX, GET_MODE (from),
-                                  0, lab1);
-
-         /* If not, do the signed "fix" and branch around fixup code.  */
-         expand_fix (to, from, 0);
-         emit_jump_insn (targetm.gen_jump (lab2));
-         emit_barrier ();
-
-         /* Otherwise, subtract 2**(N-1), convert to signed number,
-            then add 2**(N-1).  Do the addition using XOR since this
-            will often generate better code.  */
-         emit_label (lab1);
-         target = expand_binop (GET_MODE (from), sub_optab, from, limit,
-                                NULL_RTX, 0, OPTAB_LIB_WIDEN);
-         expand_fix (to, target, 0);
-         target = expand_binop (to_mode, xor_optab, to,
-                                gen_int_mode
-                                (HOST_WIDE_INT_1 << (bitsize - 1),
-                                 to_mode),
-                                to, 1, OPTAB_LIB_WIDEN);
-
-         if (target != to)
-           emit_move_insn (to, target);
-
-         emit_label (lab2);
-
-         if (optab_handler (mov_optab, to_mode) != CODE_FOR_nothing)
-           {
-             /* Make a place for a REG_NOTE and add it.  */
-             insn = emit_move_insn (to, to);
-             set_dst_reg_note (insn, REG_EQUAL,
-                               gen_rtx_fmt_e (UNSIGNED_FIX, to_mode,
-                                              copy_rtx (from)),
-                               to);
-           }
+    FOR_EACH_MODE_FROM (fmode_iter, as_a <scalar_mode> (GET_MODE (from)))
+      {
+       scalar_mode fmode = fmode_iter.require ();
+       if (CODE_FOR_nothing != can_fix_p (to_mode, fmode,
+                                          0, &must_trunc)
+           && (!DECIMAL_FLOAT_MODE_P (fmode)
+               || (GET_MODE_BITSIZE (fmode) > GET_MODE_PRECISION (to_mode))))
+         {
+           int bitsize;
+           REAL_VALUE_TYPE offset;
+           rtx limit;
+           rtx_code_label *lab1, *lab2;
+           rtx_insn *insn;
+
+           bitsize = GET_MODE_PRECISION (to_mode);
+           real_2expN (&offset, bitsize - 1, fmode);
+           limit = const_double_from_real_value (offset, fmode);
+           lab1 = gen_label_rtx ();
+           lab2 = gen_label_rtx ();
 
-         return;
-       }
+           if (fmode != GET_MODE (from))
+             from = convert_to_mode (fmode, from, 0);
+
+           /* See if we need to do the subtraction.  */
+           do_pending_stack_adjust ();
+           emit_cmp_and_jump_insns (from, limit, GE, NULL_RTX,
+                                    GET_MODE (from), 0, lab1);
+
+           /* If not, do the signed "fix" and branch around fixup code.  */
+           expand_fix (to, from, 0);
+           emit_jump_insn (targetm.gen_jump (lab2));
+           emit_barrier ();
+
+           /* Otherwise, subtract 2**(N-1), convert to signed number,
+              then add 2**(N-1).  Do the addition using XOR since this
+              will often generate better code.  */
+           emit_label (lab1);
+           target = expand_binop (GET_MODE (from), sub_optab, from, limit,
+                                  NULL_RTX, 0, OPTAB_LIB_WIDEN);
+           expand_fix (to, target, 0);
+           target = expand_binop (to_mode, xor_optab, to,
+                                  gen_int_mode
+                                  (HOST_WIDE_INT_1 << (bitsize - 1),
+                                   to_mode),
+                                  to, 1, OPTAB_LIB_WIDEN);
+
+           if (target != to)
+             emit_move_insn (to, target);
+
+           emit_label (lab2);
+
+           if (optab_handler (mov_optab, to_mode) != CODE_FOR_nothing)
+             {
+               /* Make a place for a REG_NOTE and add it.  */
+               insn = emit_move_insn (to, to);
+               set_dst_reg_note (insn, REG_EQUAL,
+                                 gen_rtx_fmt_e (UNSIGNED_FIX, to_mode,
+                                                copy_rtx (from)),
+                                 to);
+             }
+
+           return;
+         }
+      }
 
   /* We can't do it with an insn, so use a library call.  But first ensure
      that the mode of TO is at least as wide as SImode, since those are the
index b8bf5d2b8b0345dcd751e03b2c813c8ce3abf6c8..14089a65659d26ebdc01e336d6e8f0f2ab13fcbb 100644 (file)
@@ -4212,8 +4212,10 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
      needs to be generated.  */
   gcc_assert (ncopies >= 1);
 
-  machine_mode lhs_mode = SCALAR_TYPE_MODE (lhs_type);
-  machine_mode rhs_mode = SCALAR_TYPE_MODE (rhs_type);
+  bool found_mode = false;
+  scalar_mode lhs_mode = SCALAR_TYPE_MODE (lhs_type);
+  scalar_mode rhs_mode = SCALAR_TYPE_MODE (rhs_type);
+  opt_scalar_mode rhs_mode_iter;
 
   /* Supportable by target?  */
   switch (modifier)
@@ -4247,8 +4249,9 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
        goto unsupported;
 
       fltsz = GET_MODE_SIZE (lhs_mode);
-      FOR_EACH_2XWIDER_MODE (rhs_mode, rhs_mode)
+      FOR_EACH_2XWIDER_MODE (rhs_mode_iter, rhs_mode)
        {
+         rhs_mode = rhs_mode_iter.require ();
          if (GET_MODE_SIZE (rhs_mode) > fltsz)
            break;
 
@@ -4275,10 +4278,13 @@ vectorizable_conversion (gimple *stmt, gimple_stmt_iterator *gsi,
          if (supportable_widening_operation (NOP_EXPR, stmt, cvt_type,
                                              vectype_in, &code1, &code2,
                                              &multi_step_cvt, &interm_types))
-           break;
+           {
+             found_mode = true;
+             break;
+           }
        }
 
-      if (rhs_mode == VOIDmode || GET_MODE_SIZE (rhs_mode) > fltsz)
+      if (!found_mode)
        goto unsupported;
 
       if (GET_MODE_SIZE (rhs_mode) == fltsz)