diff mbox series

Add support for MODE_VECTOR_BOOL

Message ID 87o9ovte91.fsf@linaro.org
State New
Headers show
Series Add support for MODE_VECTOR_BOOL | expand

Commit Message

Richard Sandiford Oct. 25, 2017, 3:54 p.m. UTC
This patch adds a new mode class to represent vectors of booleans.
GET_MODE_BITSIZE (m) / GET_MODE_NUNITS (m) determines the number
of bits that are used to represent each boolean; this can be 1
for a fully-packed representation or greater than 1 for an unpacked
representation.  In the latter case, the value of bits other than
the lowest is not significant.

These are used by the SVE port to represent predicates.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu,
on top of the poly_int series.  OK to install?

Richard


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

gcc/
	* mode-classes.def (MODE_VECTOR_BOOL): New mode class.
	* machmode.h (INTEGRAL_MODE_P, VECTOR_MODE_P): Return true
	for MODE_VECTOR_BOOL.
	* machmode.def (VECTOR_BOOL_MODE): Document.
	* genmodes.c (VECTOR_BOOL_MODE): New macro.
	(make_vector_bool_mode): New function.
	(complete_mode, emit_mode_wider, emit_mode_adjustments): Handle
	MODE_VECTOR_BOOL.
	* lto-streamer-in.c (lto_input_mode_table): Likewise.
	* stor-layout.c (int_mode_for_mode): Likewise.
	* tree.c (build_vector_type_for_mode): Likewise.
	* varasm.c (output_constant_pool_2): Likewise.
	* emit-rtl.c (gen_const_vec_duplicate): Likewise,
	(init_emit_once): Make sure that CONST1_RTX (BImode) and
	CONSTM1_RTX (BImode) are the same thing.  Initialize const_tiny_rtx
	for MODE_VECTOR_BOOL.
	* expr.c (expand_expr_real_1): Use VECTOR_MODE_P instead of a list
	of mode class checks.
	* tree-vect-generic.c (expand_vector_operation): Use VECTOR_MODE_P
	instead of a list of mode class checks.
	(expand_vector_scalar_condition): Likewise.
	(type_for_widest_vector_mode): Handle BImode as an inner mode.

gcc/c-family/
	* c-common.c (c_common_type_for_mode): Handle MODE_VECTOR_BOOL.

gcc/fortran/
	* trans-types.c (gfc_type_for_mode): Handle MODE_VECTOR_BOOL.

gcc/go/
	* go-lang.c (go_langhook_type_for_mode): Handle MODE_VECTOR_BOOL.

gcc/lto/
	* lto-lang.c (lto_type_for_mode): Handle MODE_VECTOR_BOOL.

Comments

Richard Biener Oct. 25, 2017, 3:57 p.m. UTC | #1
On October 25, 2017 5:54:02 PM GMT+02:00, Richard Sandiford <richard.sandiford@linaro.org> wrote:
>This patch adds a new mode class to represent vectors of booleans.
>GET_MODE_BITSIZE (m) / GET_MODE_NUNITS (m) determines the number
>of bits that are used to represent each boolean; this can be 1
>for a fully-packed representation or greater than 1 for an unpacked
>representation.  In the latter case, the value of bits other than
>the lowest is not significant.
>
>These are used by the SVE port to represent predicates.
>
>Tested on aarch64-linux-gnu, x86_64-linux-gnu and
>powerpc64le-linux-gnu,
>on top of the poly_int series.  OK to install?

AVX uses integer modes for predicates. Can't you do the same thing, with variable size, of course? 

AVX has moves between predicate registers and GPRs. 

Richard. 


