https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97579
--- Comment #4 from Martin Liška <marxin at gcc dot gnu.org> --- > > Hmm, but get_vcond_mask_icode expects the vector mode first and the > mask mode second. But it would be odd if that's the mistake... > (but the patterns agree as well). > > Now, the code seems to be a bit confused. We're looking at > > > op0 = op0a tcode op0b; > lhs = op0 ? op1 : op2; > > and I assume the check tries to verify we can expand both the > compare-to-mask and the vcond_mask. Then we need to query > > tree op0_type = TREE_TYPE (op0); > tree op0a_type = TREE_TYPE (op0a); > if (used_vec_cond_exprs >= 2 > && (get_vcond_mask_icode (mode, TYPE_MODE (op0_type)) > != CODE_FOR_nothing) > && expand_vec_cmp_expr_p (op0a_type, op0_type, tcode)) > { > > no? Yes, the code was really bogus. I understand it now as you and there's patch for it: diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc index b64e31fc6fe..bba41f84ef1 100644 --- a/gcc/gimple-isel.cc +++ b/gcc/gimple-isel.cc @@ -158,15 +158,22 @@ gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi, gassign *def_stmt = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (op0)); if (def_stmt) { + /* We process the following statements: + op0 = op0a tcode op0b; + lhs = op0 ? op1 : op2; + + where MODE is mode of the LHS. + */ tcode = gimple_assign_rhs_code (def_stmt); op0a = gimple_assign_rhs1 (def_stmt); op0b = gimple_assign_rhs2 (def_stmt); + tree op0_type = TREE_TYPE (op0); tree op0a_type = TREE_TYPE (op0a); if (used_vec_cond_exprs >= 2 - && (get_vcond_mask_icode (mode, TYPE_MODE (op0a_type)) + && (get_vcond_mask_icode (mode, TYPE_MODE (op0_type)) != CODE_FOR_nothing) - && expand_vec_cmp_expr_p (op0a_type, TREE_TYPE (lhs), tcode)) + && expand_vec_cmp_expr_p (op0a_type, op0_type, tcode)) { /* Keep the SSA name and use vcond_mask. */ tcode = TREE_CODE (op0); > That would match > > if (TREE_CODE_CLASS (tcode) != tcc_comparison) > { > gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0))); > if (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0))) > != CODE_FOR_nothing) Yes, it's expanded as a .VCOND_MASK now. > > Doing that shifts the ICE elsewhere though: > > during GIMPLE pass: isel > x.c: In function 'calc_rows': > x.c:22:1: internal compiler error: in gimple_expand_vec_cond_expr, at > gimple-isel.cc:204 > 22 | calc_rows() { > | ^~~~~~~~~ > 0x17c3bd8 gimple_expand_vec_cond_expr > /home/rguenther/src/gcc2/gcc/gimple-isel.cc:202 > > Now we face the situation where lhs == HImode but op0a is V16SImode > so a VEC_COND_EXPR combining masks based on a compare. That's > a situation we didn't run into before the VEC_COND_EXPR splitting. I can confirm that: mask__258.180_254 = vect_cst__77 != { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; mask__581.198_1001 = VEC_COND_EXPR <mask__258.180_254, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, mask__649.184_117>; > > Which means we're missing a fallback like > > if (expand_vec_cmp_expr_p (op0a_type, op0_type, tcode)) > { > expand the comparison to a mask > turn the VEC_COND_EXPR into a mask operation, > maskr = cmpmask ? maska : maskb; > becomes > maskr = (maska & cmpmask) | (maskb & ~cmpmask); > } > > the alternative is to add vcond_mask patterns for mask value modes > (I think vternlog can do this in one operation, there may also be > a mask operation for this). But that would be an enhancement > and not require any new fallback code. > > But first double-check the first point I made above.