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....@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 (); + } + } +}