[6/9] Make mode_for_vector return an opt_mode

Message ID 873782itg4.fsf@linaro.org
State New
Headers show
Series
  • Make more use of opt_mode
Related show

Commit Message

Richard Sandiford Sept. 4, 2017, 11:39 a.m.
...following on from the mode_for_size change.  The patch also removes
machmode.h versions of the stor-layout.c comments, since the comments
in the .c file are more complete.

2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* machmode.h (mode_for_vector): Return an opt_mode.
	* stor-layout.c (mode_for_vector): Likewise.
	(mode_for_int_vector): Update accordingly.
	(layout_type): Likewise.
	* config/i386/i386.c (emit_memmov): Likewise.
	(ix86_expand_set_or_movmem): Likewise.
	(ix86_expand_vector_init): Likewise.
	(ix86_get_mask_mode): Likewise.
	* config/powerpcspe/powerpcspe.c (rs6000_expand_vec_perm_const_1):
	Likewise.
	* config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Likewise.
	* expmed.c (extract_bit_field_1): Likewise.
	* expr.c (expand_expr_real_2): Likewise.
	* optabs-query.c (can_vec_perm_p): Likewise.
	(can_vec_mask_load_store_p): Likewise.
	* optabs.c (expand_vec_perm): Likewise.
	* targhooks.c (default_get_mask_mode): Likewise.
	* tree-vect-stmts.c (vectorizable_store): Likewise.
	(vectorizable_load): Likewise.
	(get_vectype_for_scalar_type_and_size): Likewise.

Comments

Richard Biener Sept. 5, 2017, 11:37 a.m. | #1
On Mon, Sep 4, 2017 at 1:39 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> ...following on from the mode_for_size change.  The patch also removes

> machmode.h versions of the stor-layout.c comments, since the comments

> in the .c file are more complete.


Ok.

Richard.

> 2017-09-04  Richard Sandiford  <richard.sandiford@linaro.org>

>

> gcc/

>         * machmode.h (mode_for_vector): Return an opt_mode.

>         * stor-layout.c (mode_for_vector): Likewise.

>         (mode_for_int_vector): Update accordingly.

>         (layout_type): Likewise.

>         * config/i386/i386.c (emit_memmov): Likewise.

>         (ix86_expand_set_or_movmem): Likewise.

>         (ix86_expand_vector_init): Likewise.

>         (ix86_get_mask_mode): Likewise.

>         * config/powerpcspe/powerpcspe.c (rs6000_expand_vec_perm_const_1):

>         Likewise.

>         * config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Likewise.

>         * expmed.c (extract_bit_field_1): Likewise.

>         * expr.c (expand_expr_real_2): Likewise.

>         * optabs-query.c (can_vec_perm_p): Likewise.

>         (can_vec_mask_load_store_p): Likewise.

>         * optabs.c (expand_vec_perm): Likewise.

>         * targhooks.c (default_get_mask_mode): Likewise.

>         * tree-vect-stmts.c (vectorizable_store): Likewise.

>         (vectorizable_load): Likewise.

>         (get_vectype_for_scalar_type_and_size): Likewise.

>

> Index: gcc/machmode.h

> ===================================================================

> --- gcc/machmode.h      2017-09-04 12:18:53.153306182 +0100

> +++ gcc/machmode.h      2017-09-04 12:18:55.821333642 +0100

> @@ -682,8 +682,6 @@ decimal_float_mode_for_size (unsigned in

>      (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));

>  }

>

> -/* Similar to mode_for_size, but find the smallest mode for a given width.  */

> -

>  extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);

>

>  /* Find the narrowest integer mode that contains at least SIZE bits.

> @@ -695,17 +693,9 @@ smallest_int_mode_for_size (unsigned int

>    return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));

>  }

>

> -/* Return an integer mode of exactly the same size as the input mode.  */

> -

>  extern opt_scalar_int_mode int_mode_for_mode (machine_mode);

> -

>  extern machine_mode bitwise_mode_for_mode (machine_mode);

> -

> -/* Return a mode that is suitable for representing a vector,

> -   or BLKmode on failure.  */

> -

> -extern machine_mode mode_for_vector (scalar_mode, unsigned);

> -

> +extern opt_machine_mode mode_for_vector (scalar_mode, unsigned);

>  extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);

>

>  /* Return the integer vector equivalent of MODE, if one exists.  In other

> Index: gcc/stor-layout.c

> ===================================================================

> --- gcc/stor-layout.c   2017-09-04 12:18:53.153306182 +0100

> +++ gcc/stor-layout.c   2017-09-04 12:18:55.824344959 +0100

> @@ -471,11 +471,11 @@ bitwise_type_for_mode (machine_mode mode

>    return inner_type;

>  }

>

> -/* Find a mode that is suitable for representing a vector with

> -   NUNITS elements of mode INNERMODE.  Returns BLKmode if there

> -   is no suitable mode.  */

