On Mon, Aug 10, 2026 at 7:48 PM Richard Sandiford
<[email protected]> wrote:
>
> "Robin Dapp" <[email protected]> writes:
> >>> > (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
> >
> > Yeah I don't particularly like it either, in particular that we need
> > to replicate canonicalization for these "unstructured" operands in
> > simplify-rtx.  It's not a big deal but feels redundant.
> >
> >>  (vec_predicate
> >>   (plus:<mode> (...) (...))
> >
> > This would still be my preferred way just by the way it reads and re-uses
> > existing code.  Richard's objection here was, though:
> >
> >> This again avoids contextual interpretation.  A predicated plus is not
> >> equivalent to taking an existing unpredicated plus and predicating it,
> >> and vice versa.
> >
> > I didn't realize cond_exec is similar and that we need to avoid the 
> > "hoisting"
> > situation already.  So maybe the above wouldn't be too bad?
>
> cond_exec is a top-level code though.  It wraps sets, rather than occurring
> within sets.  Contextual interpretation is a given there, since e.g.
> XEXP (..., 0) on a SET or a CLOBBER needs to be interpreted as an lvalue
> rather than an rvalue.
>
> That is, you can't interpret a top-level RTX code by evaluating its
> operands first and then applying the operator to them.  But you can do
> that for all existing rvalue codes that I'm aware of.
>
> So it depends on what kind of code we want.  Do we want a top-level code or
> an rvalue code?  A "vector predicate version of cond_exec" could indeed...
>
> > Introducing a vec_pred_set would avoid a vec_copy... RTX code.  I'm not
> > looking forward to adding combine/etc. handling for vec_predicate +
> > vec_pred_set combinations, though :)
>
> ...be like this, although perhaps keeping the set and the vec_predicate
> separate (the former within the latter).
>
> But the thing about cond_exec is that it's all or nothing.  The action
> that it wraps either happens or doesn't happen.  The natural way of
> extending that to predicates would be to say that the wrapped operation
> either happens for a lane or does not happen for a lane.  In other words,
> it would be lane-level cond_exec rather than the existing vector-level
> cond_exec.
>
> That would be a natural way of describing merge predication and
> predicated stores, where the destination is partially modified and
> partially preserved.  Doing that sounds good to me if it's what we want.
>
> But I thought we wanted more than that from the new RTL code.  I thought
> we wanted to use it to describe an operation that is performed on some
> lanes to produce a full vector result, with the values of other lanes
> being taken from elsewhere.  E.g. SVE patterns "need" at least merge
> with zero, merge with first operand, merge with second operand, and
> merge with third operand.
>
> If we took the cond_exec approach, we'd presumably require the wrapped
> set operation to have a certain form and use information in the
> vec_predicate wrapper to "imagine" what the corresponding operation
> for inactive lanes would be.

Maybe

(vec_cond_exec
  ((pred:X) (set ...)
  (set ...)))

with the 2nd (optional) set being executed for inactive lanes?  That
would basically be an "else" operation rather than an "else" value
that we have now in the IFNs.

> (In theory, we could avoid the "imagination" by having an explicit
> rtx that describes the operation for inactive lanes, but that would
> require duplicating the destination, which sounds worse.)

Does it?

> Even with that, the cond_exec approach still seems a bit inflexible.
> It wouldn't help if we wanted the predicated operation to be nested
> within another (unconditional) operation.  E.g. it's feasible that an
> instruction could perform zero predication followed by some form of
> permutation.  IIRC SVE LD1RQ would be like that.

True, so I guess that rules out a toplevel RTX as a generic enough vehicle,
but then at least zero predication can be handled fine already and combine
splitting that out wouldn't be harmful (if recognizable).

> Having vec_predicate be an rvalue that occurs within the set would
> avoid that inflexibility.  But vec_predicate would then be completely
> unlike cond_exec.  Both the vec_predicate rtx itself and its operands
> would be subject to combination, cse, forward progatation, etc.
>
> Allowing:
>
>   (vec_predicate
>     predicate
>     (plus op op1)
>     ...)
>
> would mean that vec_predicate could not be interpreted by evaluating its
> operands ("predicate" and "(plus op0 op1)"), then applying the vec_predicate
> operator to the result.  vec_predicate could only be interpreted by
> treating RTX_CODE and RTX_CODE (XEXP (x, 1)) as a compound operation
> whose operands are formed from XEXP (x, 0), XEXP (XEXP (x, 1), 0),
> XEXP (XEXP (x, 1), 1) and whatever is in "...".  AFAIK that would
> make it unique among rtxes that can occur as or within a SET_SRC.
>
> I realise that the form above would make the initial implementation easier.
> But I fear that's only because we'd have to abandon any realistic hope of
> identifying which pieces of code need to be taught about this new exception
> and instead wait for users and fuzzers to find them experimentally.
>
> That said, I realise that the alternatives aren't particularly appealing
> either, even if they seem semantically cleaner (to me).

I think at this point having a "cheat sheet" of how the various uses
(masked store, masked load, masked operation) look like with the
different proposed ways would be nice to have.  Possibly the wiki
can host a table of those?

Richard.

>
> Richard

Reply via email to