>Richard
>
>
>2017-10-25  Richard Sandiford  <richard.sandiford@linaro.org>
>	    Alan Hayward  <alan.hayward@arm.com>
>	    David Sherwood  <david.sherwood@arm.com>
>
>gcc/
>	* mode-classes.def (MODE_VECTOR_BOOL): New mode class.
>	* machmode.h (INTEGRAL_MODE_P, VECTOR_MODE_P): Return true
>	for MODE_VECTOR_BOOL.
>	* machmode.def (VECTOR_BOOL_MODE): Document.
>	* genmodes.c (VECTOR_BOOL_MODE): New macro.
>	(make_vector_bool_mode): New function.
>	(complete_mode, emit_mode_wider, emit_mode_adjustments): Handle
>	MODE_VECTOR_BOOL.
>	* lto-streamer-in.c (lto_input_mode_table): Likewise.
>	* stor-layout.c (int_mode_for_mode): Likewise.
>	* tree.c (build_vector_type_for_mode): Likewise.
>	* varasm.c (output_constant_pool_2): Likewise.
>	* emit-rtl.c (gen_const_vec_duplicate): Likewise,
>	(init_emit_once): Make sure that CONST1_RTX (BImode) and
>	CONSTM1_RTX (BImode) are the same thing.  Initialize const_tiny_rtx
>	for MODE_VECTOR_BOOL.
>	* expr.c (expand_expr_real_1): Use VECTOR_MODE_P instead of a list
>	of mode class checks.
>	* tree-vect-generic.c (expand_vector_operation): Use VECTOR_MODE_P
>	instead of a list of mode class checks.
>	(expand_vector_scalar_condition): Likewise.
>	(type_for_widest_vector_mode): Handle BImode as an inner mode.
>
>gcc/c-family/
>	* c-common.c (c_common_type_for_mode): Handle MODE_VECTOR_BOOL.
>
>gcc/fortran/
>	* trans-types.c (gfc_type_for_mode): Handle MODE_VECTOR_BOOL.
>
>gcc/go/
>	* go-lang.c (go_langhook_type_for_mode): Handle MODE_VECTOR_BOOL.
>
>gcc/lto/
>	* lto-lang.c (lto_type_for_mode): Handle MODE_VECTOR_BOOL.
>
>Index: gcc/mode-classes.def
>===================================================================
>--- gcc/mode-classes.def	2017-10-25 16:50:18.000869425 +0100
>+++ gcc/mode-classes.def	2017-10-25 16:50:35.628184659 +0100
>@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.
> DEF_MODE_CLASS (MODE_DECIMAL_FLOAT),	/* decimal floating point */	   \
>   DEF_MODE_CLASS (MODE_COMPLEX_INT), 	/* complex numbers */		   \
>   DEF_MODE_CLASS (MODE_COMPLEX_FLOAT),					   \
>+  DEF_MODE_CLASS (MODE_VECTOR_BOOL),	/* vectors of single bits */	   \
>   DEF_MODE_CLASS (MODE_VECTOR_INT),	/* SIMD vectors */		   \
>   DEF_MODE_CLASS (MODE_VECTOR_FRACT),	/* SIMD vectors */		   \
>   DEF_MODE_CLASS (MODE_VECTOR_UFRACT),	/* SIMD vectors */		   \
>Index: gcc/machmode.h
>===================================================================
>--- gcc/machmode.h	2017-10-25 16:50:31.832332710 +0100
>+++ gcc/machmode.h	2017-10-25 16:50:35.628184659 +0100
>@@ -108,6 +108,7 @@ #define INTEGRAL_MODE_P(MODE)			\
>   (GET_MODE_CLASS (MODE) == MODE_INT		\
>    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
>    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
>+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
> 
> /* Nonzero if MODE is a floating-point mode.  */
>@@ -123,8 +124,9 @@ #define COMPLEX_MODE_P(MODE)			\
>    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
> 
> /* Nonzero if MODE is a vector mode.  */
>-#define VECTOR_MODE_P(MODE)			\
>-  (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT	\
>+#define VECTOR_MODE_P(MODE)				\
>+  (GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL		\
>+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT		\
>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT	\
>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT	\
>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT	\
>Index: gcc/machmode.def
>===================================================================
>--- gcc/machmode.def	2017-10-25 16:50:18.000869425 +0100
>+++ gcc/machmode.def	2017-10-25 16:50:35.628184659 +0100
>@@ -142,6 +142,12 @@ along with GCC; see the file COPYING3.
> 	than two bytes (if CLASS is FLOAT).  CLASS must be INT or
> 	FLOAT.  The names follow the same rule as VECTOR_MODE uses.
> 
>+     VECTOR_BOOL_MODE (COUNT, BYTESIZE)
>+	Create a vector of booleans with COUNT elements and BYTESIZE bytes.
>+	Each boolean occupies (COUNT * BITS_PER_UNIT) / BYTESIZE bits,
>+	with the element at index 0 occupying the lsb of the first byte
>+	in memory.  Only the lowest bit of each element is significant.
>+
>      COMPLEX_MODES (CLASS);
>         For all modes presently declared in class CLASS, construct
> 	corresponding complex modes.  Modes smaller than one byte
>Index: gcc/genmodes.c
>===================================================================
>--- gcc/genmodes.c	2017-10-25 16:50:31.828332866 +0100
>+++ gcc/genmodes.c	2017-10-25 16:50:35.627184698 +0100
>@@ -375,6 +375,10 @@ complete_mode (struct mode_data *m)
>       m->bytesize = 2 * m->component->bytesize;
>       break;
> 
>+    case MODE_VECTOR_BOOL:
>+      validate_mode (m, UNSET, SET, SET, SET, UNSET);
>+      break;
>+
>     case MODE_VECTOR_INT:
>     case MODE_VECTOR_FLOAT:
>     case MODE_VECTOR_FRACT:
>@@ -526,6 +530,36 @@ make_vector_modes (enum mode_class cl, u
>     }
> }
> 
>+/* Create a vector of booleans with COUNT elements and BYTESIZE bytes
>+   in total.  */
>+#define VECTOR_BOOL_MODE(COUNT, BYTESIZE) \
>+  make_vector_bool_mode (COUNT, BYTESIZE, __FILE__, __LINE__)
>+static void ATTRIBUTE_UNUSED
>+make_vector_bool_mode (unsigned int count, unsigned int bytesize,
>+		       const char *file, unsigned int line)
>+{
>+  struct mode_data *m = find_mode ("BI");
>+  if (!m)
>+    {
>+      error ("%s:%d: no mode \"BI\"", file, line);
>+      return;
>+    }
>+
>+  char buf[8];
>+  if ((size_t) snprintf (buf, sizeof buf, "V%uBI", count) >= sizeof
>buf)
>+    {
>+      error ("%s:%d: number of vector elements is too high",
>+	     file, line);
>+      return;
>+    }
>+
>+  struct mode_data *v = new_mode (MODE_VECTOR_BOOL,
>+				  xstrdup (buf), file, line);
>+  v->component = m;
>+  v->ncomponents = count;
>+  v->bytesize = bytesize;
>+}
>+
> /* Input.  */
> 
> #define _SPECIAL_MODE(C, N) \
>@@ -1438,7 +1472,8 @@ emit_mode_wider (void)
> 
> 	  /* For vectors we want twice the number of components,
> 	     with the same element type.  */
>-	  if (m->cl == MODE_VECTOR_INT
>+	  if (m->cl == MODE_VECTOR_BOOL
>+	      || m->cl == MODE_VECTOR_INT
> 	      || m->cl == MODE_VECTOR_FLOAT
> 	      || m->cl == MODE_VECTOR_FRACT
> 	      || m->cl == MODE_VECTOR_UFRACT
>@@ -1657,6 +1692,7 @@ emit_mode_adjustments (void)
>       printf ("\n  /* %s:%d */\n", a->file, a->line);
>       switch (a->mode->cl)
> 	{
>+	case MODE_VECTOR_BOOL:
> 	case MODE_VECTOR_INT:
> 	case MODE_VECTOR_FLOAT:
> 	case MODE_VECTOR_FRACT:
>@@ -1688,6 +1724,10 @@ emit_mode_adjustments (void)
> 		      m->name);
> 	      break;
> 
>+	    case MODE_VECTOR_BOOL:
>+	      /* Changes to BImode should not affect vector booleans.  */
>+	      break;
>+
> 	    case MODE_VECTOR_INT:
> 	    case MODE_VECTOR_FLOAT:
> 	    case MODE_VECTOR_FRACT:
>@@ -1728,6 +1768,10 @@ emit_mode_adjustments (void)
> 	      printf ("  mode_base_align[E_%smode] = s;\n", m->name);
> 	      break;
> 
>+	    case MODE_VECTOR_BOOL:
>+	      /* Changes to BImode should not affect vector booleans.  */
>+	      break;
>+
> 	    case MODE_VECTOR_INT:
> 	    case MODE_VECTOR_FLOAT:
> 	    case MODE_VECTOR_FRACT:
>Index: gcc/lto-streamer-in.c
>===================================================================
>--- gcc/lto-streamer-in.c	2017-10-25 16:50:31.832332710 +0100
>+++ gcc/lto-streamer-in.c	2017-10-25 16:50:35.628184659 +0100
>@@ -1662,6 +1662,7 @@ lto_input_mode_table (struct lto_file_de
> 	{
> 	  switch (mclass)
> 	    {
>+	    case MODE_VECTOR_BOOL:
> 	    case MODE_VECTOR_INT:
> 	    case MODE_VECTOR_FLOAT:
> 	    case MODE_VECTOR_FRACT:
>Index: gcc/stor-layout.c
>===================================================================
>--- gcc/stor-layout.c	2017-10-25 16:50:24.925601288 +0100
>+++ gcc/stor-layout.c	2017-10-25 16:50:35.629184620 +0100
>@@ -378,12 +378,13 @@ int_mode_for_mode (machine_mode mode)
>     case MODE_COMPLEX_FLOAT:
>     case MODE_FLOAT:
>     case MODE_DECIMAL_FLOAT:
>-    case MODE_VECTOR_INT:
>-    case MODE_VECTOR_FLOAT:
>     case MODE_FRACT:
>     case MODE_ACCUM:
>     case MODE_UFRACT:
>     case MODE_UACCUM:
>+    case MODE_VECTOR_BOOL:
>+    case MODE_VECTOR_INT:
>+    case MODE_VECTOR_FLOAT:
>     case MODE_VECTOR_FRACT:
>     case MODE_VECTOR_ACCUM:
>     case MODE_VECTOR_UFRACT:
>Index: gcc/tree.c
>===================================================================
>--- gcc/tree.c	2017-10-25 16:50:31.843332282 +0100
>+++ gcc/tree.c	2017-10-25 16:50:35.630184581 +0100
>@@ -10561,6 +10561,7 @@ build_vector_type_for_mode (tree innerty
> 
>   switch (GET_MODE_CLASS (mode))
>     {
>+    case MODE_VECTOR_BOOL:
>     case MODE_VECTOR_INT:
>     case MODE_VECTOR_FLOAT:
>     case MODE_VECTOR_FRACT:
>Index: gcc/varasm.c
>===================================================================
>--- gcc/varasm.c	2017-10-25 16:50:24.928601171 +0100
>+++ gcc/varasm.c	2017-10-25 16:50:35.631184542 +0100
>@@ -3926,6 +3926,32 @@ output_constant_pool_2 (fixed_size_mode
>       assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
>       break;
> 
>+    case MODE_VECTOR_BOOL:
>+      {
>+	gcc_assert (GET_CODE (x) == CONST_VECTOR);
>+
>+	/* Pick the smallest integer mode that contains at least one
>+	   whole element.  Often this is byte_mode and contains more
>+	   than one element.  */
>+	unsigned int nelts = CONST_VECTOR_NUNITS (x);
>+	unsigned int elt_bits = GET_MODE_BITSIZE (mode) / nelts;
>+	unsigned int int_bits = MAX (elt_bits, BITS_PER_UNIT);
>+	scalar_int_mode int_mode = int_mode_for_size (int_bits, 0).require
>();
>+
>+	/* Build the constant up one integer at a time.  */
>+	unsigned int elts_per_int = int_bits / elt_bits;
>+	for (unsigned int i = 0; i < nelts; i += elts_per_int)
>+	  {
>+	    unsigned HOST_WIDE_INT value = 0;
>+	    unsigned int limit = MIN (nelts - i, elts_per_int);
>+	    for (unsigned int j = 0; j < limit; ++j)
>+	      if (INTVAL (CONST_VECTOR_ELT (x, i + j)) != 0)
>+		value |= 1 << (j * elt_bits);
>+	    output_constant_pool_2 (int_mode, gen_int_mode (value, int_mode),
>+				    i != 0 ? MIN (align, int_bits) : align);
>+	  }
>+	break;
>+      }
>     case MODE_VECTOR_FLOAT:
>     case MODE_VECTOR_INT:
>     case MODE_VECTOR_FRACT:
>Index: gcc/emit-rtl.c
>===================================================================
>--- gcc/emit-rtl.c	2017-10-25 16:50:31.826332943 +0100
>+++ gcc/emit-rtl.c	2017-10-25 16:50:35.625184776 +0100
>@@ -5960,6 +5960,16 @@ gen_const_vec_duplicate_1 (machine_mode
> rtx
> gen_const_vec_duplicate (machine_mode mode, rtx elt)
> {
>+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
>+    {
>+      if (elt == const1_rtx || elt == constm1_rtx)
>+	return CONST1_RTX (mode);
>+      else if (elt == const0_rtx)
>+	return CONST0_RTX (mode);
>+      else
>+	gcc_unreachable ();
>+    }
>+
>   scalar_mode inner_mode = GET_MODE_INNER (mode);
>   if (elt == CONST0_RTX (inner_mode))
>     return CONST0_RTX (mode);
>@@ -6284,6 +6294,12 @@ init_emit_once (void)
>   FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
>     const_tiny_rtx[3][(int) mode] = constm1_rtx;
> 
>+  /* For BImode, 1 and -1 are unsigned and signed interpretations
>+     of the same value.  */
>+  const_tiny_rtx[0][(int) BImode] = const0_rtx;
>+  const_tiny_rtx[1][(int) BImode] = const_true_rtx;
>+  const_tiny_rtx[3][(int) BImode] = const_true_rtx;
>+
>   for (mode = MIN_MODE_PARTIAL_INT;
>        mode <= MAX_MODE_PARTIAL_INT;
>        mode = (machine_mode)((int)(mode) + 1))
>@@ -6301,6 +6317,15 @@ init_emit_once (void)
>   const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
>     }
> 
>+  /* As for BImode, "all 1" and "all -1" are unsigned and signed
>+     interpretations of the same value.  */
>+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
>+    {
>+      const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
>+      const_tiny_rtx[3][(int) mode] = gen_const_vector (mode, 3);
>+      const_tiny_rtx[1][(int) mode] = const_tiny_rtx[3][(int) mode];
>+    }
>+
>   FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
>     {
>       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
>@@ -6402,10 +6427,6 @@ init_emit_once (void)
>     if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
>       const_tiny_rtx[0][i] = const0_rtx;
> 
>-  const_tiny_rtx[0][(int) BImode] = const0_rtx;
>-  if (STORE_FLAG_VALUE == 1)
>-    const_tiny_rtx[1][(int) BImode] = const1_rtx;
>-
>   FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_POINTER_BOUNDS)
>     {
>       scalar_mode smode = smode_iter.require ();
>Index: gcc/expr.c
>===================================================================
>--- gcc/expr.c	2017-10-25 16:50:31.827332904 +0100
>+++ gcc/expr.c	2017-10-25 16:50:35.627184698 +0100
>@@ -10053,12 +10053,7 @@ expand_expr_real_1 (tree exp, rtx target
>     case VECTOR_CST:
>       {
> 	tree tmp = NULL_TREE;
>-	if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FRACT
>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UFRACT
>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_ACCUM
>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UACCUM)
>+	if (VECTOR_MODE_P (mode))
> 	  return const_vector_from_tree (exp);
> 	scalar_int_mode int_mode;
> 	if (is_int_mode (mode, &int_mode))
>Index: gcc/tree-vect-generic.c
>===================================================================
>--- gcc/tree-vect-generic.c	2017-10-25 16:50:25.047596556 +0100
>+++ gcc/tree-vect-generic.c	2017-10-25 16:50:35.629184620 +0100
>@@ -980,12 +980,7 @@ expand_vector_operation (gimple_stmt_ite
>/* If the compute mode is not a vector mode (hence we are not
>decomposing
>  a BLKmode vector to smaller, hardware-supported vectors), we may want
>      to expand the operations in parallel.  */
>-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
>+  if (!VECTOR_MODE_P (compute_mode))
>     switch (code)
>       {
>       case PLUS_EXPR:
>@@ -1174,6 +1169,8 @@ type_for_widest_vector_mode (tree type,
>     mode = MIN_MODE_VECTOR_ACCUM;
>   else if (SCALAR_UACCUM_MODE_P (inner_mode))
>     mode = MIN_MODE_VECTOR_UACCUM;
>+  else if (inner_mode == BImode)
>+    mode = MIN_MODE_VECTOR_BOOL;
>   else
>     mode = MIN_MODE_VECTOR_INT;
> 
>@@ -1531,12 +1528,7 @@ expand_vector_scalar_condition (gimple_s
>/* If the compute mode is not a vector mode (hence we are not
>decomposing
>  a BLKmode vector to smaller, hardware-supported vectors), we may want
>      to expand the operations in parallel.  */
>-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
>+  if (!VECTOR_MODE_P (compute_mode))
>     new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
> 				      COND_EXPR);
>   else
>Index: gcc/c-family/c-common.c
>===================================================================
>--- gcc/c-family/c-common.c	2017-10-25 16:50:24.861603766 +0100
>+++ gcc/c-family/c-common.c	2017-10-25 16:50:35.625184776 +0100
>@@ -2281,6 +2281,14 @@ c_common_type_for_mode (machine_mode mod
>       if (inner_type != NULL_TREE)
> 	return build_complex_type (inner_type);
>     }
>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>+    {
>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>(mode),
>+						    GET_MODE_NUNITS (mode));
>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>+      return build_vector_type_for_mode (bool_type, mode);
>+    }
>   else if (VECTOR_MODE_P (mode)
> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>     {
>Index: gcc/fortran/trans-types.c
>===================================================================
>--- gcc/fortran/trans-types.c	2017-10-25 16:50:24.869603456 +0100
>+++ gcc/fortran/trans-types.c	2017-10-25 16:50:35.627184698 +0100
>@@ -3159,6 +3159,14 @@ gfc_type_for_mode (machine_mode mode, in
>tree type = gfc_type_for_size (GET_MODE_PRECISION (int_mode),
>unsignedp);
>return type != NULL_TREE && mode == TYPE_MODE (type) ? type :
>NULL_TREE;
>     }
>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>+    {
>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>(mode),
>+						    GET_MODE_NUNITS (mode));
>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>+      return build_vector_type_for_mode (bool_type, mode);
>+    }
>   else if (VECTOR_MODE_P (mode)
> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>     {
>Index: gcc/go/go-lang.c
>===================================================================
>--- gcc/go/go-lang.c	2017-10-25 16:50:24.870603417 +0100
>+++ gcc/go/go-lang.c	2017-10-25 16:50:35.627184698 +0100
>@@ -372,9 +372,17 @@ go_langhook_type_for_mode (machine_mode
>      make sense for the middle-end to ask the frontend for a type
>      which the frontend does not support.  However, at least for now
>      it is required.  See PR 46805.  */
>-  if (VECTOR_MODE_P (mode)
>+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>       && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>     {
>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>(mode),
>+						    GET_MODE_NUNITS (mode));
>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>+      return build_vector_type_for_mode (bool_type, mode);
>+    }
>+  else if (VECTOR_MODE_P (mode)
>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>+    {
>       tree inner;
> 
>  inner = go_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
>Index: gcc/lto/lto-lang.c
>===================================================================
>--- gcc/lto/lto-lang.c	2017-10-25 16:50:24.871603378 +0100
>+++ gcc/lto/lto-lang.c	2017-10-25 16:50:35.628184659 +0100
>@@ -971,6 +971,14 @@ lto_type_for_mode (machine_mode mode, in
>       if (inner_type != NULL_TREE)
> 	return build_complex_type (inner_type);
>     }
>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>+    {
>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>(mode),
>+						    GET_MODE_NUNITS (mode));
>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>+      return build_vector_type_for_mode (bool_type, mode);
>+    }
>   else if (VECTOR_MODE_P (mode)
> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>     {
Richard Sandiford Oct. 25, 2017, 4:05 p.m. UTC | #2
Richard Biener <richard.guenther@gmail.com> writes:
> On October 25, 2017 5:54:02 PM GMT+02:00, Richard Sandiford
> <richard.sandiford@linaro.org> wrote:
>>This patch adds a new mode class to represent vectors of booleans.
>>GET_MODE_BITSIZE (m) / GET_MODE_NUNITS (m) determines the number
>>of bits that are used to represent each boolean; this can be 1
>>for a fully-packed representation or greater than 1 for an unpacked
>>representation.  In the latter case, the value of bits other than
>>the lowest is not significant.
>>
>>These are used by the SVE port to represent predicates.
>>
>>Tested on aarch64-linux-gnu, x86_64-linux-gnu and
>>powerpc64le-linux-gnu,
>>on top of the poly_int series.  OK to install?
>
> AVX uses integer modes for predicates. Can't you do the same thing, with
> variable size, of course?

Variable-sized integers would be really painful.  The main point of
the scalar_int_mode series was to take advantage of the fact that
integers are always fixed size, to avoid poly_int speading even further.

I don't think there's any benefit to modelling them as integers for SVE.
We never want to refer to them as integers, but we often want to refer
to them as vectors.  And treating them as vectors fits with the
tree representation.

> AVX has moves between predicate registers and GPRs.

SVE doesn't have/need this.  The GPRs have 64 bits and the maximum
predicate size is 256 bits, so the two aren't necessarily compatible.

I guess you're worried that target-independent code will suddenly
need to cope with two different representations of the same thing.
But besides this patch, it all gets hidden behind the existing
get_mask_mode hook.

Thanks,
Richard

>
> Richard. 
>
>
>>Richard
>>
>>
>>2017-10-25  Richard Sandiford  <richard.sandiford@linaro.org>
>>	    Alan Hayward  <alan.hayward@arm.com>
>>	    David Sherwood  <david.sherwood@arm.com>
>>
>>gcc/
>>	* mode-classes.def (MODE_VECTOR_BOOL): New mode class.
>>	* machmode.h (INTEGRAL_MODE_P, VECTOR_MODE_P): Return true
>>	for MODE_VECTOR_BOOL.
>>	* machmode.def (VECTOR_BOOL_MODE): Document.
>>	* genmodes.c (VECTOR_BOOL_MODE): New macro.
>>	(make_vector_bool_mode): New function.
>>	(complete_mode, emit_mode_wider, emit_mode_adjustments): Handle
>>	MODE_VECTOR_BOOL.
>>	* lto-streamer-in.c (lto_input_mode_table): Likewise.
>>	* stor-layout.c (int_mode_for_mode): Likewise.
>>	* tree.c (build_vector_type_for_mode): Likewise.
>>	* varasm.c (output_constant_pool_2): Likewise.
>>	* emit-rtl.c (gen_const_vec_duplicate): Likewise,
>>	(init_emit_once): Make sure that CONST1_RTX (BImode) and
>>	CONSTM1_RTX (BImode) are the same thing.  Initialize const_tiny_rtx
>>	for MODE_VECTOR_BOOL.
>>	* expr.c (expand_expr_real_1): Use VECTOR_MODE_P instead of a list
>>	of mode class checks.
>>	* tree-vect-generic.c (expand_vector_operation): Use VECTOR_MODE_P
>>	instead of a list of mode class checks.
>>	(expand_vector_scalar_condition): Likewise.
>>	(type_for_widest_vector_mode): Handle BImode as an inner mode.
>>
>>gcc/c-family/
>>	* c-common.c (c_common_type_for_mode): Handle MODE_VECTOR_BOOL.
>>
>>gcc/fortran/
>>	* trans-types.c (gfc_type_for_mode): Handle MODE_VECTOR_BOOL.
>>
>>gcc/go/
>>	* go-lang.c (go_langhook_type_for_mode): Handle MODE_VECTOR_BOOL.
>>
>>gcc/lto/
>>	* lto-lang.c (lto_type_for_mode): Handle MODE_VECTOR_BOOL.
>>
>>Index: gcc/mode-classes.def
>>===================================================================
>>--- gcc/mode-classes.def	2017-10-25 16:50:18.000869425 +0100
>>+++ gcc/mode-classes.def	2017-10-25 16:50:35.628184659 +0100
>>@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.
>> DEF_MODE_CLASS (MODE_DECIMAL_FLOAT),	/* decimal floating point */	   \
>>   DEF_MODE_CLASS (MODE_COMPLEX_INT), 	/* complex numbers */		   \
>>   DEF_MODE_CLASS (MODE_COMPLEX_FLOAT),					   \
>>+  DEF_MODE_CLASS (MODE_VECTOR_BOOL),	/* vectors of single bits */	   \
>>   DEF_MODE_CLASS (MODE_VECTOR_INT),	/* SIMD vectors */		   \
>>   DEF_MODE_CLASS (MODE_VECTOR_FRACT),	/* SIMD vectors */		   \
>>   DEF_MODE_CLASS (MODE_VECTOR_UFRACT),	/* SIMD vectors */		   \
>>Index: gcc/machmode.h
>>===================================================================
>>--- gcc/machmode.h	2017-10-25 16:50:31.832332710 +0100
>>+++ gcc/machmode.h	2017-10-25 16:50:35.628184659 +0100
>>@@ -108,6 +108,7 @@ #define INTEGRAL_MODE_P(MODE)			\
>>   (GET_MODE_CLASS (MODE) == MODE_INT		\
>>    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
>>    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
>>+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
>> 
>> /* Nonzero if MODE is a floating-point mode.  */
>>@@ -123,8 +124,9 @@ #define COMPLEX_MODE_P(MODE)			\
>>    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
>> 
>> /* Nonzero if MODE is a vector mode.  */
>>-#define VECTOR_MODE_P(MODE)			\
>>-  (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT	\
>>+#define VECTOR_MODE_P(MODE)				\
>>+  (GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL		\
>>+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT		\
>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT	\
>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT	\
>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT	\
>>Index: gcc/machmode.def
>>===================================================================
>>--- gcc/machmode.def	2017-10-25 16:50:18.000869425 +0100
>>+++ gcc/machmode.def	2017-10-25 16:50:35.628184659 +0100
>>@@ -142,6 +142,12 @@ along with GCC; see the file COPYING3.
>> 	than two bytes (if CLASS is FLOAT).  CLASS must be INT or
>> 	FLOAT.  The names follow the same rule as VECTOR_MODE uses.
>> 
>>+     VECTOR_BOOL_MODE (COUNT, BYTESIZE)
>>+	Create a vector of booleans with COUNT elements and BYTESIZE bytes.
>>+	Each boolean occupies (COUNT * BITS_PER_UNIT) / BYTESIZE bits,
>>+	with the element at index 0 occupying the lsb of the first byte
>>+	in memory.  Only the lowest bit of each element is significant.
>>+
>>      COMPLEX_MODES (CLASS);
>>         For all modes presently declared in class CLASS, construct
>> 	corresponding complex modes.  Modes smaller than one byte
>>Index: gcc/genmodes.c
>>===================================================================
>>--- gcc/genmodes.c	2017-10-25 16:50:31.828332866 +0100
>>+++ gcc/genmodes.c	2017-10-25 16:50:35.627184698 +0100
>>@@ -375,6 +375,10 @@ complete_mode (struct mode_data *m)
>>       m->bytesize = 2 * m->component->bytesize;
>>       break;
>> 
>>+    case MODE_VECTOR_BOOL:
>>+      validate_mode (m, UNSET, SET, SET, SET, UNSET);
>>+      break;
>>+
>>     case MODE_VECTOR_INT:
>>     case MODE_VECTOR_FLOAT:
>>     case MODE_VECTOR_FRACT:
>>@@ -526,6 +530,36 @@ make_vector_modes (enum mode_class cl, u
>>     }
>> }
>> 
>>+/* Create a vector of booleans with COUNT elements and BYTESIZE bytes
>>+   in total.  */
>>+#define VECTOR_BOOL_MODE(COUNT, BYTESIZE) \
>>+  make_vector_bool_mode (COUNT, BYTESIZE, __FILE__, __LINE__)
>>+static void ATTRIBUTE_UNUSED
>>+make_vector_bool_mode (unsigned int count, unsigned int bytesize,
>>+		       const char *file, unsigned int line)
>>+{
>>+  struct mode_data *m = find_mode ("BI");
>>+  if (!m)
>>+    {
>>+      error ("%s:%d: no mode \"BI\"", file, line);
>>+      return;
>>+    }
>>+
>>+  char buf[8];
>>+  if ((size_t) snprintf (buf, sizeof buf, "V%uBI", count) >= sizeof
>>buf)
>>+    {
>>+      error ("%s:%d: number of vector elements is too high",
>>+	     file, line);
>>+      return;
>>+    }
>>+
>>+  struct mode_data *v = new_mode (MODE_VECTOR_BOOL,
>>+				  xstrdup (buf), file, line);
>>+  v->component = m;
>>+  v->ncomponents = count;
>>+  v->bytesize = bytesize;
>>+}
>>+
>> /* Input.  */
>> 
>> #define _SPECIAL_MODE(C, N) \
>>@@ -1438,7 +1472,8 @@ emit_mode_wider (void)
>> 
>> 	  /* For vectors we want twice the number of components,
>> 	     with the same element type.  */
>>-	  if (m->cl == MODE_VECTOR_INT
>>+	  if (m->cl == MODE_VECTOR_BOOL
>>+	      || m->cl == MODE_VECTOR_INT
>> 	      || m->cl == MODE_VECTOR_FLOAT
>> 	      || m->cl == MODE_VECTOR_FRACT
>> 	      || m->cl == MODE_VECTOR_UFRACT
>>@@ -1657,6 +1692,7 @@ emit_mode_adjustments (void)
>>       printf ("\n  /* %s:%d */\n", a->file, a->line);
>>       switch (a->mode->cl)
>> 	{
>>+	case MODE_VECTOR_BOOL:
>> 	case MODE_VECTOR_INT:
>> 	case MODE_VECTOR_FLOAT:
>> 	case MODE_VECTOR_FRACT:
>>@@ -1688,6 +1724,10 @@ emit_mode_adjustments (void)
>> 		      m->name);
>> 	      break;
>> 
>>+	    case MODE_VECTOR_BOOL:
>>+	      /* Changes to BImode should not affect vector booleans.  */
>>+	      break;
>>+
>> 	    case MODE_VECTOR_INT:
>> 	    case MODE_VECTOR_FLOAT:
>> 	    case MODE_VECTOR_FRACT:
>>@@ -1728,6 +1768,10 @@ emit_mode_adjustments (void)
>> 	      printf ("  mode_base_align[E_%smode] = s;\n", m->name);
>> 	      break;
>> 
>>+	    case MODE_VECTOR_BOOL:
>>+	      /* Changes to BImode should not affect vector booleans.  */
>>+	      break;
>>+
>> 	    case MODE_VECTOR_INT:
>> 	    case MODE_VECTOR_FLOAT:
>> 	    case MODE_VECTOR_FRACT:
>>Index: gcc/lto-streamer-in.c
>>===================================================================
>>--- gcc/lto-streamer-in.c	2017-10-25 16:50:31.832332710 +0100
>>+++ gcc/lto-streamer-in.c	2017-10-25 16:50:35.628184659 +0100
>>@@ -1662,6 +1662,7 @@ lto_input_mode_table (struct lto_file_de
>> 	{
>> 	  switch (mclass)
>> 	    {
>>+	    case MODE_VECTOR_BOOL:
>> 	    case MODE_VECTOR_INT:
>> 	    case MODE_VECTOR_FLOAT:
>> 	    case MODE_VECTOR_FRACT:
>>Index: gcc/stor-layout.c
>>===================================================================
>>--- gcc/stor-layout.c	2017-10-25 16:50:24.925601288 +0100
>>+++ gcc/stor-layout.c	2017-10-25 16:50:35.629184620 +0100
>>@@ -378,12 +378,13 @@ int_mode_for_mode (machine_mode mode)
>>     case MODE_COMPLEX_FLOAT:
>>     case MODE_FLOAT:
>>     case MODE_DECIMAL_FLOAT:
>>-    case MODE_VECTOR_INT:
>>-    case MODE_VECTOR_FLOAT:
>>     case MODE_FRACT:
>>     case MODE_ACCUM:
>>     case MODE_UFRACT:
>>     case MODE_UACCUM:
>>+    case MODE_VECTOR_BOOL:
>>+    case MODE_VECTOR_INT:
>>+    case MODE_VECTOR_FLOAT:
>>     case MODE_VECTOR_FRACT:
>>     case MODE_VECTOR_ACCUM:
>>     case MODE_VECTOR_UFRACT:
>>Index: gcc/tree.c
>>===================================================================
>>--- gcc/tree.c	2017-10-25 16:50:31.843332282 +0100
>>+++ gcc/tree.c	2017-10-25 16:50:35.630184581 +0100
>>@@ -10561,6 +10561,7 @@ build_vector_type_for_mode (tree innerty
>> 
>>   switch (GET_MODE_CLASS (mode))
>>     {
>>+    case MODE_VECTOR_BOOL:
>>     case MODE_VECTOR_INT:
>>     case MODE_VECTOR_FLOAT:
>>     case MODE_VECTOR_FRACT:
>>Index: gcc/varasm.c
>>===================================================================
>>--- gcc/varasm.c	2017-10-25 16:50:24.928601171 +0100
>>+++ gcc/varasm.c	2017-10-25 16:50:35.631184542 +0100
>>@@ -3926,6 +3926,32 @@ output_constant_pool_2 (fixed_size_mode
>>       assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
>>       break;
>> 
>>+    case MODE_VECTOR_BOOL:
>>+      {
>>+	gcc_assert (GET_CODE (x) == CONST_VECTOR);
>>+
>>+	/* Pick the smallest integer mode that contains at least one
>>+	   whole element.  Often this is byte_mode and contains more
>>+	   than one element.  */
>>+	unsigned int nelts = CONST_VECTOR_NUNITS (x);
>>+	unsigned int elt_bits = GET_MODE_BITSIZE (mode) / nelts;
>>+	unsigned int int_bits = MAX (elt_bits, BITS_PER_UNIT);
>>+	scalar_int_mode int_mode = int_mode_for_size (int_bits, 0).require
>>();
>>+
>>+	/* Build the constant up one integer at a time.  */
>>+	unsigned int elts_per_int = int_bits / elt_bits;
>>+	for (unsigned int i = 0; i < nelts; i += elts_per_int)
>>+	  {
>>+	    unsigned HOST_WIDE_INT value = 0;
>>+	    unsigned int limit = MIN (nelts - i, elts_per_int);
>>+	    for (unsigned int j = 0; j < limit; ++j)
>>+	      if (INTVAL (CONST_VECTOR_ELT (x, i + j)) != 0)
>>+		value |= 1 << (j * elt_bits);
>>+	    output_constant_pool_2 (int_mode, gen_int_mode (value, int_mode),
>>+				    i != 0 ? MIN (align, int_bits) : align);
>>+	  }
>>+	break;
>>+      }
>>     case MODE_VECTOR_FLOAT:
>>     case MODE_VECTOR_INT:
>>     case MODE_VECTOR_FRACT:
>>Index: gcc/emit-rtl.c
>>===================================================================
>>--- gcc/emit-rtl.c	2017-10-25 16:50:31.826332943 +0100
>>+++ gcc/emit-rtl.c	2017-10-25 16:50:35.625184776 +0100
>>@@ -5960,6 +5960,16 @@ gen_const_vec_duplicate_1 (machine_mode
>> rtx
>> gen_const_vec_duplicate (machine_mode mode, rtx elt)
>> {
>>+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
>>+    {
>>+      if (elt == const1_rtx || elt == constm1_rtx)
>>+	return CONST1_RTX (mode);
>>+      else if (elt == const0_rtx)
>>+	return CONST0_RTX (mode);
>>+      else
>>+	gcc_unreachable ();
>>+    }
>>+
>>   scalar_mode inner_mode = GET_MODE_INNER (mode);
>>   if (elt == CONST0_RTX (inner_mode))
>>     return CONST0_RTX (mode);
>>@@ -6284,6 +6294,12 @@ init_emit_once (void)
>>   FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
>>     const_tiny_rtx[3][(int) mode] = constm1_rtx;
>> 
>>+  /* For BImode, 1 and -1 are unsigned and signed interpretations
>>+     of the same value.  */
>>+  const_tiny_rtx[0][(int) BImode] = const0_rtx;
>>+  const_tiny_rtx[1][(int) BImode] = const_true_rtx;
>>+  const_tiny_rtx[3][(int) BImode] = const_true_rtx;
>>+
>>   for (mode = MIN_MODE_PARTIAL_INT;
>>        mode <= MAX_MODE_PARTIAL_INT;
>>        mode = (machine_mode)((int)(mode) + 1))
>>@@ -6301,6 +6317,15 @@ init_emit_once (void)
>>   const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
>>     }
>> 
>>+  /* As for BImode, "all 1" and "all -1" are unsigned and signed
>>+     interpretations of the same value.  */
>>+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
>>+    {
>>+      const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
>>+      const_tiny_rtx[3][(int) mode] = gen_const_vector (mode, 3);
>>+      const_tiny_rtx[1][(int) mode] = const_tiny_rtx[3][(int) mode];
>>+    }
>>+
>>   FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
>>     {
>>       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
>>@@ -6402,10 +6427,6 @@ init_emit_once (void)
>>     if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
>>       const_tiny_rtx[0][i] = const0_rtx;
>> 
>>-  const_tiny_rtx[0][(int) BImode] = const0_rtx;
>>-  if (STORE_FLAG_VALUE == 1)
>>-    const_tiny_rtx[1][(int) BImode] = const1_rtx;
>>-
>>   FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_POINTER_BOUNDS)
>>     {
>>       scalar_mode smode = smode_iter.require ();
>>Index: gcc/expr.c
>>===================================================================
>>--- gcc/expr.c	2017-10-25 16:50:31.827332904 +0100
>>+++ gcc/expr.c	2017-10-25 16:50:35.627184698 +0100
>>@@ -10053,12 +10053,7 @@ expand_expr_real_1 (tree exp, rtx target
>>     case VECTOR_CST:
>>       {
>> 	tree tmp = NULL_TREE;
>>-	if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FRACT
>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UFRACT
>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_ACCUM
>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UACCUM)
>>+	if (VECTOR_MODE_P (mode))
>> 	  return const_vector_from_tree (exp);
>> 	scalar_int_mode int_mode;
>> 	if (is_int_mode (mode, &int_mode))
>>Index: gcc/tree-vect-generic.c
>>===================================================================
>>--- gcc/tree-vect-generic.c	2017-10-25 16:50:25.047596556 +0100
>>+++ gcc/tree-vect-generic.c	2017-10-25 16:50:35.629184620 +0100
>>@@ -980,12 +980,7 @@ expand_vector_operation (gimple_stmt_ite
>>/* If the compute mode is not a vector mode (hence we are not
>>decomposing
>>  a BLKmode vector to smaller, hardware-supported vectors), we may want
>>      to expand the operations in parallel.  */
>>-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
>>+  if (!VECTOR_MODE_P (compute_mode))
>>     switch (code)
>>       {
>>       case PLUS_EXPR:
>>@@ -1174,6 +1169,8 @@ type_for_widest_vector_mode (tree type,
>>     mode = MIN_MODE_VECTOR_ACCUM;
>>   else if (SCALAR_UACCUM_MODE_P (inner_mode))
>>     mode = MIN_MODE_VECTOR_UACCUM;
>>+  else if (inner_mode == BImode)
>>+    mode = MIN_MODE_VECTOR_BOOL;
>>   else
>>     mode = MIN_MODE_VECTOR_INT;
>> 
>>@@ -1531,12 +1528,7 @@ expand_vector_scalar_condition (gimple_s
>>/* If the compute mode is not a vector mode (hence we are not
>>decomposing
>>  a BLKmode vector to smaller, hardware-supported vectors), we may want
>>      to expand the operations in parallel.  */
>>-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
>>+  if (!VECTOR_MODE_P (compute_mode))
>>     new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
>> 				      COND_EXPR);
>>   else
>>Index: gcc/c-family/c-common.c
>>===================================================================
>>--- gcc/c-family/c-common.c	2017-10-25 16:50:24.861603766 +0100
>>+++ gcc/c-family/c-common.c	2017-10-25 16:50:35.625184776 +0100
>>@@ -2281,6 +2281,14 @@ c_common_type_for_mode (machine_mode mod
>>       if (inner_type != NULL_TREE)
>> 	return build_complex_type (inner_type);
>>     }
>>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>+    {
>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>(mode),
>>+						    GET_MODE_NUNITS (mode));
>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>+      return build_vector_type_for_mode (bool_type, mode);
>>+    }
>>   else if (VECTOR_MODE_P (mode)
>> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>     {
>>Index: gcc/fortran/trans-types.c
>>===================================================================
>>--- gcc/fortran/trans-types.c	2017-10-25 16:50:24.869603456 +0100
>>+++ gcc/fortran/trans-types.c	2017-10-25 16:50:35.627184698 +0100
>>@@ -3159,6 +3159,14 @@ gfc_type_for_mode (machine_mode mode, in
>>tree type = gfc_type_for_size (GET_MODE_PRECISION (int_mode),
>>unsignedp);
>>return type != NULL_TREE && mode == TYPE_MODE (type) ? type :
>>NULL_TREE;
>>     }
>>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>+    {
>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>(mode),
>>+						    GET_MODE_NUNITS (mode));
>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>+      return build_vector_type_for_mode (bool_type, mode);
>>+    }
>>   else if (VECTOR_MODE_P (mode)
>> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>     {
>>Index: gcc/go/go-lang.c
>>===================================================================
>>--- gcc/go/go-lang.c	2017-10-25 16:50:24.870603417 +0100
>>+++ gcc/go/go-lang.c	2017-10-25 16:50:35.627184698 +0100
>>@@ -372,9 +372,17 @@ go_langhook_type_for_mode (machine_mode
>>      make sense for the middle-end to ask the frontend for a type
>>      which the frontend does not support.  However, at least for now
>>      it is required.  See PR 46805.  */
>>-  if (VECTOR_MODE_P (mode)
>>+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>       && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>     {
>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>(mode),
>>+						    GET_MODE_NUNITS (mode));
>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>+      return build_vector_type_for_mode (bool_type, mode);
>>+    }
>>+  else if (VECTOR_MODE_P (mode)
>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>+    {
>>       tree inner;
>> 
>>  inner = go_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
>>Index: gcc/lto/lto-lang.c
>>===================================================================
>>--- gcc/lto/lto-lang.c	2017-10-25 16:50:24.871603378 +0100
>>+++ gcc/lto/lto-lang.c	2017-10-25 16:50:35.628184659 +0100
>>@@ -971,6 +971,14 @@ lto_type_for_mode (machine_mode mode, in
>>       if (inner_type != NULL_TREE)
>> 	return build_complex_type (inner_type);
>>     }
>>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>+    {
>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>(mode),
>>+						    GET_MODE_NUNITS (mode));
>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>+      return build_vector_type_for_mode (bool_type, mode);
>>+    }
>>   else if (VECTOR_MODE_P (mode)
>> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>     {
Richard Biener Oct. 25, 2017, 4:35 p.m. UTC | #3
On October 25, 2017 6:05:48 PM GMT+02:00, Richard Sandiford <richard.sandiford@linaro.org> wrote:
>Richard Biener <richard.guenther@gmail.com> writes:
>> On October 25, 2017 5:54:02 PM GMT+02:00, Richard Sandiford
>> <richard.sandiford@linaro.org> wrote:
>>>This patch adds a new mode class to represent vectors of booleans.
>>>GET_MODE_BITSIZE (m) / GET_MODE_NUNITS (m) determines the number
>>>of bits that are used to represent each boolean; this can be 1
>>>for a fully-packed representation or greater than 1 for an unpacked
>>>representation.  In the latter case, the value of bits other than
>>>the lowest is not significant.
>>>
>>>These are used by the SVE port to represent predicates.
>>>
>>>Tested on aarch64-linux-gnu, x86_64-linux-gnu and
>>>powerpc64le-linux-gnu,
>>>on top of the poly_int series.  OK to install?
>>
>> AVX uses integer modes for predicates. Can't you do the same thing,
>with
>> variable size, of course?
>
>Variable-sized integers would be really painful.  The main point of
>the scalar_int_mode series was to take advantage of the fact that
>integers are always fixed size, to avoid poly_int speading even
>further.
>
>I don't think there's any benefit to modelling them as integers for
>SVE.
>We never want to refer to them as integers, but we often want to refer
>to them as vectors.  And treating them as vectors fits with the
>tree representation.
>
>> AVX has moves between predicate registers and GPRs.
>
>SVE doesn't have/need this.  The GPRs have 64 bits and the maximum
>predicate size is 256 bits, so the two aren't necessarily compatible.
>
>I guess you're worried that target-independent code will suddenly
>need to cope with two different representations of the same thing.
>But besides this patch, it all gets hidden behind the existing
>get_mask_mode hook.

OK, fine. I was exactly wondering that. The AVX handling required changes all over the place... 

Richard. 

>Thanks,
>Richard
>
>>
>> Richard. 
>>
>>
>>>Richard
>>>
>>>
>>>2017-10-25  Richard Sandiford  <richard.sandiford@linaro.org>
>>>	    Alan Hayward  <alan.hayward@arm.com>
>>>	    David Sherwood  <david.sherwood@arm.com>
>>>
>>>gcc/
>>>	* mode-classes.def (MODE_VECTOR_BOOL): New mode class.
>>>	* machmode.h (INTEGRAL_MODE_P, VECTOR_MODE_P): Return true
>>>	for MODE_VECTOR_BOOL.
>>>	* machmode.def (VECTOR_BOOL_MODE): Document.
>>>	* genmodes.c (VECTOR_BOOL_MODE): New macro.
>>>	(make_vector_bool_mode): New function.
>>>	(complete_mode, emit_mode_wider, emit_mode_adjustments): Handle
>>>	MODE_VECTOR_BOOL.
>>>	* lto-streamer-in.c (lto_input_mode_table): Likewise.
>>>	* stor-layout.c (int_mode_for_mode): Likewise.
>>>	* tree.c (build_vector_type_for_mode): Likewise.
>>>	* varasm.c (output_constant_pool_2): Likewise.
>>>	* emit-rtl.c (gen_const_vec_duplicate): Likewise,
>>>	(init_emit_once): Make sure that CONST1_RTX (BImode) and
>>>	CONSTM1_RTX (BImode) are the same thing.  Initialize const_tiny_rtx
>>>	for MODE_VECTOR_BOOL.
>>>	* expr.c (expand_expr_real_1): Use VECTOR_MODE_P instead of a list
>>>	of mode class checks.
>>>	* tree-vect-generic.c (expand_vector_operation): Use VECTOR_MODE_P
>>>	instead of a list of mode class checks.
>>>	(expand_vector_scalar_condition): Likewise.
>>>	(type_for_widest_vector_mode): Handle BImode as an inner mode.
>>>
>>>gcc/c-family/
>>>	* c-common.c (c_common_type_for_mode): Handle MODE_VECTOR_BOOL.
>>>
>>>gcc/fortran/
>>>	* trans-types.c (gfc_type_for_mode): Handle MODE_VECTOR_BOOL.
>>>
>>>gcc/go/
>>>	* go-lang.c (go_langhook_type_for_mode): Handle MODE_VECTOR_BOOL.
>>>
>>>gcc/lto/
>>>	* lto-lang.c (lto_type_for_mode): Handle MODE_VECTOR_BOOL.
>>>
>>>Index: gcc/mode-classes.def
>>>===================================================================
>>>--- gcc/mode-classes.def	2017-10-25 16:50:18.000869425 +0100
>>>+++ gcc/mode-classes.def	2017-10-25 16:50:35.628184659 +0100
>>>@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.
>>> DEF_MODE_CLASS (MODE_DECIMAL_FLOAT),	/* decimal floating point */	  
>\
>>>   DEF_MODE_CLASS (MODE_COMPLEX_INT), 	/* complex numbers */		   \
>>>   DEF_MODE_CLASS (MODE_COMPLEX_FLOAT),					   \
>>>+  DEF_MODE_CLASS (MODE_VECTOR_BOOL),	/* vectors of single bits */	  
>\
>>>   DEF_MODE_CLASS (MODE_VECTOR_INT),	/* SIMD vectors */		   \
>>>   DEF_MODE_CLASS (MODE_VECTOR_FRACT),	/* SIMD vectors */		   \
>>>   DEF_MODE_CLASS (MODE_VECTOR_UFRACT),	/* SIMD vectors */		   \
>>>Index: gcc/machmode.h
>>>===================================================================
>>>--- gcc/machmode.h	2017-10-25 16:50:31.832332710 +0100
>>>+++ gcc/machmode.h	2017-10-25 16:50:35.628184659 +0100
>>>@@ -108,6 +108,7 @@ #define INTEGRAL_MODE_P(MODE)			\
>>>   (GET_MODE_CLASS (MODE) == MODE_INT		\
>>>    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
>>>    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
>>>+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
>>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
>>> 
>>> /* Nonzero if MODE is a floating-point mode.  */
>>>@@ -123,8 +124,9 @@ #define COMPLEX_MODE_P(MODE)			\
>>>    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
>>> 
>>> /* Nonzero if MODE is a vector mode.  */
>>>-#define VECTOR_MODE_P(MODE)			\
>>>-  (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT	\
>>>+#define VECTOR_MODE_P(MODE)				\
>>>+  (GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL		\
>>>+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT		\
>>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT	\
>>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT	\
>>>    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT	\
>>>Index: gcc/machmode.def
>>>===================================================================
>>>--- gcc/machmode.def	2017-10-25 16:50:18.000869425 +0100
>>>+++ gcc/machmode.def	2017-10-25 16:50:35.628184659 +0100
>>>@@ -142,6 +142,12 @@ along with GCC; see the file COPYING3.
>>> 	than two bytes (if CLASS is FLOAT).  CLASS must be INT or
>>> 	FLOAT.  The names follow the same rule as VECTOR_MODE uses.
>>> 
>>>+     VECTOR_BOOL_MODE (COUNT, BYTESIZE)
>>>+	Create a vector of booleans with COUNT elements and BYTESIZE bytes.
>>>+	Each boolean occupies (COUNT * BITS_PER_UNIT) / BYTESIZE bits,
>>>+	with the element at index 0 occupying the lsb of the first byte
>>>+	in memory.  Only the lowest bit of each element is significant.
>>>+
>>>      COMPLEX_MODES (CLASS);
>>>         For all modes presently declared in class CLASS, construct
>>> 	corresponding complex modes.  Modes smaller than one byte
>>>Index: gcc/genmodes.c
>>>===================================================================
>>>--- gcc/genmodes.c	2017-10-25 16:50:31.828332866 +0100
>>>+++ gcc/genmodes.c	2017-10-25 16:50:35.627184698 +0100
>>>@@ -375,6 +375,10 @@ complete_mode (struct mode_data *m)
>>>       m->bytesize = 2 * m->component->bytesize;
>>>       break;
>>> 
>>>+    case MODE_VECTOR_BOOL:
>>>+      validate_mode (m, UNSET, SET, SET, SET, UNSET);
>>>+      break;
>>>+
>>>     case MODE_VECTOR_INT:
>>>     case MODE_VECTOR_FLOAT:
>>>     case MODE_VECTOR_FRACT:
>>>@@ -526,6 +530,36 @@ make_vector_modes (enum mode_class cl, u
>>>     }
>>> }
>>> 
>>>+/* Create a vector of booleans with COUNT elements and BYTESIZE
>bytes
>>>+   in total.  */
>>>+#define VECTOR_BOOL_MODE(COUNT, BYTESIZE) \
>>>+  make_vector_bool_mode (COUNT, BYTESIZE, __FILE__, __LINE__)
>>>+static void ATTRIBUTE_UNUSED
>>>+make_vector_bool_mode (unsigned int count, unsigned int bytesize,
>>>+		       const char *file, unsigned int line)
>>>+{
>>>+  struct mode_data *m = find_mode ("BI");
>>>+  if (!m)
>>>+    {
>>>+      error ("%s:%d: no mode \"BI\"", file, line);
>>>+      return;
>>>+    }
>>>+
>>>+  char buf[8];
>>>+  if ((size_t) snprintf (buf, sizeof buf, "V%uBI", count) >= sizeof
>>>buf)
>>>+    {
>>>+      error ("%s:%d: number of vector elements is too high",
>>>+	     file, line);
>>>+      return;
>>>+    }
>>>+
>>>+  struct mode_data *v = new_mode (MODE_VECTOR_BOOL,
>>>+				  xstrdup (buf), file, line);
>>>+  v->component = m;
>>>+  v->ncomponents = count;
>>>+  v->bytesize = bytesize;
>>>+}
>>>+
>>> /* Input.  */
>>> 
>>> #define _SPECIAL_MODE(C, N) \
>>>@@ -1438,7 +1472,8 @@ emit_mode_wider (void)
>>> 
>>> 	  /* For vectors we want twice the number of components,
>>> 	     with the same element type.  */
>>>-	  if (m->cl == MODE_VECTOR_INT
>>>+	  if (m->cl == MODE_VECTOR_BOOL
>>>+	      || m->cl == MODE_VECTOR_INT
>>> 	      || m->cl == MODE_VECTOR_FLOAT
>>> 	      || m->cl == MODE_VECTOR_FRACT
>>> 	      || m->cl == MODE_VECTOR_UFRACT
>>>@@ -1657,6 +1692,7 @@ emit_mode_adjustments (void)
>>>       printf ("\n  /* %s:%d */\n", a->file, a->line);
>>>       switch (a->mode->cl)
>>> 	{
>>>+	case MODE_VECTOR_BOOL:
>>> 	case MODE_VECTOR_INT:
>>> 	case MODE_VECTOR_FLOAT:
>>> 	case MODE_VECTOR_FRACT:
>>>@@ -1688,6 +1724,10 @@ emit_mode_adjustments (void)
>>> 		      m->name);
>>> 	      break;
>>> 
>>>+	    case MODE_VECTOR_BOOL:
>>>+	      /* Changes to BImode should not affect vector booleans.  */
>>>+	      break;
>>>+
>>> 	    case MODE_VECTOR_INT:
>>> 	    case MODE_VECTOR_FLOAT:
>>> 	    case MODE_VECTOR_FRACT:
>>>@@ -1728,6 +1768,10 @@ emit_mode_adjustments (void)
>>> 	      printf ("  mode_base_align[E_%smode] = s;\n", m->name);
>>> 	      break;
>>> 
>>>+	    case MODE_VECTOR_BOOL:
>>>+	      /* Changes to BImode should not affect vector booleans.  */
>>>+	      break;
>>>+
>>> 	    case MODE_VECTOR_INT:
>>> 	    case MODE_VECTOR_FLOAT:
>>> 	    case MODE_VECTOR_FRACT:
>>>Index: gcc/lto-streamer-in.c
>>>===================================================================
>>>--- gcc/lto-streamer-in.c	2017-10-25 16:50:31.832332710 +0100
>>>+++ gcc/lto-streamer-in.c	2017-10-25 16:50:35.628184659 +0100
>>>@@ -1662,6 +1662,7 @@ lto_input_mode_table (struct lto_file_de
>>> 	{
>>> 	  switch (mclass)
>>> 	    {
>>>+	    case MODE_VECTOR_BOOL:
>>> 	    case MODE_VECTOR_INT:
>>> 	    case MODE_VECTOR_FLOAT:
>>> 	    case MODE_VECTOR_FRACT:
>>>Index: gcc/stor-layout.c
>>>===================================================================
>>>--- gcc/stor-layout.c	2017-10-25 16:50:24.925601288 +0100
>>>+++ gcc/stor-layout.c	2017-10-25 16:50:35.629184620 +0100
>>>@@ -378,12 +378,13 @@ int_mode_for_mode (machine_mode mode)
>>>     case MODE_COMPLEX_FLOAT:
>>>     case MODE_FLOAT:
>>>     case MODE_DECIMAL_FLOAT:
>>>-    case MODE_VECTOR_INT:
>>>-    case MODE_VECTOR_FLOAT:
>>>     case MODE_FRACT:
>>>     case MODE_ACCUM:
>>>     case MODE_UFRACT:
>>>     case MODE_UACCUM:
>>>+    case MODE_VECTOR_BOOL:
>>>+    case MODE_VECTOR_INT:
>>>+    case MODE_VECTOR_FLOAT:
>>>     case MODE_VECTOR_FRACT:
>>>     case MODE_VECTOR_ACCUM:
>>>     case MODE_VECTOR_UFRACT:
>>>Index: gcc/tree.c
>>>===================================================================
>>>--- gcc/tree.c	2017-10-25 16:50:31.843332282 +0100
>>>+++ gcc/tree.c	2017-10-25 16:50:35.630184581 +0100
>>>@@ -10561,6 +10561,7 @@ build_vector_type_for_mode (tree innerty
>>> 
>>>   switch (GET_MODE_CLASS (mode))
>>>     {
>>>+    case MODE_VECTOR_BOOL:
>>>     case MODE_VECTOR_INT:
>>>     case MODE_VECTOR_FLOAT:
>>>     case MODE_VECTOR_FRACT:
>>>Index: gcc/varasm.c
>>>===================================================================
>>>--- gcc/varasm.c	2017-10-25 16:50:24.928601171 +0100
>>>+++ gcc/varasm.c	2017-10-25 16:50:35.631184542 +0100
>>>@@ -3926,6 +3926,32 @@ output_constant_pool_2 (fixed_size_mode
>>>       assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
>>>       break;
>>> 
>>>+    case MODE_VECTOR_BOOL:
>>>+      {
>>>+	gcc_assert (GET_CODE (x) == CONST_VECTOR);
>>>+
>>>+	/* Pick the smallest integer mode that contains at least one
>>>+	   whole element.  Often this is byte_mode and contains more
>>>+	   than one element.  */
>>>+	unsigned int nelts = CONST_VECTOR_NUNITS (x);
>>>+	unsigned int elt_bits = GET_MODE_BITSIZE (mode) / nelts;
>>>+	unsigned int int_bits = MAX (elt_bits, BITS_PER_UNIT);
>>>+	scalar_int_mode int_mode = int_mode_for_size (int_bits, 0).require
>>>();
>>>+
>>>+	/* Build the constant up one integer at a time.  */
>>>+	unsigned int elts_per_int = int_bits / elt_bits;
>>>+	for (unsigned int i = 0; i < nelts; i += elts_per_int)
>>>+	  {
>>>+	    unsigned HOST_WIDE_INT value = 0;
>>>+	    unsigned int limit = MIN (nelts - i, elts_per_int);
>>>+	    for (unsigned int j = 0; j < limit; ++j)
>>>+	      if (INTVAL (CONST_VECTOR_ELT (x, i + j)) != 0)
>>>+		value |= 1 << (j * elt_bits);
>>>+	    output_constant_pool_2 (int_mode, gen_int_mode (value,
>int_mode),
>>>+				    i != 0 ? MIN (align, int_bits) : align);
>>>+	  }
>>>+	break;
>>>+      }
>>>     case MODE_VECTOR_FLOAT:
>>>     case MODE_VECTOR_INT:
>>>     case MODE_VECTOR_FRACT:
>>>Index: gcc/emit-rtl.c
>>>===================================================================
>>>--- gcc/emit-rtl.c	2017-10-25 16:50:31.826332943 +0100
>>>+++ gcc/emit-rtl.c	2017-10-25 16:50:35.625184776 +0100
>>>@@ -5960,6 +5960,16 @@ gen_const_vec_duplicate_1 (machine_mode
>>> rtx
>>> gen_const_vec_duplicate (machine_mode mode, rtx elt)
>>> {
>>>+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
>>>+    {
>>>+      if (elt == const1_rtx || elt == constm1_rtx)
>>>+	return CONST1_RTX (mode);
>>>+      else if (elt == const0_rtx)
>>>+	return CONST0_RTX (mode);
>>>+      else
>>>+	gcc_unreachable ();
>>>+    }
>>>+
>>>   scalar_mode inner_mode = GET_MODE_INNER (mode);
>>>   if (elt == CONST0_RTX (inner_mode))
>>>     return CONST0_RTX (mode);
>>>@@ -6284,6 +6294,12 @@ init_emit_once (void)
>>>   FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
>>>     const_tiny_rtx[3][(int) mode] = constm1_rtx;
>>> 
>>>+  /* For BImode, 1 and -1 are unsigned and signed interpretations
>>>+     of the same value.  */
>>>+  const_tiny_rtx[0][(int) BImode] = const0_rtx;
>>>+  const_tiny_rtx[1][(int) BImode] = const_true_rtx;
>>>+  const_tiny_rtx[3][(int) BImode] = const_true_rtx;
>>>+
>>>   for (mode = MIN_MODE_PARTIAL_INT;
>>>        mode <= MAX_MODE_PARTIAL_INT;
>>>        mode = (machine_mode)((int)(mode) + 1))
>>>@@ -6301,6 +6317,15 @@ init_emit_once (void)
>>>   const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner,
>inner);
>>>     }
>>> 
>>>+  /* As for BImode, "all 1" and "all -1" are unsigned and signed
>>>+     interpretations of the same value.  */
>>>+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
>>>+    {
>>>+      const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
>>>+      const_tiny_rtx[3][(int) mode] = gen_const_vector (mode, 3);
>>>+      const_tiny_rtx[1][(int) mode] = const_tiny_rtx[3][(int) mode];
>>>+    }
>>>+
>>>   FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
>>>     {
>>>       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
>>>@@ -6402,10 +6427,6 @@ init_emit_once (void)
>>>     if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
>>>       const_tiny_rtx[0][i] = const0_rtx;
>>> 
>>>-  const_tiny_rtx[0][(int) BImode] = const0_rtx;
>>>-  if (STORE_FLAG_VALUE == 1)
>>>-    const_tiny_rtx[1][(int) BImode] = const1_rtx;
>>>-
>>>   FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_POINTER_BOUNDS)
>>>     {
>>>       scalar_mode smode = smode_iter.require ();
>>>Index: gcc/expr.c
>>>===================================================================
>>>--- gcc/expr.c	2017-10-25 16:50:31.827332904 +0100
>>>+++ gcc/expr.c	2017-10-25 16:50:35.627184698 +0100
>>>@@ -10053,12 +10053,7 @@ expand_expr_real_1 (tree exp, rtx target
>>>     case VECTOR_CST:
>>>       {
>>> 	tree tmp = NULL_TREE;
>>>-	if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
>>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
>>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FRACT
>>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UFRACT
>>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_ACCUM
>>>-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UACCUM)
>>>+	if (VECTOR_MODE_P (mode))
>>> 	  return const_vector_from_tree (exp);
>>> 	scalar_int_mode int_mode;
>>> 	if (is_int_mode (mode, &int_mode))
>>>Index: gcc/tree-vect-generic.c
>>>===================================================================
>>>--- gcc/tree-vect-generic.c	2017-10-25 16:50:25.047596556 +0100
>>>+++ gcc/tree-vect-generic.c	2017-10-25 16:50:35.629184620 +0100
>>>@@ -980,12 +980,7 @@ expand_vector_operation (gimple_stmt_ite
>>>/* If the compute mode is not a vector mode (hence we are not
>>>decomposing
>>>  a BLKmode vector to smaller, hardware-supported vectors), we may
>want
>>>      to expand the operations in parallel.  */
>>>-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
>>>+  if (!VECTOR_MODE_P (compute_mode))
>>>     switch (code)
>>>       {
>>>       case PLUS_EXPR:
>>>@@ -1174,6 +1169,8 @@ type_for_widest_vector_mode (tree type,
>>>     mode = MIN_MODE_VECTOR_ACCUM;
>>>   else if (SCALAR_UACCUM_MODE_P (inner_mode))
>>>     mode = MIN_MODE_VECTOR_UACCUM;
>>>+  else if (inner_mode == BImode)
>>>+    mode = MIN_MODE_VECTOR_BOOL;
>>>   else
>>>     mode = MIN_MODE_VECTOR_INT;
>>> 
>>>@@ -1531,12 +1528,7 @@ expand_vector_scalar_condition (gimple_s
>>>/* If the compute mode is not a vector mode (hence we are not
>>>decomposing
>>>  a BLKmode vector to smaller, hardware-supported vectors), we may
>want
>>>      to expand the operations in parallel.  */
>>>-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
>>>-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
>>>+  if (!VECTOR_MODE_P (compute_mode))
>>>     new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2,
>rhs3,
>>> 				      COND_EXPR);
>>>   else
>>>Index: gcc/c-family/c-common.c
>>>===================================================================
>>>--- gcc/c-family/c-common.c	2017-10-25 16:50:24.861603766 +0100
>>>+++ gcc/c-family/c-common.c	2017-10-25 16:50:35.625184776 +0100
>>>@@ -2281,6 +2281,14 @@ c_common_type_for_mode (machine_mode mod
>>>       if (inner_type != NULL_TREE)
>>> 	return build_complex_type (inner_type);
>>>     }
>>>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>+    {
>>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>>(mode),
>>>+						    GET_MODE_NUNITS (mode));
>>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>>+      return build_vector_type_for_mode (bool_type, mode);
>>>+    }
>>>   else if (VECTOR_MODE_P (mode)
>>> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>     {
>>>Index: gcc/fortran/trans-types.c
>>>===================================================================
>>>--- gcc/fortran/trans-types.c	2017-10-25 16:50:24.869603456 +0100
>>>+++ gcc/fortran/trans-types.c	2017-10-25 16:50:35.627184698 +0100
>>>@@ -3159,6 +3159,14 @@ gfc_type_for_mode (machine_mode mode, in
>>>tree type = gfc_type_for_size (GET_MODE_PRECISION (int_mode),
>>>unsignedp);
>>>return type != NULL_TREE && mode == TYPE_MODE (type) ? type :
>>>NULL_TREE;
>>>     }
>>>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>+    {
>>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>>(mode),
>>>+						    GET_MODE_NUNITS (mode));
>>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>>+      return build_vector_type_for_mode (bool_type, mode);
>>>+    }
>>>   else if (VECTOR_MODE_P (mode)
>>> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>     {
>>>Index: gcc/go/go-lang.c
>>>===================================================================
>>>--- gcc/go/go-lang.c	2017-10-25 16:50:24.870603417 +0100
>>>+++ gcc/go/go-lang.c	2017-10-25 16:50:35.627184698 +0100
>>>@@ -372,9 +372,17 @@ go_langhook_type_for_mode (machine_mode
>>>      make sense for the middle-end to ask the frontend for a type
>>>      which the frontend does not support.  However, at least for now
>>>      it is required.  See PR 46805.  */
>>>-  if (VECTOR_MODE_P (mode)
>>>+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>>       && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>     {
>>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>>(mode),
>>>+						    GET_MODE_NUNITS (mode));
>>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>>+      return build_vector_type_for_mode (bool_type, mode);
>>>+    }
>>>+  else if (VECTOR_MODE_P (mode)
>>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>+    {
>>>       tree inner;
>>> 
>>>  inner = go_langhook_type_for_mode (GET_MODE_INNER (mode),
>unsignedp);
>>>Index: gcc/lto/lto-lang.c
>>>===================================================================
>>>--- gcc/lto/lto-lang.c	2017-10-25 16:50:24.871603378 +0100
>>>+++ gcc/lto/lto-lang.c	2017-10-25 16:50:35.628184659 +0100
>>>@@ -971,6 +971,14 @@ lto_type_for_mode (machine_mode mode, in
>>>       if (inner_type != NULL_TREE)
>>> 	return build_complex_type (inner_type);
>>>     }
>>>+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
>>>+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>+    {
>>>+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE
>>>(mode),
>>>+						    GET_MODE_NUNITS (mode));
>>>+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
>>>+      return build_vector_type_for_mode (bool_type, mode);
>>>+    }
>>>   else if (VECTOR_MODE_P (mode)
>>> 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
>>>     {
diff mbox series

Patch

Index: gcc/mode-classes.def
===================================================================
--- gcc/mode-classes.def	2017-10-25 16:50:18.000869425 +0100
+++ gcc/mode-classes.def	2017-10-25 16:50:35.628184659 +0100
@@ -31,6 +31,7 @@  along with GCC; see the file COPYING3.
   DEF_MODE_CLASS (MODE_DECIMAL_FLOAT),	/* decimal floating point */	   \
   DEF_MODE_CLASS (MODE_COMPLEX_INT), 	/* complex numbers */		   \
   DEF_MODE_CLASS (MODE_COMPLEX_FLOAT),					   \
+  DEF_MODE_CLASS (MODE_VECTOR_BOOL),	/* vectors of single bits */	   \
   DEF_MODE_CLASS (MODE_VECTOR_INT),	/* SIMD vectors */		   \
   DEF_MODE_CLASS (MODE_VECTOR_FRACT),	/* SIMD vectors */		   \
   DEF_MODE_CLASS (MODE_VECTOR_UFRACT),	/* SIMD vectors */		   \
Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-10-25 16:50:31.832332710 +0100
+++ gcc/machmode.h	2017-10-25 16:50:35.628184659 +0100
@@ -108,6 +108,7 @@  #define INTEGRAL_MODE_P(MODE)			\
   (GET_MODE_CLASS (MODE) == MODE_INT		\
    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
    || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
 
 /* Nonzero if MODE is a floating-point mode.  */
@@ -123,8 +124,9 @@  #define COMPLEX_MODE_P(MODE)			\
    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
 
 /* Nonzero if MODE is a vector mode.  */
-#define VECTOR_MODE_P(MODE)			\
-  (GET_MODE_CLASS (MODE) == MODE_VECTOR_INT	\
+#define VECTOR_MODE_P(MODE)				\
+  (GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL		\
+   || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT		\
    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT	\
    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT	\
    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT	\
Index: gcc/machmode.def
===================================================================
--- gcc/machmode.def	2017-10-25 16:50:18.000869425 +0100
+++ gcc/machmode.def	2017-10-25 16:50:35.628184659 +0100
@@ -142,6 +142,12 @@  along with GCC; see the file COPYING3.
 	than two bytes (if CLASS is FLOAT).  CLASS must be INT or
 	FLOAT.  The names follow the same rule as VECTOR_MODE uses.
 
+     VECTOR_BOOL_MODE (COUNT, BYTESIZE)
+	Create a vector of booleans with COUNT elements and BYTESIZE bytes.
+	Each boolean occupies (COUNT * BITS_PER_UNIT) / BYTESIZE bits,
+	with the element at index 0 occupying the lsb of the first byte
+	in memory.  Only the lowest bit of each element is significant.
+
      COMPLEX_MODES (CLASS);
         For all modes presently declared in class CLASS, construct
 	corresponding complex modes.  Modes smaller than one byte
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	2017-10-25 16:50:31.828332866 +0100
+++ gcc/genmodes.c	2017-10-25 16:50:35.627184698 +0100
@@ -375,6 +375,10 @@  complete_mode (struct mode_data *m)
       m->bytesize = 2 * m->component->bytesize;
       break;
 
+    case MODE_VECTOR_BOOL:
+      validate_mode (m, UNSET, SET, SET, SET, UNSET);
+      break;
+
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
     case MODE_VECTOR_FRACT:
@@ -526,6 +530,36 @@  make_vector_modes (enum mode_class cl, u
     }
 }
 
+/* Create a vector of booleans with COUNT elements and BYTESIZE bytes
+   in total.  */
+#define VECTOR_BOOL_MODE(COUNT, BYTESIZE) \
+  make_vector_bool_mode (COUNT, BYTESIZE, __FILE__, __LINE__)
+static void ATTRIBUTE_UNUSED
+make_vector_bool_mode (unsigned int count, unsigned int bytesize,
+		       const char *file, unsigned int line)
+{
+  struct mode_data *m = find_mode ("BI");
+  if (!m)
+    {
+      error ("%s:%d: no mode \"BI\"", file, line);
+      return;
+    }
+
+  char buf[8];
+  if ((size_t) snprintf (buf, sizeof buf, "V%uBI", count) >= sizeof buf)
+    {
+      error ("%s:%d: number of vector elements is too high",
+	     file, line);
+      return;
+    }
+
+  struct mode_data *v = new_mode (MODE_VECTOR_BOOL,
+				  xstrdup (buf), file, line);
+  v->component = m;
+  v->ncomponents = count;
+  v->bytesize = bytesize;
+}
+
 /* Input.  */
 
 #define _SPECIAL_MODE(C, N) \
@@ -1438,7 +1472,8 @@  emit_mode_wider (void)
 
 	  /* For vectors we want twice the number of components,
 	     with the same element type.  */
-	  if (m->cl == MODE_VECTOR_INT
+	  if (m->cl == MODE_VECTOR_BOOL
+	      || m->cl == MODE_VECTOR_INT
 	      || m->cl == MODE_VECTOR_FLOAT
 	      || m->cl == MODE_VECTOR_FRACT
 	      || m->cl == MODE_VECTOR_UFRACT
@@ -1657,6 +1692,7 @@  emit_mode_adjustments (void)
       printf ("\n  /* %s:%d */\n", a->file, a->line);
       switch (a->mode->cl)
 	{
+	case MODE_VECTOR_BOOL:
 	case MODE_VECTOR_INT:
 	case MODE_VECTOR_FLOAT:
 	case MODE_VECTOR_FRACT:
@@ -1688,6 +1724,10 @@  emit_mode_adjustments (void)
 		      m->name);
 	      break;
 
+	    case MODE_VECTOR_BOOL:
+	      /* Changes to BImode should not affect vector booleans.  */
+	      break;
+
 	    case MODE_VECTOR_INT:
 	    case MODE_VECTOR_FLOAT:
 	    case MODE_VECTOR_FRACT:
@@ -1728,6 +1768,10 @@  emit_mode_adjustments (void)
 	      printf ("  mode_base_align[E_%smode] = s;\n", m->name);
 	      break;
 
+	    case MODE_VECTOR_BOOL:
+	      /* Changes to BImode should not affect vector booleans.  */
+	      break;
+
 	    case MODE_VECTOR_INT:
 	    case MODE_VECTOR_FLOAT:
 	    case MODE_VECTOR_FRACT:
Index: gcc/lto-streamer-in.c
===================================================================
--- gcc/lto-streamer-in.c	2017-10-25 16:50:31.832332710 +0100
+++ gcc/lto-streamer-in.c	2017-10-25 16:50:35.628184659 +0100
@@ -1662,6 +1662,7 @@  lto_input_mode_table (struct lto_file_de
 	{
 	  switch (mclass)
 	    {
+	    case MODE_VECTOR_BOOL:
 	    case MODE_VECTOR_INT:
 	    case MODE_VECTOR_FLOAT:
 	    case MODE_VECTOR_FRACT:
Index: gcc/stor-layout.c
===================================================================
--- gcc/stor-layout.c	2017-10-25 16:50:24.925601288 +0100
+++ gcc/stor-layout.c	2017-10-25 16:50:35.629184620 +0100
@@ -378,12 +378,13 @@  int_mode_for_mode (machine_mode mode)
     case MODE_COMPLEX_FLOAT:
     case MODE_FLOAT:
     case MODE_DECIMAL_FLOAT:
-    case MODE_VECTOR_INT:
-    case MODE_VECTOR_FLOAT:
     case MODE_FRACT:
     case MODE_ACCUM:
     case MODE_UFRACT:
     case MODE_UACCUM:
+    case MODE_VECTOR_BOOL:
+    case MODE_VECTOR_INT:
+    case MODE_VECTOR_FLOAT:
     case MODE_VECTOR_FRACT:
     case MODE_VECTOR_ACCUM:
     case MODE_VECTOR_UFRACT:
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	2017-10-25 16:50:31.843332282 +0100
+++ gcc/tree.c	2017-10-25 16:50:35.630184581 +0100
@@ -10561,6 +10561,7 @@  build_vector_type_for_mode (tree innerty
 
   switch (GET_MODE_CLASS (mode))
     {
+    case MODE_VECTOR_BOOL:
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FLOAT:
     case MODE_VECTOR_FRACT:
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c	2017-10-25 16:50:24.928601171 +0100
+++ gcc/varasm.c	2017-10-25 16:50:35.631184542 +0100
@@ -3926,6 +3926,32 @@  output_constant_pool_2 (fixed_size_mode
       assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
       break;
 
+    case MODE_VECTOR_BOOL:
+      {
+	gcc_assert (GET_CODE (x) == CONST_VECTOR);
+
+	/* Pick the smallest integer mode that contains at least one
+	   whole element.  Often this is byte_mode and contains more
+	   than one element.  */
+	unsigned int nelts = CONST_VECTOR_NUNITS (x);
+	unsigned int elt_bits = GET_MODE_BITSIZE (mode) / nelts;
+	unsigned int int_bits = MAX (elt_bits, BITS_PER_UNIT);
+	scalar_int_mode int_mode = int_mode_for_size (int_bits, 0).require ();
+
+	/* Build the constant up one integer at a time.  */
+	unsigned int elts_per_int = int_bits / elt_bits;
+	for (unsigned int i = 0; i < nelts; i += elts_per_int)
+	  {
+	    unsigned HOST_WIDE_INT value = 0;
+	    unsigned int limit = MIN (nelts - i, elts_per_int);
+	    for (unsigned int j = 0; j < limit; ++j)
+	      if (INTVAL (CONST_VECTOR_ELT (x, i + j)) != 0)
+		value |= 1 << (j * elt_bits);
+	    output_constant_pool_2 (int_mode, gen_int_mode (value, int_mode),
+				    i != 0 ? MIN (align, int_bits) : align);
+	  }
+	break;
+      }
     case MODE_VECTOR_FLOAT:
     case MODE_VECTOR_INT:
     case MODE_VECTOR_FRACT:
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2017-10-25 16:50:31.826332943 +0100
+++ gcc/emit-rtl.c	2017-10-25 16:50:35.625184776 +0100
@@ -5960,6 +5960,16 @@  gen_const_vec_duplicate_1 (machine_mode
 rtx
 gen_const_vec_duplicate (machine_mode mode, rtx elt)
 {
+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+    {
+      if (elt == const1_rtx || elt == constm1_rtx)
+	return CONST1_RTX (mode);
+      else if (elt == const0_rtx)
+	return CONST0_RTX (mode);
+      else
+	gcc_unreachable ();
+    }
+
   scalar_mode inner_mode = GET_MODE_INNER (mode);
   if (elt == CONST0_RTX (inner_mode))
     return CONST0_RTX (mode);
@@ -6284,6 +6294,12 @@  init_emit_once (void)
   FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
     const_tiny_rtx[3][(int) mode] = constm1_rtx;
 
+  /* For BImode, 1 and -1 are unsigned and signed interpretations
+     of the same value.  */
+  const_tiny_rtx[0][(int) BImode] = const0_rtx;
+  const_tiny_rtx[1][(int) BImode] = const_true_rtx;
+  const_tiny_rtx[3][(int) BImode] = const_true_rtx;
+
   for (mode = MIN_MODE_PARTIAL_INT;
        mode <= MAX_MODE_PARTIAL_INT;
        mode = (machine_mode)((int)(mode) + 1))
@@ -6301,6 +6317,15 @@  init_emit_once (void)
       const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
     }
 
+  /* As for BImode, "all 1" and "all -1" are unsigned and signed
+     interpretations of the same value.  */
+  FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_BOOL)
+    {
+      const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
+      const_tiny_rtx[3][(int) mode] = gen_const_vector (mode, 3);
+      const_tiny_rtx[1][(int) mode] = const_tiny_rtx[3][(int) mode];
+    }
+
   FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
@@ -6402,10 +6427,6 @@  init_emit_once (void)
     if (GET_MODE_CLASS ((machine_mode) i) == MODE_CC)
       const_tiny_rtx[0][i] = const0_rtx;
 
-  const_tiny_rtx[0][(int) BImode] = const0_rtx;
-  if (STORE_FLAG_VALUE == 1)
-    const_tiny_rtx[1][(int) BImode] = const1_rtx;
-
   FOR_EACH_MODE_IN_CLASS (smode_iter, MODE_POINTER_BOUNDS)
     {
       scalar_mode smode = smode_iter.require ();
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-10-25 16:50:31.827332904 +0100
+++ gcc/expr.c	2017-10-25 16:50:35.627184698 +0100
@@ -10053,12 +10053,7 @@  expand_expr_real_1 (tree exp, rtx target
     case VECTOR_CST:
       {
 	tree tmp = NULL_TREE;
-	if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_FRACT
-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UFRACT
-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_ACCUM
-	    || GET_MODE_CLASS (mode) == MODE_VECTOR_UACCUM)
+	if (VECTOR_MODE_P (mode))
 	  return const_vector_from_tree (exp);
 	scalar_int_mode int_mode;
 	if (is_int_mode (mode, &int_mode))
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	2017-10-25 16:50:25.047596556 +0100
+++ gcc/tree-vect-generic.c	2017-10-25 16:50:35.629184620 +0100
@@ -980,12 +980,7 @@  expand_vector_operation (gimple_stmt_ite
   /* If the compute mode is not a vector mode (hence we are not decomposing
      a BLKmode vector to smaller, hardware-supported vectors), we may want
      to expand the operations in parallel.  */
-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
+  if (!VECTOR_MODE_P (compute_mode))
     switch (code)
       {
       case PLUS_EXPR:
@@ -1174,6 +1169,8 @@  type_for_widest_vector_mode (tree type,
     mode = MIN_MODE_VECTOR_ACCUM;
   else if (SCALAR_UACCUM_MODE_P (inner_mode))
     mode = MIN_MODE_VECTOR_UACCUM;
+  else if (inner_mode == BImode)
+    mode = MIN_MODE_VECTOR_BOOL;
   else
     mode = MIN_MODE_VECTOR_INT;
 
@@ -1531,12 +1528,7 @@  expand_vector_scalar_condition (gimple_s
   /* If the compute mode is not a vector mode (hence we are not decomposing
      a BLKmode vector to smaller, hardware-supported vectors), we may want
      to expand the operations in parallel.  */
-  if (GET_MODE_CLASS (compute_mode) != MODE_VECTOR_INT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FLOAT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_FRACT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UFRACT
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_ACCUM
-      && GET_MODE_CLASS (compute_mode) != MODE_VECTOR_UACCUM)
+  if (!VECTOR_MODE_P (compute_mode))
     new_rhs = expand_vector_parallel (gsi, do_cond, type, rhs2, rhs3,
 				      COND_EXPR);
   else
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	2017-10-25 16:50:24.861603766 +0100
+++ gcc/c-family/c-common.c	2017-10-25 16:50:35.625184776 +0100
@@ -2281,6 +2281,14 @@  c_common_type_for_mode (machine_mode mod
       if (inner_type != NULL_TREE)
 	return build_complex_type (inner_type);
     }
+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+    {
+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
+						    GET_MODE_NUNITS (mode));
+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
+      return build_vector_type_for_mode (bool_type, mode);
+    }
   else if (VECTOR_MODE_P (mode)
 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
     {
Index: gcc/fortran/trans-types.c
===================================================================
--- gcc/fortran/trans-types.c	2017-10-25 16:50:24.869603456 +0100
+++ gcc/fortran/trans-types.c	2017-10-25 16:50:35.627184698 +0100
@@ -3159,6 +3159,14 @@  gfc_type_for_mode (machine_mode mode, in
       tree type = gfc_type_for_size (GET_MODE_PRECISION (int_mode), unsignedp);
       return type != NULL_TREE && mode == TYPE_MODE (type) ? type : NULL_TREE;
     }
+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+    {
+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
+						    GET_MODE_NUNITS (mode));
+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
+      return build_vector_type_for_mode (bool_type, mode);
+    }
   else if (VECTOR_MODE_P (mode)
 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
     {
Index: gcc/go/go-lang.c
===================================================================
--- gcc/go/go-lang.c	2017-10-25 16:50:24.870603417 +0100
+++ gcc/go/go-lang.c	2017-10-25 16:50:35.627184698 +0100
@@ -372,9 +372,17 @@  go_langhook_type_for_mode (machine_mode
      make sense for the middle-end to ask the frontend for a type
      which the frontend does not support.  However, at least for now
      it is required.  See PR 46805.  */
-  if (VECTOR_MODE_P (mode)
+  if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
       && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
     {
+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
+						    GET_MODE_NUNITS (mode));
+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
+      return build_vector_type_for_mode (bool_type, mode);
+    }
+  else if (VECTOR_MODE_P (mode)
+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+    {
       tree inner;
 
       inner = go_langhook_type_for_mode (GET_MODE_INNER (mode), unsignedp);
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	2017-10-25 16:50:24.871603378 +0100
+++ gcc/lto/lto-lang.c	2017-10-25 16:50:35.628184659 +0100
@@ -971,6 +971,14 @@  lto_type_for_mode (machine_mode mode, in
       if (inner_type != NULL_TREE)
 	return build_complex_type (inner_type);
     }
+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL
+	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
+    {
+      unsigned int elem_bits = vector_element_size (GET_MODE_BITSIZE (mode),
+						    GET_MODE_NUNITS (mode));
+      tree bool_type = build_nonstandard_boolean_type (elem_bits);
+      return build_vector_type_for_mode (bool_type, mode);
+    }
   else if (VECTOR_MODE_P (mode)
 	   && valid_vector_subparts_p (GET_MODE_NUNITS (mode)))
     {