Message ID | 20151223091424.GA35713@msticlxl57.ims.intel.com |
---|---|
State | New |
Headers | show |
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 --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 (); + } + } +}