diff mbox

[PR,target/69010] Fix expand for constant boolean vectors with a scalar mode

Message ID 20151223091424.GA35713@msticlxl57.ims.intel.com
State New
Headers show

Commit Message

Ilya Enkovich Dec. 23, 2015, 9:14 a.m. UTC
Hi,

Currently boolean vector constant is expanded incorrectly when
it has a scalar mode.  Generated constant is incorrect and also
its mode (which is VOIDmode) is used for roce_reg which causes
ICE.  This patch fixes both problems.  Bootstrapped and tested
on x86_64-pc-linux-gnu.  OK for trunk?

Thanks,
Ilya
--
gcc/

2015-12-23  Ilya Enkovich  <enkovich.gnu@gmail.com>

	* expr.c (expand_expr_real_1): For boolean vector constants
	with a scalar mode use const_scalar_mask_from_tree.
	(const_scalar_mask_from_tree): New.
	* optabs.c (expand_vec_cond_mask_expr): Use mask mode
	assigned to a mask type to handle constants.

gcc/testsuite/

2015-12-23  Ilya Enkovich  <enkovich.gnu@gmail.com>

	* gcc.target/i386/pr69010.c: New test.

Comments

Richard Biener Jan. 8, 2016, 9:46 a.m. UTC | #1
On Wed, Dec 23, 2015 at 10:14 AM, Ilya Enkovich <enkovich.gnu@gmail.com> wrote:
> Hi,
>
> Currently boolean vector constant is expanded incorrectly when
> it has a scalar mode.  Generated constant is incorrect and also
> its mode (which is VOIDmode) is used for roce_reg which causes
> ICE.  This patch fixes both problems.  Bootstrapped and tested
> on x86_64-pc-linux-gnu.  OK for trunk?

Ok.

Thanks,
Richard.

> Thanks,
> Ilya
> --
> gcc/
>
> 2015-12-23  Ilya Enkovich  <enkovich.gnu@gmail.com>
>
>         * expr.c (expand_expr_real_1): For boolean vector constants
>         with a scalar mode use const_scalar_mask_from_tree.
>         (const_scalar_mask_from_tree): New.
>         * optabs.c (expand_vec_cond_mask_expr): Use mask mode
>         assigned to a mask type to handle constants.
>
> gcc/testsuite/
>
> 2015-12-23  Ilya Enkovich  <enkovich.gnu@gmail.com>
>
>         * gcc.target/i386/pr69010.c: New test.
>
>
> diff --git a/gcc/expr.c b/gcc/expr.c
> index bd43dc4..2183ef2 100644
> --- a/gcc/expr.c
> +++ b/gcc/expr.c
> @@ -137,6 +137,7 @@ static void emit_single_push_insn (machine_mode, rtx, tree);
>  #endif
>  static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int);
>  static rtx const_vector_from_tree (tree);
> +static rtx const_scalar_mask_from_tree (tree);
>  static tree tree_expr_size (const_tree);
>  static HOST_WIDE_INT int_expr_size (tree);
>
> @@ -9745,9 +9746,15 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
>           return const_vector_from_tree (exp);
>         if (GET_MODE_CLASS (mode) == MODE_INT)
>           {
> -           tree type_for_mode = lang_hooks.types.type_for_mode (mode, 1);
> -           if (type_for_mode)
> -             tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR, type_for_mode, exp);
> +           if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
> +             return const_scalar_mask_from_tree (exp);
> +           else
> +             {
> +               tree type_for_mode = lang_hooks.types.type_for_mode (mode, 1);
> +               if (type_for_mode)
> +                 tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR,
> +                                       type_for_mode, exp);
> +             }
>           }
>         if (!tmp)
>           {
> @@ -11458,6 +11465,29 @@ const_vector_mask_from_tree (tree exp)
>    return gen_rtx_CONST_VECTOR (mode, v);
>  }
>
> +/* Return a CONST_INT rtx representing vector mask for
> +   a VECTOR_CST of booleans.  */
> +static rtx
> +const_scalar_mask_from_tree (tree exp)
> +{
> +  machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
> +  wide_int res = wi::zero (GET_MODE_PRECISION (mode));
> +  tree elt;
> +  unsigned i;
> +
> +  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
> +    {
> +      elt = VECTOR_CST_ELT (exp, i);
> +      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
> +      if (integer_all_onesp (elt))
> +       res = wi::set_bit (res, i);
> +      else
> +       gcc_assert (integer_zerop (elt));
> +    }
> +
> +  return immed_wide_int_const (res, mode);
> +}
> +
>  /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
>  static rtx
>  const_vector_from_tree (tree exp)
> diff --git a/gcc/optabs.c b/gcc/optabs.c
> index 8cc4802..ae675fb 100644
> --- a/gcc/optabs.c
> +++ b/gcc/optabs.c
> @@ -5547,7 +5547,7 @@ expand_vec_cond_mask_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
>    rtx_op1 = expand_normal (op1);
>    rtx_op2 = expand_normal (op2);
>
> -  mask = force_reg (GET_MODE (mask), mask);
> +  mask = force_reg (mask_mode, mask);
>    rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
>
>    create_output_operand (&ops[0], target, mode);
> diff --git a/gcc/testsuite/gcc.target/i386/pr69010.c b/gcc/testsuite/gcc.target/i386/pr69010.c
> new file mode 100644
> index 0000000..29f66f4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/pr69010.c
> @@ -0,0 +1,49 @@
> +/* { dg-do run } */
> +/* { dg-options "-O2 -ftree-vectorize -mavx512bw" } */
> +/* { dg-require-effective-target avx512bw } */
> +
> +#define AVX512BW
> +#include "avx512f-helper.h"
> +
> +extern void abort (void);
> +
> +void __attribute__((noinline,noclone))
> +test1 (int *a, int *b, int *c)
> +{
> +  int i;
> +  for (i = 0; i < 16; i++)
> +    {
> +      if ((i == 0) || (i == 3))
> +       a[i] = b[i];
> +      else
> +       a[i] = c[i];
> +    }
> +}
> +
> +void
> +TEST ()
> +{
> +  int a[16], b[16], c[16], i;
> +
> +  for (i = 0; i < 16; i++)
> +    {
> +      a[i] = i;
> +      b[i] = -i;
> +    }
> +
> +  test1 (a, b, c);
> +
> +  for (i = 0; i < 16; i++)
> +    {
> +      if ((i == 0) || (i == 3))
> +       {
> +         if (a[i] != b[i])
> +           abort ();
> +       }
> +      else
> +       {
> +         if (a[i] != c[i])
> +           abort ();
> +       }
> +    }
> +}
diff mbox

