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.

Reply via email to