https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97579
--- Comment #3 from rguenther at suse dot de <rguenther at suse dot de> --- On Tue, 27 Oct 2020, marxin at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97579 > > --- Comment #2 from Martin Li?ka <marxin at gcc dot gnu.org> --- > (In reply to Richard Biener from comment #1) > > So we have used_vec_cond_exprs == 1 and a V16SI eq/ne compare with a > > vector(16) <signed-boolean:1> HImode result. We fall into > > > > gcc_assert (known_eq (GET_MODE_SIZE (mode), GET_MODE_SIZE (cmp_op_mode)) > > && known_eq (GET_MODE_NUNITS (mode), > > GET_MODE_NUNITS (cmp_op_mode))); > > > > then but this is clearly a case where we _have_ to use the vec_cmp_expr > > (because of the scalar mode). So either simply remove the > > used_vec_cond_exprs check or amend it with the negative of the above assert. > > No, used_vec_cond_exprs == 2, but we fail here: > > 166 if (used_vec_cond_exprs >= 2 > 167 && (get_vcond_mask_icode (mode, TYPE_MODE (op0a_type)) > 168 != CODE_FOR_nothing) > 169 && expand_vec_cmp_expr_p (op0a_type, TREE_TYPE (lhs), > tcode)) > > where: > > #0 get_vcond_mask_icode (vmode=E_HImode, mmode=E_V16SImode) at > /home/marxin/Programming/gcc/gcc/optabs-query.h:131 > > returns false. 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? 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) 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. 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.