Richard Biener <rguent...@suse.de> writes: > This makes sure to lower VECTOR_BOOLEAN_TYPE_P typed VEC_COND_EXPRs > so we don't try to use vcond to expand those. That's especially > improtant for x86 integer mode boolean vectors but eventually > as well for aarch64 / gcn VnBImode ones. > > Bootstrap and regtest running on x86_64-unknown-linux-gnu. > > 2020-11-25 Richard Biener <rguent...@suse.de> > > PR middle-end/97579 > * gimple-isel.cc (gimple_expand_vec_cond_expr): Lower > VECTOR_BOOLEAN_TYPE_P VEC_COND_EXPRs. > > * gcc.dg/pr97579.c: New testcase. > --- > gcc/gimple-isel.cc | 21 +++++++++++++++++++-- > gcc/testsuite/gcc.dg/pr97579.c | 31 +++++++++++++++++++++++++++++++ > 2 files changed, 50 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/pr97579.c > > diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc > index b5362cc4b01..eac1f62e1ff 100644 > --- a/gcc/gimple-isel.cc > +++ b/gcc/gimple-isel.cc > @@ -37,6 +37,7 @@ along with GCC; see the file COPYING3. If not see > #include "tree-ssa-dce.h" > #include "memmodel.h" > #include "optabs.h" > +#include "gimple-fold.h" > > /* Expand all ARRAY_REF(VIEW_CONVERT_EXPR) gimple assignments into calls to > internal function based on vector type of selected expansion. > @@ -134,6 +135,24 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi, > lhs = gimple_assign_lhs (stmt); > machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); > > + /* Lower mask typed VEC_COND_EXPRs to bitwise operations. Those can > + end up generated by folding and at least for integer mode masks > + we cannot expect vcond expanders to exist. We lower a ? b : c > + to (b & a) | (c & ~a). */
I think it is reasonable to provide them for vector modes though. E.g. for SVE we have: (define_insn "@vcond_mask_<mode><mode>" [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa") (ior:PRED_ALL (and:PRED_ALL (match_operand:PRED_ALL 3 "register_operand" "Upa") (match_operand:PRED_ALL 1 "register_operand" "Upa")) (and:PRED_ALL (not (match_dup 3)) (match_operand:PRED_ALL 2 "register_operand" "Upa"))))] "TARGET_SVE" "sel\t%0.b, %3, %1.b, %2.b" ) So it might better to check for an integer mode as well. Thanks, Richard > + if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (lhs))) > + { > + gcc_assert (types_compatible_p (TREE_TYPE (op0), TREE_TYPE (op1))); > + gimple_seq stmts = NULL; > + tree type = TREE_TYPE (lhs); > + location_t loc = gimple_location (stmt); > + tree tem0 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op1, op0); > + tree tem1 = gimple_build (&stmts, loc, BIT_NOT_EXPR, type, op0); > + tree tem2 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op2, tem1); > + tree tem3 = gimple_build (&stmts, loc, BIT_IOR_EXPR, type, tem0, tem2); > + gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT); > + return gimple_build_assign (lhs, tem3); > + } > + > gcc_assert (!COMPARISON_CLASS_P (op0)); > if (TREE_CODE (op0) == SSA_NAME) > { > @@ -198,7 +217,6 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi, > cmp_op_mode = TYPE_MODE (TREE_TYPE (op0a)); > unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a)); > > - > gcc_assert (known_eq (GET_MODE_NUNITS (mode), > GET_MODE_NUNITS (cmp_op_mode))); > > @@ -246,7 +264,6 @@ gimple_expand_vec_exprs (void) > { > gimple *g = gimple_expand_vec_cond_expr (&gsi, > &vec_cond_ssa_name_uses); > - > if (g != NULL) > { > tree lhs = gimple_assign_lhs (gsi_stmt (gsi)); > diff --git a/gcc/testsuite/gcc.dg/pr97579.c b/gcc/testsuite/gcc.dg/pr97579.c > new file mode 100644 > index 00000000000..5cd5427a528 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/pr97579.c > @@ -0,0 +1,31 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O3 --param=max-unswitch-insns=1024" } */ > +/* { dg-additional-options "-mavx512vl" { target x86_64-*-* i?86-*-* } } */ > + > +int bad_odd_rows_0_0, rows_bad_row1, rows_bad_group_okay, calc_rows_row2; > + > +int > +rows_bad() { > + int i, in_zeroes; > + char block; > + i = 0; > + for (; i < 5; i++) > + if (rows_bad_row1 & i) > + in_zeroes = 0; > + else { > + if (!in_zeroes) > + in_zeroes = 1; > + if (block & 1) > + rows_bad_group_okay = 1; > + } > + if (in_zeroes) > + return rows_bad_group_okay; > +} > + > +void > +calc_rows() { > + for (; calc_rows_row2; calc_rows_row2++) { > + rows_bad(); > + bad_odd_rows_0_0 = rows_bad(); > + } > +}