Richard Biener <rguent...@suse.de> writes:
> On Thu, 20 Jun 2024, Richard Sandiford wrote:
>
>> Richard Biener <rguent...@suse.de> writes:
>> > On Mon, 17 Jun 2024, Richard Sandiford wrote:
>> >
>> >> Richard Biener <rguent...@suse.de> writes:
>> >> > On Fri, 14 Jun 2024, Richard Biener wrote:
>> >> >
>> >> >> On Fri, 14 Jun 2024, Richard Sandiford wrote:
>> >> >> 
>> >> >> > Richard Biener <rguent...@suse.de> writes:
>> >> >> > > On Fri, 14 Jun 2024, Richard Sandiford wrote:
>> >> >> > >
>> >> >> > >> Richard Biener <rguent...@suse.de> writes:
>> >> >> > >> > The following retires vcond{,u,eq} optabs by stopping to use 
>> >> >> > >> > them
>> >> >> > >> > from the middle-end.  Targets instead (should) implement 
>> >> >> > >> > vcond_mask
>> >> >> > >> > and vec_cmp{,u,eq} optabs.  The PR this change refers to lists
>> >> >> > >> > possibly affected targets - those implementing these patterns,
>> >> >> > >> > and in particular it lists mips, sparc and ia64 as targets that
>> >> >> > >> > most definitely will regress while others might simply remove
>> >> >> > >> > their vcond{,u,eq} patterns.
>> >> >> > >> >
>> >> >> > >> > I'd appreciate testing, I do not expect fallout for x86 or 
>> >> >> > >> > arm/aarch64.
>> >> >> > >> > I know riscv doesn't implement any of the legacy optabs.  But 
>> >> >> > >> > less
>> >> >> > >> > maintained vector targets might need adjustments.
>> >> >> > >> >
>> >> >> > >> > I want to get rid of those optabs for GCC 15.  If I don't hear 
>> >> >> > >> > from
>> >> >> > >> > you I will assume your target is fine.
>> >> >> > >> 
>> >> >> > >> Great!  Thanks for doing this.
>> >> >> > >> 
>> >> >> > >> Is there a plan for how we should handle vector comparisons that
>> >> >> > >> have to be done as the inverse of the negated condition?  Should
>> >> >> > >> targets simply not provide vec_cmp for such conditions and leave
>> >> >> > >> the target-independent code to deal with the fallout?  (For a
>> >> >> > >> standalone comparison, it would invert the result.  For a 
>> >> >> > >> VEC_COND_EXPR
>> >> >> > >> it would swap the true and false values.)
>> >> >> > >
>> >> >> > > I would expect that the ISEL pass which currently deals with 
>> >> >> > > finding
>> >> >> > > valid combos of .VCMP{,U,EQ} and .VCOND_MASK deals with this.
>> >> >> > > So how do we deal with this right now?  I expect RTL expansion will
>> >> >> > > do the inverse trick, no?
>> >> >> > 
>> >> >> > I think in practice (at least for the targets I've worked on),
>> >> >> > the target's vec_cmp handles the inversion itself.  Thus the
>> >> >> > main optimisation done by targets' vcond patterns is to avoid
>> >> >> > the inversion (and instead swap the true/false values) when the
>> >> >> > "opposite" comparison is the native one.
>> >> >> 
>> >> >> I see.  I suppose whether or not vec_cmp is handled is determined
>> >> >> by a FAIL so it's somewhat difficult to determine this at ISEL time.
>> >> 
>> >> In principle we could say that the predicates should accept only the
>> >> conditions that can be done natively.  Then target-independent code
>> >> can apply the usual approaches to generating other conditions
>> >> (which tend to be replicated across targets anyway).
>> >
>> > Ah yeah, I suppose that would work.  So we'd update the docs
>> > to say predicates are required to reject not handled compares
>> > and otherwise the expander may not FAIL?
>> >
>> > I'll note that expand_vec_cmp_expr_p already looks at the insn
>> > predicates, so adjusting vector lowering (and vectorization) to
>> > emit only recognized compares (and requiring folding to keep it at that)
>> > should be possible.
>> >
>> > ISEL would then mainly need to learn the trick of swapping vector
>> > cond arms on inverted masks.  OTOH folding should also do that.
>> 
>> Yeah.
>> 
>> > Or do you suggest to allow all compares on GIMPLE and only fixup
>> > during ISEL?  How do we handle vector lowering then?  Would it be
>> > enough to require "any" condition code and thus we expect targets
>> > to implement enough codes so all compares can be handled by
>> > swapping/inversion?
>> 
>> I'm not sure TBH.  I can see the argument that "canonicalising"
>> conditions for the target could be either vector lowering or ISEL.
>> 
>> If a target can only do == or != natively, for instance (is any target
>> like that?), then I think it should be ok for the predicates to accept
>> only that condition.  Then the opposite != or == could be done using
>> vector lowering/ISEL, but ordered comparisons would need to be lowered
>> as though vec_cmp wasn't implemented at all.
>> 
>> Something similar probably applies to FP comparisons if the handling
>> of unordered comparisons is limited.
>> 
>> And if we do that, it might be easier for vector lowering to handle
>> everything itself, rather than try to predict what ISEL is going to do.
>
> I agree that as we have to handle completely unsupported cases in
> vector lowering anyway it's reasonable to try to force only supported
> ops after that.
>
> Note that when targets stop to advertise not supported compares then
> the vectorizer likely needs adjustments as well.  We can of course
> put some common logic into the middle-end like making the
> expand_vec_cmp_expr_p function take additional optional arguments
> to indicate whether swapping operands or inverting the condition
> code makes the comparison supported.
>
> Do you know any target off head that restricts vec_cmp support via
> predicates?  I'm not exactly sure how do implement such predicate
> and having a patch for a target with some vector coverage would
> be nice for implementing this.  I'd start with the vector lowering
> bits obviously, I suspect there's quite some patterns in match.pd
> that need guarding in case there's no existing target doing such
> predication.

I'm not aware of a target that already does it, since I imagine the
pessimisation would be unacceptable.  But here's what it might look like
for AArch64 Advanced SIMD:

diff --git a/gcc/config/aarch64/aarch64-simd.md 
b/gcc/config/aarch64/aarch64-simd.md
index 01b084d8ccb..a3ce504cddd 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3844,9 +3844,12 @@ (define_expand "cbranch<mode>4"
 
 ;; Patterns comparing two vectors to produce a mask.
 
+(define_predicate "int_vec_cmp_operator"
+  (match_code "lt,ge,le,gt,ltu,geu,leu,gtu,eq"))
+
 (define_expand "vec_cmp<mode><mode>"
   [(set (match_operand:VSDQ_I_DI 0 "register_operand")
-         (match_operator 1 "comparison_operator"
+         (match_operator 1 "int_vec_cmp_operator"
            [(match_operand:VSDQ_I_DI 2 "register_operand")
             (match_operand:VSDQ_I_DI 3 "nonmemory_operand")]))]
   "TARGET_SIMD"
@@ -3924,9 +3927,12 @@ (define_expand "vec_cmp<mode><mode>"
   DONE;
 })
 
+(define_predicate "fp_vec_cmp_operator"
+  (match_code "lt,ge,le,gt,eq"))
+
 (define_expand "vec_cmp<mode><v_int_equiv>"
   [(set (match_operand:<V_INT_EQUIV> 0 "register_operand")
-       (match_operator 1 "comparison_operator"
+       (match_operator 1 "fp_vec_cmp_operator"
            [(match_operand:VDQF 2 "register_operand")
             (match_operand:VDQF 3 "nonmemory_operand")]))]
   "TARGET_SIMD"

The FP case is tricky to decide because we do implement UNORDERED,
but seem to do it in a way that could signal invalid for sNaNs.
For -fno-signaling-nans, the approach of doing two ==s and
combining them is target-independent.

Thanks,
Richard

Reply via email to