> +/* Find a mode that is suitable for representing a vector with NUNITS

> +   elements of mode INNERMODE, if one exists.  The returned mode can be

> +   either an integer mode or a vector mode.  */

>

> -machine_mode

> +opt_machine_mode

>  mode_for_vector (scalar_mode innermode, unsigned nunits)

>  {

>    machine_mode mode;

> @@ -499,22 +499,18 @@ mode_for_vector (scalar_mode innermode,

>    FOR_EACH_MODE_FROM (mode, mode)

>      if (GET_MODE_NUNITS (mode) == nunits

>         && GET_MODE_INNER (mode) == innermode)

> -      break;

> +      return mode;

>

>    /* For integers, try mapping it to a same-sized scalar mode.  */

> -  if (mode == VOIDmode

> -      && GET_MODE_CLASS (innermode) == MODE_INT)

> +  if (GET_MODE_CLASS (innermode) == MODE_INT)

>      {

>        unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);

> -      mode = int_mode_for_size (nbits, 0).else_blk ();

> +      if (int_mode_for_size (nbits, 0).exists (&mode)

> +         && have_regs_of_mode[mode])

> +       return mode;

>      }

>

> -  if (mode == VOIDmode

> -      || (GET_MODE_CLASS (mode) == MODE_INT

> -         && !have_regs_of_mode[mode]))

> -    return BLKmode;

> -

> -  return mode;

> +  return opt_machine_mode ();

>  }

>

