Hi Tamar,

Glad to see this series :)

I'm still trying to wrap my head around the changes as well as the 
status before, and what we need for RVV in order to make proper use of 
it.

Also, I'm getting the impression that this is the first time we could 
use two separate else values (one for the tail, one for the inactive 
elements).  But let's not go there now, I don't want to make people 
detest RVV even more :)

One main point I'd still like to raise, though.  If that has been 
discussed already, feel free to ignore:

Right now both the mask as well as the len path mask the comparison 
(where the m & cmp comes from that you want to optimize) and not the 
following "reduction" (= COUNT_ACTIVE) that feeds the branch.  For RVV 
that's surely not the best solution and I'd rather have a plain vector 
comparison, implicitly length masked, as input for
LEN_COUNT_ACTIVE/LEN_MASK_INDEX_FIRST so that the m & cmp never even 
gets emitted.  For RVV that approach should always better, for SVE I'm 
not so sure.  I could imagine that the predicate handling for ncopies > 
1 gets more expensive with that suggestion.

Would masking COUNT_ACTIVE work for SVE, at least for the ncopies = 1 
case or am I missing something fundamental?  Or maybe it just doesn't 
scale beyond ncopies = 1?  But wouldn't some of the extra work we need 
to do (like the TER and duplicate use) in this series vanish if that 
were a viable approach?

One way or another, I was just curious and, of course, I'm not asking 
you to change the RVV code path.  I'll do that myself it there's still 
time during stage 1.

So to my understanding, right now with trapping math excluded, we don't 
need a masked vec_cmp for RVV because we could just compare without 
length, ignoring tail elements, then popcount the result and branch 
dependent on it.  With trapping math the cond_len variant is needed but 
won't be optimized anyway.

Apart from that, I have mostly bikeshedding to contribute, with the RVV 
usage in mind.

> +@cindex @code{IFN_COUNT_ACTIVE} internal function
> +@item @samp{IFN_COUNT_ACTIVE}
> +The @code{IFN_COUNT_ACTIVE} internal function directly maps to the
> +@code{count_active} instruction pattern.  It returns the number of active
> +elements in its argument.
> +
> +@cindex @code{IFN_COND_COUNT_ACTIVE} internal function
> +@item @samp{IFN_COND_COUNT_ACTIVE}
> +The @code{IFN_COND_COUNT_ACTIVE} internal function directly maps to the
> +@code{cond_count_active} instruction pattern.  It returns the number of
> +active elements in its second argument under the mask in its first
> +argument.
> +
> +@cindex @code{IFN_COND_LEN_COUNT_ACTIVE} internal function
> +@item @samp{IFN_COND_LEN_COUNT_ACTIVE}
> +The @code{IFN_COND_LEN_COUNT_ACTIVE} internal function directly maps to the
> +@code{cond_len_count_active} instruction pattern.  It is like
> +@code{IFN_COND_COUNT_ACTIVE}, but also ignores elements whose index is
> +greater than or equal to the sum of the length and bias arguments.
> +
> +@cindex @code{IFN_INDEX_FIRST_ACTIVE} internal function
> +@item @samp{IFN_INDEX_FIRST_ACTIVE}
> +The @code{IFN_INDEX_FIRST_ACTIVE} internal function directly maps to the
> +@code{index_first_active} instruction pattern.  It returns the index of the
> +first active element in its argument.  The result is undefined if the
> +predicate has no active elements.

Could we define the result as -1?  RVV's vfirst returns -1 if no bits 
are set and that would help to rely on it.


I know I mentioned naming before, sorry, but I got confused about 
"active" again.  The functions here refer to the set bits in a 
vector/mask as active while there can be fewer active lanes than set 
bits.  So arguably, we should rather call them INDEX_FIRST_SET etc. but 
I'm not going to ask you change everything unless there's consensus.

The one I mentioned before, EXTRACT_FIRST_ACTIVE is still ok I guess, 
because it actually extracts an active lane.  But the IFNs operating on 
predicates don't.  I just realized RVV's insns already follow the 
set-naming (like vmsbf vector mask set before first).  Believe it or 
not, that's not where I'm coming from :)

Usually we add len ifns (as well as mask ifns) to internal_fn_len_index 
and internal_fn_mask_index but as we can't re-use 
add_mask_else_and_len_args due to optab operand order, it won't help 
anyway.  And I really hope we can untangle all of this eventually when 
we have an RTL vector predicate.

> +
> +@cindex @code{IFN_COND_INDEX_FIRST_ACTIVE} internal function
> +@item @samp{IFN_COND_INDEX_FIRST_ACTIVE}
> +The @code{IFN_COND_INDEX_FIRST_ACTIVE} internal function directly maps to the
> +@code{cond_index_first_active} instruction pattern.  It returns the index of
> +the first active element in its second argument under the mask in its first
> +argument.  The result is undefined if the selected predicate has no active
> +elements.

Maybe a short note here that these IFNs take a predicate/mask type as 
input?

-- 
Regards
 Robin

Reply via email to