On Wed, Dec 23, 2015 at 10:14 AM, Ilya Enkovich <enkovich....@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....@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....@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 (); > + } > + } > +}