>  /* Return the mode for a vector that has NUNITS integer elements of

> @@ -525,12 +521,10 @@ mode_for_vector (scalar_mode innermode,

>  mode_for_int_vector (unsigned int int_bits, unsigned int nunits)

>  {

>    scalar_int_mode int_mode;

> -  if (int_mode_for_size (int_bits, 0).exists (&int_mode))

> -    {

> -      machine_mode vec_mode = mode_for_vector (int_mode, nunits);

> -      if (vec_mode != BLKmode)

> -       return vec_mode;

> -    }

> +  machine_mode vec_mode;

> +  if (int_mode_for_size (int_bits, 0).exists (&int_mode)

> +      && mode_for_vector (int_mode, nunits).exists (&vec_mode))

> +    return vec_mode;

>    return opt_machine_mode ();

>  }

>

> @@ -2264,7 +2258,7 @@ layout_type (tree type)

>         if (TYPE_MODE (type) == VOIDmode)

>           SET_TYPE_MODE (type,

>                          mode_for_vector (SCALAR_TYPE_MODE (innertype),

> -                                         nunits));

> +                                         nunits).else_blk ());

>

>         TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));

>          TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));

> Index: gcc/config/i386/i386.c

> ===================================================================

> --- gcc/config/i386/i386.c      2017-09-04 12:18:44.903326171 +0100

> +++ gcc/config/i386/i386.c      2017-09-04 12:18:55.808284598 +0100

> @@ -27420,9 +27420,8 @@ emit_memmov (rtx destmem, rtx *srcmem, r

>    if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))

>      {

>        int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);

> -      move_mode = mode_for_vector (word_mode, nunits);

> -      code = optab_handler (mov_optab, move_mode);

> -      if (code == CODE_FOR_nothing)

> +      if (!mode_for_vector (word_mode, nunits).exists (&move_mode)

> +         || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)

>         {

>           move_mode = word_mode;

>           piece_size = GET_MODE_SIZE (move_mode);

> @@ -28654,8 +28653,8 @@ ix86_expand_set_or_movmem (rtx dst, rtx

>        if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))

>         {

>           int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);

> -         move_mode = mode_for_vector (word_mode, nunits);

> -         if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)

> +         if (!mode_for_vector (word_mode, nunits).exists (&move_mode)

> +             || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)

>             move_mode = word_mode;

>         }

>        gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);

> @@ -44497,11 +44496,9 @@ ix86_expand_vector_init (bool mmx_ok, rt

>           rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };

>           if (inner_mode == QImode || inner_mode == HImode)

>             {

> -             mode = mode_for_vector (SImode,

> -                                     n_elts * GET_MODE_SIZE (inner_mode) / 4);

> -             inner_mode

> -               = mode_for_vector (SImode,

> -                                  n_elts * GET_MODE_SIZE (inner_mode) / 8);

> +             unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);

> +             mode = mode_for_vector (SImode, n_bits / 4).require ();

> +             inner_mode = mode_for_vector (SImode, n_bits / 8).require ();

>               ops[0] = gen_lowpart (inner_mode, ops[0]);

>               ops[1] = gen_lowpart (inner_mode, ops[1]);

>               subtarget = gen_reg_rtx (mode);

> @@ -51619,7 +51616,7 @@ ix86_get_mask_mode (unsigned nunits, uns

>

>    gcc_assert (elem_size * nunits == vector_size);

>

> -  return mode_for_vector (elem_mode, nunits);

> +  return mode_for_vector (elem_mode, nunits).else_blk ();

>  }

>

>

> Index: gcc/config/powerpcspe/powerpcspe.c

> ===================================================================

> --- gcc/config/powerpcspe/powerpcspe.c  2017-09-04 12:18:53.148287319 +0100

> +++ gcc/config/powerpcspe/powerpcspe.c  2017-09-04 12:18:55.812299689 +0100

> @@ -38679,7 +38679,7 @@ rs6000_expand_vec_perm_const_1 (rtx targ

>

>        vmode = GET_MODE (target);

>        gcc_assert (GET_MODE_NUNITS (vmode) == 2);

> -      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);

> +      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();

>        x = gen_rtx_VEC_CONCAT (dmode, op0, op1);

>        v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));

>        x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));

> Index: gcc/config/rs6000/rs6000.c

> ===================================================================

> --- gcc/config/rs6000/rs6000.c  2017-09-04 12:18:53.151298637 +0100

> +++ gcc/config/rs6000/rs6000.c  2017-09-04 12:18:55.815311006 +0100

> @@ -35525,7 +35525,7 @@ rs6000_expand_vec_perm_const_1 (rtx targ

>

>        vmode = GET_MODE (target);

>        gcc_assert (GET_MODE_NUNITS (vmode) == 2);

> -      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);

> +      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();

>        x = gen_rtx_VEC_CONCAT (dmode, op0, op1);

>        v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));

>        x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));

> Index: gcc/expmed.c

> ===================================================================

> --- gcc/expmed.c        2017-09-04 12:18:50.673054653 +0100

> +++ gcc/expmed.c        2017-09-04 12:18:55.817318551 +0100

> @@ -1578,10 +1578,11 @@ extract_bit_field_1 (rtx str_rtx, unsign

>        machine_mode new_mode = GET_MODE (op0);

>        if (GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode))

>         {

> -         new_mode = mode_for_vector (GET_MODE_INNER (tmode),

> -                                     GET_MODE_BITSIZE (GET_MODE (op0))

> -                                     / GET_MODE_UNIT_BITSIZE (tmode));

> -         if (!VECTOR_MODE_P (new_mode)

> +         scalar_mode inner_mode = GET_MODE_INNER (tmode);

> +         unsigned int nunits = (GET_MODE_BITSIZE (GET_MODE (op0))

> +                                / GET_MODE_UNIT_BITSIZE (tmode));

> +         if (!mode_for_vector (inner_mode, nunits).exists (&new_mode)

> +             || !VECTOR_MODE_P (new_mode)

>               || GET_MODE_SIZE (new_mode) != GET_MODE_SIZE (GET_MODE (op0))

>               || GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode)

>               || !targetm.vector_mode_supported_p (new_mode))

> Index: gcc/expr.c

> ===================================================================

> --- gcc/expr.c  2017-09-04 12:18:44.938520082 +0100

> +++ gcc/expr.c  2017-09-04 12:18:55.820329869 +0100

> @@ -9445,7 +9445,7 @@ #define REDUCE_BIT_FIELD(expr)    (reduce_b

>           tree sel_type = TREE_TYPE (treeop2);

>           machine_mode vmode

>             = mode_for_vector (SCALAR_TYPE_MODE (TREE_TYPE (sel_type)),

> -                              TYPE_VECTOR_SUBPARTS (sel_type));

> +                              TYPE_VECTOR_SUBPARTS (sel_type)).require ();

>           gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);

>           op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);

>           gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);

> Index: gcc/optabs-query.c

> ===================================================================

> --- gcc/optabs-query.c  2017-08-30 12:20:31.700622400 +0100

> +++ gcc/optabs-query.c  2017-09-04 12:18:55.821333642 +0100

> @@ -376,10 +376,9 @@ can_vec_perm_p (machine_mode mode, bool

>      return true;

>

>    /* We allow fallback to a QI vector mode, and adjust the mask.  */

> -  if (GET_MODE_INNER (mode) == QImode)

> -    return false;

> -  qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));

> -  if (!VECTOR_MODE_P (qimode))

> +  if (GET_MODE_INNER (mode) == QImode

> +      || !mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode)

> +      || !VECTOR_MODE_P (qimode))

>      return false;

>

