On Fri, 17 Jul 2026, Jeffrey Law wrote:

> 
> 
> On 5/19/2026 6:14 AM, Robin Dapp wrote:
> > Hi,
> >
> > I have been playing around with a vec_predicate RTX locally, moving parts of
> > the RVV backend over to it.  Its main purpose is to lay out common operands
> > in
> > a fixed order.  This helps rtl passes to reason about the predicate as a
> > whole,
> > as well as backends which needed to carry index information if they wanted
> > to
> > access particular fields.
> And just to be clear, the ability to find the predicate and interpret is a
> huge part of the motivation here.
> 
> >
> > The staging I have in mind is roughly, each at least one patch:
> >
> >   (1) Add basic vec_predicate plumbing for non-"move" insns.
> >   (2) Handle vec_predicate in simplify-rtx to allow canonicalization,
> >   merging,
> >       and elision.
> >   (3) Convert a self-contained subset of RVV instructions to the new format.
> >
> > A vec_predicate would look like this:
> >
> > (define_insn "pred_add"
> >    [(set (match_operand:V 0      "register_operand"      "=vd")
> >  (vec_predicate:V plus
> >    [(match_operand:V 3   "register_operand"      " v")
> >    (match_operand:V 4   "register_operand"      " v")]

So there's not actually the predicated RTL operation, but just
the code and a vector of ... operands?  I'd have expected either

 (vec_predicate
  (plus:<mode> (...) (...))

or

 (cond_plus:<mode>
  (vec_predicate
    ...)
  (...) (...))

where the latter is probably "safer" combine/split wise.  The latter
would mimic .COND_* ifns on GIMPLE, but of course we'd explode the
RTX code somewhat unless we maybe stage it like

 (cond_op:<mode> PLUS
  (vec_predicate ...)
  (...) (...))

and that's where you come from?  Having (vec_predicate ..) as
nested RTX would allow that to be compile-time shortened for
targets that do not need all of the below ...

> >    (match_operand:V 2    "else_operand"          " velse")
> >    (match_operand:<VM> 1 "mask_operand"          " vm")
> >    (match_operand 5      "vector_length_operand" " vl")
> >    (const_int 0)                                              # Bias
> >    (match_operand 6      "const_int_operand"     " i")     # Length else
> >    policy
> >    (match_operand 7      "const_int_operand"     " i")))]) # Mask else
> >    policy
> So at a high level this seems to broadly match what the RISC-V backend is
> doing.  That shouldn't be a big surprise to anyone.

... like x86 can do with mask_operand and else_operand.

> >
> > As AVX and SVE don't need operands 5-7, and most autovec patterns might not
> > even need the else/mask, I added default-fill parsing in read-rtl: If a
> > vec_predicate ends prematurely, the remaining operands are filled with
> > "autovec" defaults like zero-fill policies, no bias, full length, etc.
> > One issue with default filling is the mode of else and mask.  I hope that
> > can work if we use dedicated sentinels like VEC_UNDEF and VEC_ALL_TRUE
> > (which target predicates would need to allow)?
> I think as long as we can avoid the need for the other architectures to worry
> about this stuff with any kind of regularity, then we're going to be in good
> shape.  Obviously the RTL optimizers will need awareness, but the target files
> shouldn't.  If that means we need a few well known sentinels, that's OK by me.
>
> >
> > What's not yet covered but should be in the future:
> >
> >   - Predicated vector "copy" insns (register copy, load, store).
> >     During initial brainstorming we couldn't come up with a good way to
> >     represent predicated vector stores.
> >     What could perhaps work is something like
> >      [(set (reg:V) (vec_predicate:V vec_copy [reg:V] ...))]
> >    and
> >      [(set (reg:V) (vec_predicate:V vec_copy [mem:V] ...))]
> >      [(set (mem:V) (vec_predicate:V vec_copy [reg:V] ...))]
> >    where the mem attributes could still be stored in dest or src.
> >    This obviously would not inherit any regular "move" handling we have.
> >    I'm not sure this is a good thing :)  But at least it would be a clear
> >    cut.
> I can probably live with moves being special.  Exposing the predicates on the
> operations seems like the big gain to me, even if we have a few stragglers
> like moves.
> 
> >
> > Once we have predicated loads, the question of vectorizer interaction needs
> > to
> > come up, which brings us to another work or staging item:
> >
> >   (4?) Add handling for the new shape to ifn and optabs.  So far, I couldn't
> >        think of a nicer way of identifying "vec_predicate"-style
> >        optabs/insns
> >        than adding a field to idata and have it be populated by genoutput
> >        and
> >        friends.  Then, we could do something like
> >  bool
> >      insn_has_vec_predicate (enum insn_code icode)
> >       {
> >         return insn_data[icode].vec_predicate_opno >= 0;
> >       }
> Seems basically reasonable and it allows you to trivially gate all kinds of
> behavior that most targets aren't going to need.
> 
> >
> > gcc/ChangeLog:
> >
> >  * cse.cc (hash_rtx): Hash predicate code.
> >  (exp_equiv_p): Return false for unequal code.
> >  * cselib.cc (rtx_equal_for_cselib_1): Ditto.
> >  (cselib_hash_rtx): Add predicate code to hash.
> >  * doc/rtl.texi: Document vector predicate.
> >  * dwarf2out.cc (mem_loc_descriptor): Break for vec_predicate.
> >  * emit-rtl.cc (init_emit_once): Init vec_all_true and vec_undef.
> >  (rtx_expander::get_rtx): Set vec_predicate code.
> >  (gen_vec_predicate): New function to generate a default
> >  vector predicate.
> >  (verify_vec_predicate): Verify vector predicate.
> >  * genemit.cc (generator::add_exp): Encode vec_predicate code.
> >  * genrecog.cc (rtx_test::vec_pred_code_field): Add.
> >  (safe_to_hoist_p): Ditto.
> >  (transition_parameter_type): Ditto.
> >  (match_pattern_2): Ditto.
> >  (print_nonbool_test): Print vec_predicate.
> >  (print_test): Handle vec_predicate.
> >  * print-rtl.cc (rtx_writer::print_rtx): Ditto.
> >  * read-rtl.cc (apply_code_iterator): Ditto.
> >  (rtx_reader::read_rtx_code): Ditto.
> >  * rtl.cc (DEF_RTL_EXPR): Declare vec_all_true and vec_undef.
> >  (rtx_equal_p): Compare vec_predicate code.
> >  * rtl.def (VEC_ALL_TRUE): Declare.
> >  (VEC_UNDEF): Ditto.
> >  (VEC_PREDICATE): Declare.
> >  * rtl.h (struct GTY): Add vec_pred_code.
> >  (VEC_PRED_CODE):  Add.
> >  (PUT_VEC_PRED_CODE): Add.
> >  (VEC_PRED_OPERANDS): Add.
> >  (VEC_PRED_NOPERANDS): Add.
> >  (VEC_PRED_OPERAND): Add.
> >  (VEC_PRED_ELSE): Add.
> >  (VEC_PRED_MASK): Add.
> >  (VEC_PRED_LENGTH): Add.
> >  (VEC_PRED_BIAS): Add.
> >  (VEC_PRED_TAIL_POLICY): Add.
> >  (VEC_PRED_MASK_POLICY): Add.
> >  (VEC_PRED_FIRST_OPTIONAL): Add.
> >  (VEC_PRED_UNDEF_ELSE_P): Add.
> >  (VEC_PRED_FULL_LEN): Add.
> >  (VEC_PRED_ALL_TRUE_P): Add.
> >  (enum vec_pred_policy): Add.
> >  (VEC_PRED_POLICY_MAX): Add.
> >  (VEC_PRED_POLICY_VALID_P): Add.
> >  (VEC_PRED_POLICY_PRESERVE_P): Add.
> >  (gen_vec_predicate): Declare.
> >  (verify_vec_predicate): Declare.
> >  (GTY): Declare vec_all_true and vec_undefined.
> > ---
> >   gcc/cse.cc       |  9 +++++
> >   gcc/cselib.cc    |  9 +++++
> >   gcc/doc/rtl.texi | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
> >   gcc/dwarf2out.cc |  1 +
> >   gcc/emit-rtl.cc  | 69 ++++++++++++++++++++++++++++++++++++
> >   gcc/genemit.cc   |  4 +++
> >   gcc/genrecog.cc  | 25 +++++++++++++
> >   gcc/print-rtl.cc |  3 ++
> >   gcc/read-rtl.cc  | 72 ++++++++++++++++++++++++++++++++++++--
> >   gcc/rtl.cc       | 11 ++++++
> >   gcc/rtl.def      | 18 ++++++++++
> >   gcc/rtl.h        | 55 +++++++++++++++++++++++++++++
> >   12 files changed, 365 insertions(+), 2 deletions(-)
> >
> > diff --git a/gcc/cse.cc b/gcc/cse.cc
> > index b4b39e3ebf8..ee4e8b86f1c 100644
> > --- a/gcc/cse.cc
> > +++ b/gcc/cse.cc
> > @@ -2494,6 +2494,10 @@ hash_rtx (const_rtx x, machine_mode mode,
> >    }
> >         break;
> >   +    case VEC_PREDICATE:
> > +      hash += (unsigned) VEC_PRED_CODE (x);
> > +      break;
> > +
> >       default:
> >         break;
> [ ... ]
> I wouldn't be surprised if there's more plumbing of this nature needed.   I
> guess perhaps the question to ask is are you looking for this kind of thing
> systematically or by throwing code into the compiler and seeing what trips?  I
> would think you'd want to include the relevant fields in the hash?   Of course
> if all this is handled via a recursive step, then it's a non-issue :-)
> 
> >       }
> > @@ -2623,6 +2627,11 @@ exp_equiv_p (const_rtx x, const_rtx y, int validate,
> > @@ bool for_gcse)
> >    return false;
> >         break;
> >   +    case VEC_PREDICATE:
> > +      if (VEC_PRED_CODE (x) != VEC_PRED_CODE (y))
> > +   return false;
> > +      break;
> Similar to the hashing question above, the only difference is this is
> correctness rather than just potentially having a poor hash.
> 
> >
> >
> > diff --git a/gcc/rtl.h b/gcc/rtl.h
> > index d60587dc5ce..4adbc2cb59e 100644
> > --- a/gcc/rtl.h
> > +++ b/gcc/rtl.h
> > @@ -438,6 +438,9 @@ struct GTY((desc("0"), tag("0"),
> >         /* For future expansion.  */
> >         unsigned int unused : 8;
> >       } const_vector;
> > +
> > +    /* The code of a VEC_PREDICATE.  */
> > +    unsigned int vec_pred_code;
> >     } GTY ((skip)) u2;
> It doesn't look like this is going to increase the size of an RTX as this is
> just another variant in a union.  Phew!
> 
> Overall it's nowhere near as complex as I expected.  Obviously I worry about
> missed paths, but at some level we're going to be the guinea pig here, so if
> we'll be the ones to stumble over this stuff and need to fix it.  I would
> probably not suggest other targets jump on the bandwagon until we've got
> confidence that it's working well for RISC-V.
> 
> I'd love to hear Richard S's thoughts on the gen* bits, but they generally
> looked sensible to me.
> 
> You mentioned that you've confirmed we can drop some of the vector patterns
> for RISC-V with your changes.  That's definitely a good sign.  If autovec.md
> turned into just moves, I'd jump for joy...
> 
> jeff
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to