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)))
     {
