"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.
(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.)
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.
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).
Richard