Patch

diff --git a/gcc/expr.c b/gcc/expr.c
index bd43dc4..2183ef2 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -137,6 +137,7 @@  static void emit_single_push_insn (machine_mode, rtx, tree);
 #endif
 static void do_tablejump (rtx, machine_mode, rtx, rtx, rtx, int);
 static rtx const_vector_from_tree (tree);
+static rtx const_scalar_mask_from_tree (tree);
 static tree tree_expr_size (const_tree);
 static HOST_WIDE_INT int_expr_size (tree);
 
@@ -9745,9 +9746,15 @@  expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
 	  return const_vector_from_tree (exp);
 	if (GET_MODE_CLASS (mode) == MODE_INT)
 	  {
-	    tree type_for_mode = lang_hooks.types.type_for_mode (mode, 1);
-	    if (type_for_mode)
-	      tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR, type_for_mode, exp);
+	    if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (exp)))
+	      return const_scalar_mask_from_tree (exp);
+	    else
+	      {
+		tree type_for_mode = lang_hooks.types.type_for_mode (mode, 1);
+		if (type_for_mode)
+		  tmp = fold_unary_loc (loc, VIEW_CONVERT_EXPR,
+					type_for_mode, exp);
+	      }
 	  }
 	if (!tmp)
 	  {
@@ -11458,6 +11465,29 @@  const_vector_mask_from_tree (tree exp)
   return gen_rtx_CONST_VECTOR (mode, v);
 }
 
+/* Return a CONST_INT rtx representing vector mask for
+   a VECTOR_CST of booleans.  */
+static rtx
+const_scalar_mask_from_tree (tree exp)
+{
+  machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
+  wide_int res = wi::zero (GET_MODE_PRECISION (mode));
+  tree elt;
+  unsigned i;
+
+  for (i = 0; i < VECTOR_CST_NELTS (exp); ++i)
+    {
+      elt = VECTOR_CST_ELT (exp, i);
+      gcc_assert (TREE_CODE (elt) == INTEGER_CST);
+      if (integer_all_onesp (elt))
+	res = wi::set_bit (res, i);
+      else
+	gcc_assert (integer_zerop (elt));
+    }
+
+  return immed_wide_int_const (res, mode);
+}
+
 /* Return a CONST_VECTOR rtx for a VECTOR_CST tree.  */
 static rtx
 const_vector_from_tree (tree exp)
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 8cc4802..ae675fb 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -5547,7 +5547,7 @@  expand_vec_cond_mask_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
   rtx_op1 = expand_normal (op1);
   rtx_op2 = expand_normal (op2);
 
-  mask = force_reg (GET_MODE (mask), mask);
+  mask = force_reg (mask_mode, mask);
   rtx_op1 = force_reg (GET_MODE (rtx_op1), rtx_op1);
 
   create_output_operand (&ops[0], target, mode);
diff --git a/gcc/testsuite/gcc.target/i386/pr69010.c b/gcc/testsuite/gcc.target/i386/pr69010.c
new file mode 100644
index 0000000..29f66f4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr69010.c
@@ -0,0 +1,49 @@ 
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-vectorize -mavx512bw" } */
+/* { dg-require-effective-target avx512bw } */
+
+#define AVX512BW
+#include "avx512f-helper.h"
+
+extern void abort (void);
+
+void __attribute__((noinline,noclone))
+test1 (int *a, int *b, int *c)
+{
+  int i;
+  for (i = 0; i < 16; i++)
+    {
+      if ((i == 0) || (i == 3))
+	a[i] = b[i];
+      else
+	a[i] = c[i];
+    }
+}
+
+void
+TEST ()
+{
+  int a[16], b[16], c[16], i;
+
+  for (i = 0; i < 16; i++)
+    {
+      a[i] = i;
+      b[i] = -i;
+    }
+
+  test1 (a, b, c);
+
+  for (i = 0; i < 16; i++)
+    {
+      if ((i == 0) || (i == 3))
+	{
+	  if (a[i] != b[i])
+	    abort ();
+	}
+      else
+	{
+	  if (a[i] != c[i])
+	    abort ();
+	}
+    }
+}