>    /* ??? For completeness, we ought to check the QImode version of

> @@ -547,12 +546,14 @@ can_vec_mask_load_store_p (machine_mode

>        vector_sizes &= ~cur;

>        if (cur <= GET_MODE_SIZE (smode))

>         continue;

> -      vmode = mode_for_vector (smode, cur / GET_MODE_SIZE (smode));

> -      mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),

> -                                                  cur);

> -      if (VECTOR_MODE_P (vmode)

> -         && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)

> -       return true;

> +      unsigned int nunits = cur / GET_MODE_SIZE (smode);

> +      if (mode_for_vector (smode, nunits).exists (&vmode)

> +         && VECTOR_MODE_P (vmode))

> +       {

> +         mask_mode = targetm.vectorize.get_mask_mode (nunits, cur);

> +         if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)

> +           return true;

> +       }

>      }

>    return false;

>  }

> Index: gcc/optabs.c

> ===================================================================

> --- gcc/optabs.c        2017-09-04 11:48:08.609549644 +0100

> +++ gcc/optabs.c        2017-09-04 12:18:55.823341187 +0100

> @@ -5434,13 +5434,10 @@ expand_vec_perm (machine_mode mode, rtx

>

>    /* Set QIMODE to a different vector mode with byte elements.

>       If no such mode, or if MODE already has byte elements, use VOIDmode.  */

> -  qimode = VOIDmode;

> -  if (GET_MODE_INNER (mode) != QImode)

> -    {

> -      qimode = mode_for_vector (QImode, w);

> -      if (!VECTOR_MODE_P (qimode))

> -       qimode = VOIDmode;

> -    }

> +  if (GET_MODE_INNER (mode) == QImode

> +      || !mode_for_vector (QImode, w).exists (&qimode)

> +      || !VECTOR_MODE_P (qimode))

> +    qimode = VOIDmode;

>

>    /* If the input is a constant, expand it specially.  */

>    gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);

> Index: gcc/targhooks.c

> ===================================================================

> --- gcc/targhooks.c     2017-09-04 11:50:24.568774867 +0100

> +++ gcc/targhooks.c     2017-09-04 12:18:55.825348732 +0100

