https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111337

--- Comment #7 from JuzheZhong <juzhe.zhong at rivai dot ai> ---
(In reply to rguent...@suse.de from comment #6)
> On Tue, 12 Sep 2023, juzhe.zhong at rivai dot ai wrote:
> 
> > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111337
> > 
> > --- Comment #5 from JuzheZhong <juzhe.zhong at rivai dot ai> ---
> > Oh. I see.
> > 
> > 
> > (define_expand "@vcond_mask_<mode><mode>"
> >   [(match_operand:VB 0 "register_operand")
> >    (match_operand:VB 3 "register_operand")
> >    (match_operand:VB 1 "nonmemory_operand")
> >    (match_operand:VB 2 "register_operand")]
> >   "TARGET_VECTOR"
> >   {
> >    printf ("vcond_mask\n");
> >   })
> > 
> > I implemented this pattern which can address this issue....
> > 
> > Note that VB is VECTR_BOOL...
> > 
> > So, this is a more reasonable way to do. Is that right?
> 
> Ah, I suppose ISEL could special-case VECTOR_BOOLEAN_P COND_EXPR
> to expand to bitwise ops - it already does this, but only for
> non-vector-mode masks:
> 
>   /* Lower mask typed, non-vector mode 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).  */
>   if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (lhs))
>       && !VECTOR_MODE_P (mode))
>     {
>       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);
>     }
> 
> that could be a viable expansion strathegy when the rest fails,
> but as you can see we need four stmts for this.  If you can
> think of a smarter, maybe even single-instruction, way for riscv
> then yes, handling the above pattern looks good.
> 
> I wonder whether SVE/GCN have those.

I have supported this pattern but also need 4 instructions:

(define_expand "@vcond_mask_<mode><mode>"
  [(match_operand:VB 0 "register_operand")
   (match_operand:VB 1 "register_operand")
   (match_operand:VB 2 "register_operand")
   (match_operand:VB 3 "register_operand")]
  "TARGET_VECTOR"
  {
    /* mask1 = operands[3] & operands[1].  */
    rtx mask1 = expand_binop (<MODE>mode, and_optab, operands[1],
                              operands[3], NULL_RTX, 0,
                              OPTAB_DIRECT);
    /* mask2 = ~operands[3] & operands[2].  */
    rtx inverse = expand_unop (<MODE>mode, one_cmpl_optab, operands[3],
                               NULL_RTX,
                               OPTAB_DIRECT);
    rtx mask2 = expand_binop (<MODE>mode, and_optab, operands[2],
                              inverse, NULL_RTX, 0,
                              OPTAB_DIRECT);
    /* result = mask1 | mask2.  */
    rtx result = expand_binop (<MODE>mode, ior_optab, mask1,
                               mask2, NULL_RTX, 0,
                               OPTAB_DIRECT);
    emit_move_insn (operands[0], result);
    DONE;
  })

Reply via email to