> @@ -1210,8 +1210,8 @@ default_get_mask_mode (unsigned nunits,

>

>    gcc_assert (elem_size * nunits == vector_size);

>

> -  vector_mode = mode_for_vector (elem_mode, nunits);

> -  if (!VECTOR_MODE_P (vector_mode)

> +  if (!mode_for_vector (elem_mode, nunits).exists (&vector_mode)

> +      || !VECTOR_MODE_P (vector_mode)

>        || !targetm.vector_mode_supported_p (vector_mode))

>      vector_mode = BLKmode;

>

> Index: gcc/tree-vect-stmts.c

> ===================================================================

> --- gcc/tree-vect-stmts.c       2017-08-31 07:32:43.676061469 +0100

> +++ gcc/tree-vect-stmts.c       2017-09-04 12:18:55.828360049 +0100

> @@ -6032,8 +6032,9 @@ vectorizable_store (gimple *stmt, gimple

>               /* First check if vec_extract optab doesn't support extraction

>                  of vector elts directly.  */

>               scalar_mode elmode = SCALAR_TYPE_MODE (elem_type);

> -             machine_mode vmode = mode_for_vector (elmode, group_size);

> -             if (! VECTOR_MODE_P (vmode)

> +             machine_mode vmode;

> +             if (!mode_for_vector (elmode, group_size).exists (&vmode)

> +                 || !VECTOR_MODE_P (vmode)

>                   || (convert_optab_handler (vec_extract_optab,

>                                              TYPE_MODE (vectype), vmode)

>                       == CODE_FOR_nothing))

> @@ -6046,11 +6047,12 @@ vectorizable_store (gimple *stmt, gimple

>                   unsigned lsize

>                     = group_size * GET_MODE_BITSIZE (elmode);

>                   elmode = int_mode_for_size (lsize, 0).require ();

> -                 vmode = mode_for_vector (elmode, nunits / group_size);

>                   /* If we can't construct such a vector fall back to

>                      element extracts from the original vector type and

>                      element size stores.  */

> -                 if (VECTOR_MODE_P (vmode)

> +                 if (mode_for_vector (elmode,

> +                                      nunits / group_size).exists (&vmode)

> +                     && VECTOR_MODE_P (vmode)

>                       && (convert_optab_handler (vec_extract_optab,

>                                                  vmode, elmode)

>                           != CODE_FOR_nothing))

> @@ -7070,8 +7072,9 @@ vectorizable_load (gimple *stmt, gimple_

>               /* First check if vec_init optab supports construction from

>                  vector elts directly.  */

>               scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vectype));

> -             machine_mode vmode = mode_for_vector (elmode, group_size);

> -             if (VECTOR_MODE_P (vmode)

> +             machine_mode vmode;

> +             if (mode_for_vector (elmode, group_size).exists (&vmode)

> +                 && VECTOR_MODE_P (vmode)

>                   && (convert_optab_handler (vec_init_optab,

>                                              TYPE_MODE (vectype), vmode)

>                       != CODE_FOR_nothing))

> @@ -7092,10 +7095,11 @@ vectorizable_load (gimple *stmt, gimple_

>                   unsigned lsize

>                     = group_size * TYPE_PRECISION (TREE_TYPE (vectype));

>                   elmode = int_mode_for_size (lsize, 0).require ();

> -                 vmode = mode_for_vector (elmode, nunits / group_size);

>                   /* If we can't construct such a vector fall back to

>                      element loads of the original vector type.  */

> -                 if (VECTOR_MODE_P (vmode)

> +                 if (mode_for_vector (elmode,

> +                                      nunits / group_size).exists (&vmode)

> +                     && VECTOR_MODE_P (vmode)

>                       && (convert_optab_handler (vec_init_optab, vmode, elmode)

>                           != CODE_FOR_nothing))

>                     {

> @@ -9098,8 +9102,8 @@ get_vectype_for_scalar_type_and_size (tr

>       lookup a vector mode of the specified size.  */

>    if (size == 0)

>      simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);

> -  else

> -    simd_mode = mode_for_vector (inner_mode, size / nbytes);

> +  else if (!mode_for_vector (inner_mode, size / nbytes).exists (&simd_mode))

> +    return NULL_TREE;

>    nunits = GET_MODE_SIZE (simd_mode) / nbytes;

>    /* NOTE: nunits == 1 is allowed to support single element vector types.  */

>    if (nunits < 1)

Patch

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-09-04 12:18:53.153306182 +0100
+++ gcc/machmode.h	2017-09-04 12:18:55.821333642 +0100
@@ -682,8 +682,6 @@  decimal_float_mode_for_size (unsigned in
     (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
 }
 
-/* Similar to mode_for_size, but find the smallest mode for a given width.  */
-
 extern machine_mode smallest_mode_for_size (unsigned int, enum mode_class);
 
 /* Find the narrowest integer mode that contains at least SIZE bits.
@@ -695,17 +693,9 @@  smallest_int_mode_for_size (unsigned int
   return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
 }
 
-/* Return an integer mode of exactly the same size as the input mode.  */
-
 extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
-
 extern machine_mode bitwise_mode_for_mode (machine_mode);
-
-/* Return a mode that is suitable for representing a vector,
-   or BLKmode on failure.  */
-
-extern machine_mode mode_for_vector (scalar_mode, unsigned);
-
+extern opt_machine_mode mode_for_vector (scalar_mode, unsigned);
 extern opt_machine_mode mode_for_int_vector (unsigned int, unsigned int);
 
 /* Return the integer vector equivalent of MODE, if one exists.  In other
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-09-04 12:18:53.153306182 +0100
+++ gcc/stor-layout.c	2017-09-04 12:18:55.824344959 +0100
@@ -471,11 +471,11 @@  bitwise_type_for_mode (machine_mode mode
   return inner_type;
 }
 
-/* Find a mode that is suitable for representing a vector with
-   NUNITS elements of mode INNERMODE.  Returns BLKmode if there
-   is no suitable mode.  */
+/* Find a mode that is suitable for representing a vector with NUNITS
+   elements of mode INNERMODE, if one exists.  The returned mode can be
+   either an integer mode or a vector mode.  */
 
-machine_mode
+opt_machine_mode
 mode_for_vector (scalar_mode innermode, unsigned nunits)
 {
   machine_mode mode;
@@ -499,22 +499,18 @@  mode_for_vector (scalar_mode innermode,
   FOR_EACH_MODE_FROM (mode, mode)
     if (GET_MODE_NUNITS (mode) == nunits
 	&& GET_MODE_INNER (mode) == innermode)
-      break;
+      return mode;
 
   /* For integers, try mapping it to a same-sized scalar mode.  */
-  if (mode == VOIDmode
-      && GET_MODE_CLASS (innermode) == MODE_INT)
+  if (GET_MODE_CLASS (innermode) == MODE_INT)
     {
       unsigned int nbits = nunits * GET_MODE_BITSIZE (innermode);
-      mode = int_mode_for_size (nbits, 0).else_blk ();
+      if (int_mode_for_size (nbits, 0).exists (&mode)
+	  && have_regs_of_mode[mode])
+	return mode;
     }
 
-  if (mode == VOIDmode
-      || (GET_MODE_CLASS (mode) == MODE_INT
-	  && !have_regs_of_mode[mode]))
-    return BLKmode;
-
-  return mode;
+  return opt_machine_mode ();
 }
 
 /* Return the mode for a vector that has NUNITS integer elements of
@@ -525,12 +521,10 @@  mode_for_vector (scalar_mode innermode,
 mode_for_int_vector (unsigned int int_bits, unsigned int nunits)
 {
   scalar_int_mode int_mode;
-  if (int_mode_for_size (int_bits, 0).exists (&int_mode))
-    {
-      machine_mode vec_mode = mode_for_vector (int_mode, nunits);
-      if (vec_mode != BLKmode)
-	return vec_mode;
-    }
+  machine_mode vec_mode;
+  if (int_mode_for_size (int_bits, 0).exists (&int_mode)
+      && mode_for_vector (int_mode, nunits).exists (&vec_mode))
+    return vec_mode;
   return opt_machine_mode ();
 }
 
@@ -2264,7 +2258,7 @@  layout_type (tree type)
 	if (TYPE_MODE (type) == VOIDmode)
 	  SET_TYPE_MODE (type,
 			 mode_for_vector (SCALAR_TYPE_MODE (innertype),
-					  nunits));
+					  nunits).else_blk ());
 
 	TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type));
         TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type));
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2017-09-04 12:18:44.903326171 +0100
+++ gcc/config/i386/i386.c	2017-09-04 12:18:55.808284598 +0100
@@ -27420,9 +27420,8 @@  emit_memmov (rtx destmem, rtx *srcmem, r
   if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
     {
       int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
-      move_mode = mode_for_vector (word_mode, nunits);
-      code = optab_handler (mov_optab, move_mode);
-      if (code == CODE_FOR_nothing)
+      if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
+	  || (code = optab_handler (mov_optab, move_mode)) == CODE_FOR_nothing)
 	{
 	  move_mode = word_mode;
 	  piece_size = GET_MODE_SIZE (move_mode);
@@ -28654,8 +28653,8 @@  ix86_expand_set_or_movmem (rtx dst, rtx
       if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode))
 	{
 	  int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode);
-	  move_mode = mode_for_vector (word_mode, nunits);
-	  if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
+	  if (!mode_for_vector (word_mode, nunits).exists (&move_mode)
+	      || optab_handler (mov_optab, move_mode) == CODE_FOR_nothing)
 	    move_mode = word_mode;
 	}
       gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing);
@@ -44497,11 +44496,9 @@  ix86_expand_vector_init (bool mmx_ok, rt
 	  rtx ops[2] = { XVECEXP (vals, 0, 0), XVECEXP (vals, 0, 1) };
 	  if (inner_mode == QImode || inner_mode == HImode)
 	    {
-	      mode = mode_for_vector (SImode,
-				      n_elts * GET_MODE_SIZE (inner_mode) / 4);
-	      inner_mode
-		= mode_for_vector (SImode,
-				   n_elts * GET_MODE_SIZE (inner_mode) / 8);
+	      unsigned int n_bits = n_elts * GET_MODE_SIZE (inner_mode);
+	      mode = mode_for_vector (SImode, n_bits / 4).require ();
+	      inner_mode = mode_for_vector (SImode, n_bits / 8).require ();
 	      ops[0] = gen_lowpart (inner_mode, ops[0]);
 	      ops[1] = gen_lowpart (inner_mode, ops[1]);
 	      subtarget = gen_reg_rtx (mode);
@@ -51619,7 +51616,7 @@  ix86_get_mask_mode (unsigned nunits, uns
 
   gcc_assert (elem_size * nunits == vector_size);
 
-  return mode_for_vector (elem_mode, nunits);
+  return mode_for_vector (elem_mode, nunits).else_blk ();
 }
 
 
Index: gcc/config/powerpcspe/powerpcspe.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe.c	2017-09-04 12:18:53.148287319 +0100
+++ gcc/config/powerpcspe/powerpcspe.c	2017-09-04 12:18:55.812299689 +0100
@@ -38679,7 +38679,7 @@  rs6000_expand_vec_perm_const_1 (rtx targ
 
       vmode = GET_MODE (target);
       gcc_assert (GET_MODE_NUNITS (vmode) == 2);
-      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
       x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
       v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
       x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c	2017-09-04 12:18:53.151298637 +0100
+++ gcc/config/rs6000/rs6000.c	2017-09-04 12:18:55.815311006 +0100
@@ -35525,7 +35525,7 @@  rs6000_expand_vec_perm_const_1 (rtx targ
 
       vmode = GET_MODE (target);
       gcc_assert (GET_MODE_NUNITS (vmode) == 2);
-      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4);
+      dmode = mode_for_vector (GET_MODE_INNER (vmode), 4).require ();
       x = gen_rtx_VEC_CONCAT (dmode, op0, op1);
       v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1));
       x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v));
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	2017-09-04 12:18:50.673054653 +0100
+++ gcc/expmed.c	2017-09-04 12:18:55.817318551 +0100
@@ -1578,10 +1578,11 @@  extract_bit_field_1 (rtx str_rtx, unsign
       machine_mode new_mode = GET_MODE (op0);
       if (GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode))
 	{
-	  new_mode = mode_for_vector (GET_MODE_INNER (tmode),
-				      GET_MODE_BITSIZE (GET_MODE (op0))
-				      / GET_MODE_UNIT_BITSIZE (tmode));
-	  if (!VECTOR_MODE_P (new_mode)
+	  scalar_mode inner_mode = GET_MODE_INNER (tmode);
+	  unsigned int nunits = (GET_MODE_BITSIZE (GET_MODE (op0))
+				 / GET_MODE_UNIT_BITSIZE (tmode));
+	  if (!mode_for_vector (inner_mode, nunits).exists (&new_mode)
+	      || !VECTOR_MODE_P (new_mode)
 	      || GET_MODE_SIZE (new_mode) != GET_MODE_SIZE (GET_MODE (op0))
 	      || GET_MODE_INNER (new_mode) != GET_MODE_INNER (tmode)
 	      || !targetm.vector_mode_supported_p (new_mode))
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-09-04 12:18:44.938520082 +0100
+++ gcc/expr.c	2017-09-04 12:18:55.820329869 +0100
@@ -9445,7 +9445,7 @@  #define REDUCE_BIT_FIELD(expr)	(reduce_b
 	  tree sel_type = TREE_TYPE (treeop2);
 	  machine_mode vmode
 	    = mode_for_vector (SCALAR_TYPE_MODE (TREE_TYPE (sel_type)),
-			       TYPE_VECTOR_SUBPARTS (sel_type));
+			       TYPE_VECTOR_SUBPARTS (sel_type)).require ();
 	  gcc_assert (GET_MODE_CLASS (vmode) == MODE_VECTOR_INT);
 	  op2 = simplify_subreg (vmode, op2, TYPE_MODE (sel_type), 0);
 	  gcc_assert (op2 && GET_CODE (op2) == CONST_VECTOR);
Index: gcc/optabs-query.c
===================================================================
--- gcc/optabs-query.c	2017-08-30 12:20:31.700622400 +0100
+++ gcc/optabs-query.c	2017-09-04 12:18:55.821333642 +0100
@@ -376,10 +376,9 @@  can_vec_perm_p (machine_mode mode, bool
     return true;
 
   /* We allow fallback to a QI vector mode, and adjust the mask.  */
-  if (GET_MODE_INNER (mode) == QImode)
-    return false;
-  qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
-  if (!VECTOR_MODE_P (qimode))
+  if (GET_MODE_INNER (mode) == QImode
+      || !mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode)
+      || !VECTOR_MODE_P (qimode))
     return false;
 
   /* ??? For completeness, we ought to check the QImode version of
@@ -547,12 +546,14 @@  can_vec_mask_load_store_p (machine_mode
       vector_sizes &= ~cur;
       if (cur <= GET_MODE_SIZE (smode))
 	continue;
-      vmode = mode_for_vector (smode, cur / GET_MODE_SIZE (smode));
-      mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
-						   cur);
-      if (VECTOR_MODE_P (vmode)
-	  && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
-	return true;
+      unsigned int nunits = cur / GET_MODE_SIZE (smode);
+      if (mode_for_vector (smode, nunits).exists (&vmode)
+	  && VECTOR_MODE_P (vmode))
+	{
+	  mask_mode = targetm.vectorize.get_mask_mode (nunits, cur);
+	  if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
+	    return true;
+	}
     }
   return false;
 }
Index: gcc/optabs.c
===================================================================
--- gcc/optabs.c	2017-09-04 11:48:08.609549644 +0100
+++ gcc/optabs.c	2017-09-04 12:18:55.823341187 +0100
@@ -5434,13 +5434,10 @@  expand_vec_perm (machine_mode mode, rtx
 
   /* Set QIMODE to a different vector mode with byte elements.
      If no such mode, or if MODE already has byte elements, use VOIDmode.  */
-  qimode = VOIDmode;
-  if (GET_MODE_INNER (mode) != QImode)
-    {
-      qimode = mode_for_vector (QImode, w);
-      if (!VECTOR_MODE_P (qimode))
-	qimode = VOIDmode;
-    }
+  if (GET_MODE_INNER (mode) == QImode
+      || !mode_for_vector (QImode, w).exists (&qimode)
+      || !VECTOR_MODE_P (qimode))
+    qimode = VOIDmode;
 
   /* If the input is a constant, expand it specially.  */
   gcc_assert (GET_MODE_CLASS (GET_MODE (sel)) == MODE_VECTOR_INT);
Index: gcc/targhooks.c
===================================================================
--- gcc/targhooks.c	2017-09-04 11:50:24.568774867 +0100
+++ gcc/targhooks.c	2017-09-04 12:18:55.825348732 +0100
@@ -1210,8 +1210,8 @@  default_get_mask_mode (unsigned nunits,
 
   gcc_assert (elem_size * nunits == vector_size);
 
-  vector_mode = mode_for_vector (elem_mode, nunits);
-  if (!VECTOR_MODE_P (vector_mode)
+  if (!mode_for_vector (elem_mode, nunits).exists (&vector_mode)
+      || !VECTOR_MODE_P (vector_mode)
       || !targetm.vector_mode_supported_p (vector_mode))
     vector_mode = BLKmode;
 
Index: gcc/tree-vect-stmts.c
===================================================================
--- gcc/tree-vect-stmts.c	2017-08-31 07:32:43.676061469 +0100
+++ gcc/tree-vect-stmts.c	2017-09-04 12:18:55.828360049 +0100
@@ -6032,8 +6032,9 @@  vectorizable_store (gimple *stmt, gimple
 	      /* First check if vec_extract optab doesn't support extraction
 		 of vector elts directly.  */
 	      scalar_mode elmode = SCALAR_TYPE_MODE (elem_type);
-	      machine_mode vmode = mode_for_vector (elmode, group_size);
-	      if (! VECTOR_MODE_P (vmode)
+	      machine_mode vmode;
+	      if (!mode_for_vector (elmode, group_size).exists (&vmode)
+		  || !VECTOR_MODE_P (vmode)
 		  || (convert_optab_handler (vec_extract_optab,
 					     TYPE_MODE (vectype), vmode)
 		      == CODE_FOR_nothing))
@@ -6046,11 +6047,12 @@  vectorizable_store (gimple *stmt, gimple
 		  unsigned lsize
 		    = group_size * GET_MODE_BITSIZE (elmode);
 		  elmode = int_mode_for_size (lsize, 0).require ();
-		  vmode = mode_for_vector (elmode, nunits / group_size);
 		  /* If we can't construct such a vector fall back to
 		     element extracts from the original vector type and
 		     element size stores.  */
-		  if (VECTOR_MODE_P (vmode)
+		  if (mode_for_vector (elmode,
+				       nunits / group_size).exists (&vmode)
+		      && VECTOR_MODE_P (vmode)
 		      && (convert_optab_handler (vec_extract_optab,
 						 vmode, elmode)
 			  != CODE_FOR_nothing))
@@ -7070,8 +7072,9 @@  vectorizable_load (gimple *stmt, gimple_
 	      /* First check if vec_init optab supports construction from
 		 vector elts directly.  */
 	      scalar_mode elmode = SCALAR_TYPE_MODE (TREE_TYPE (vectype));
-	      machine_mode vmode = mode_for_vector (elmode, group_size);
-	      if (VECTOR_MODE_P (vmode)
+	      machine_mode vmode;
+	      if (mode_for_vector (elmode, group_size).exists (&vmode)
+		  && VECTOR_MODE_P (vmode)
 		  && (convert_optab_handler (vec_init_optab,
 					     TYPE_MODE (vectype), vmode)
 		      != CODE_FOR_nothing))
@@ -7092,10 +7095,11 @@  vectorizable_load (gimple *stmt, gimple_
 		  unsigned lsize
 		    = group_size * TYPE_PRECISION (TREE_TYPE (vectype));
 		  elmode = int_mode_for_size (lsize, 0).require ();
-		  vmode = mode_for_vector (elmode, nunits / group_size);
 		  /* If we can't construct such a vector fall back to
 		     element loads of the original vector type.  */
-		  if (VECTOR_MODE_P (vmode)
+		  if (mode_for_vector (elmode,
+				       nunits / group_size).exists (&vmode)
+		      && VECTOR_MODE_P (vmode)
 		      && (convert_optab_handler (vec_init_optab, vmode, elmode)
 			  != CODE_FOR_nothing))
 		    {
@@ -9098,8 +9102,8 @@  get_vectype_for_scalar_type_and_size (tr
      lookup a vector mode of the specified size.  */
   if (size == 0)
     simd_mode = targetm.vectorize.preferred_simd_mode (inner_mode);
-  else
-    simd_mode = mode_for_vector (inner_mode, size / nbytes);
+  else if (!mode_for_vector (inner_mode, size / nbytes).exists (&simd_mode))
+    return NULL_TREE;
   nunits = GET_MODE_SIZE (simd_mode) / nbytes;
   /* NOTE: nunits == 1 is allowed to support single element vector types.  */
   if (nunits < 1)