Re: [PATCH v2 1/1] aarch64: Add SME2.1 structured sparsity outer product intrinsics

Claudio Bantaloukas <[email protected]>
Newsgroups gmane.comp.gcc.patches
Message-ID <[email protected]>

On 18/08/2026 12:19, Alex Coplan wrote:
> On 17/08/2026 19:12, Claudio Bantaloukas wrote:
>> Hellos!
  (snip)>>> You'll just need a mode attribute mapping ZA modes to the 
number of
>>> immediate bits needed to address them.  So the predicates become
>>> "aarch64_imm<za_imm_bits>" or so in the patterns.
>>>
>> I was thinking about following your initial suggestion but then opted for
>> aarch64_za<elem_bits>_imm for a few reasons.
>> One is because elem_bits is already there whereas za_imm_bits isn't.
> 
> Yes, but given you're going to have to add new preidcates if you don't
> add za_imm_bits, this seems a bit moot.
> 
>> One that I feel strongly about is that the za in the predicate shows intent.
> 
> I think "aarch64_imm<za_imm_bits>" shows the intent equally well.
> 
Absolutely!
	   (match_operand:DI 0 "aarch64_za<elem_bits>_imm")
vs
	   (match_operand:DI 0 "aarch64_imm<za_imm_bits>")
are equally readable and convey what arg 0 is very clearly.

But I find
	   (match_operand:DI 0 "aarch64_za32_imm")
	   (match_operand:<SVE_FULL_HF:VDOUBLE> 1 "aligned_register_operand" "Uw2")
	   (match_operand:SVE_FULL_HF 2 "register_operand" "w")
	   (match_operand:VNx16QI 3 "register_operand" "Uwo")
	   (match_operand:DI 4 "aarch64_imm2")

slightly better to
	   (match_operand:DI 0 "aarch64_imm2")
	   (match_operand:<SVE_FULL_HF:VDOUBLE> 1 "aligned_register_operand" "Uw2")
	   (match_operand:SVE_FULL_HF 2 "register_operand" "w")
	   (match_operand:VNx16QI 3 "register_operand" "Uwo")
	   (match_operand:DI 4 "aarch64_imm2")

Nevertheless, I'll go ahead with the change set out below unless told 
otherwise.

>> It makes it a little bit easier to see at a glance which opearand denotes
>> the tile.
>> And the one that I think we should discuss more widely is what to do with
>> aarch64_imm3. It's the wrong predicate to use for this case because it
>> limits the values to 4 or less whereas we would need something like
>> aarch64_lane_imm3 which correctly constrains us to 7 or less.
> 
> That's a good point, I hadn't realised that aarch64_imm3 doesn't actually
> follow the pattern here.  However, I don't think it presents an immediate
> problem for the purposes of this patch.
> 
> We have the following situation:
> 
> ZA element size | num ZA tiles | immediate bits
> ================+==============+====================
>                8 | 1            | 0
>               16 | 2            | 1
>               32 | 4            | 2
>               64 | 8            | 3
> 
> and none of the TMOP instructions have 64-bit ZA tile destintions (only
> 16- or 32-bit).
> 
> I agree, however, that using this approach presents a potential footgun
> for future SME patches (which might start using aarch64_imm3), so either
> as a pre-patch or follow-up patch, we should probably do the renaming
> you suggest below, making the aarch64_immN family of predicates
> self-consistent.
> 
> FWIW, I think aarch64_shift_imm3 is fine as a replacement name for the
> current aarch64_imm3.
> 
>>
>> If you feel strongly about adding za_imm_bits, would you consider it
>> complete if it was limited to all the modes in elem_bits belonging to 8(0),
>> 16(1), 32(2), 64(3), 128(4) bit za modes or would you rather I keep 0 out?
> 
> I don't think it would need to be implemented for all the modes in
> elem_bits.  In general, iterators and mode attributes only need
> implement what is actually practically needed.  In this case I think
> only { VNx8HI, VNx4SI, VNx2DI } and corresponding F modes are needed.
> If you wanted to be hyper-pragmatic, I think only VNx8HF and VNx4SF are
> needed by your patch as it stands, but we might as well implement the
> complete set that is likely to be used in practice.
> 
>>
>> Fields using aarch64_imm3 are described as "Is the left shift amount to be
>> applied after extension in the range 0 to 4". I guess we could call it
>> aarch64_shift_amount_imm3 and replace it in the extended register versions
>> of add, adds etc. Then we could rename aarch64_lane_imm3 to aarch64_imm3 but
>> if you look at places where aarch64_lane_imm3 is used, you'd spot the slight
>> loss in context this extended name brings.
>>
>> Let me know where you lean on this and I'll go that way.
> 
> As said above, I think we should use aarch64_imm<za_imm_bits>, and do
> this renaming (either as a pre-patch or follow-up patch), provided there
> are no objections from other reviewers/maintainers.
> 
> Thanks,
> Alex
> 
>>
>>>> +
>>>>    ;; An immediate that fits into 24 bits, but needs splitting.
>>>>    (define_predicate "aarch64_split_imm24"
>>>>      (match_code "const_int")
>>> <snip>
>>>> diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_bf16_bf16.c b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_bf16_bf16.c
>>>> new file mode 100644
>>>> index 00000000000..381ec046f45
>>>> --- /dev/null
>>>> +++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_bf16_bf16.c
>>>> @@ -0,0 +1,76 @@
>>>> +/* { dg-do assemble { target { aarch64_asm_sme-b16b16_ok && aarch64_asm_sme-tmop_ok}  } } */
>>>> +/* { dg-do compile { target { ! { aarch64_asm_sme-b16b16_ok && aarch64_asm_sme-tmop_ok } } } } */
>>>> +/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
>>>> +
>>>> +#include "test_sme2_acle.h"
>>>> +
>>>> +#pragma GCC target "+sme-tmop+sme-b16b16"
>>>> +
>>>> +/*
>>>> +** tmopa_lane_za16_bf16_bf16_0_z0_z4_z20_0:
>>>> +**	bftmopa	za0\.h, {z0\.h - z1\.h}, z4\.h, z20\[0\]
>>>> +**	ret
>>>> +*/
>>>> +TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z4_z20_0, svbfloat16x2_t, svbfloat16_t,
>>>> +		 svtmopa_lane_za16_bf16_bf16 (0, z0, z4, z20, 0),
>>>> +		 svtmopa_lane_za16 (0, z0, z4, z20, 0))
>>>> +
>>>> +/* ZA slice and offset with different values.
>>>> +** tmopa_lane_za16_bf16_bf16_1_z2_z4_z20_3:
>>>> +**	bftmopa	za1\.h, {z2\.h - z3\.h}, z4\.h, z20\[3\]
>>>> +**	ret
>>>> +*/
>>>> +TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_1_z2_z4_z20_3, svbfloat16x2_t, svbfloat16_t,
>>>> +		 svtmopa_lane_za16_bf16_bf16 (1, z2, z4, z20, 3),
>>>> +		 svtmopa_lane_za16 (1, z2, z4, z20, 3))
>>>> +
>>>> +/* The first register on the second argument must be even.
>>>> +** tmopa_lane_za16_bf16_bf16_0_z1_z4_z20_0:
>>>> +**	mov	(z\d+)\.d, z1\.d
>>>> +**	mov	(z\d+)\.d, z2\.d
>>>> +**	bftmopa	za0\.h, {\1\.h - \2\.h}, z4\.h, z20\[0\]
>>>> +**	ret
>>>> +*/
>>>> +TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z1_z4_z20_0, svbfloat16x2_t, svbfloat16_t,
>>>> +		 svtmopa_lane_za16_bf16_bf16 (0, z1, z4, z20, 0),
>>>> +		 svtmopa_lane_za16 (0, z1, z4, z20, 0))
>>>> +
>>>> +/* zk register must be one of Z20-Z23 or Z28-z31.
>>>> +** tmopa_lane_za16_bf16_bf16_0_z0_z4_z19_0:
>>>> +**	mov	(z2[0-3]|z2[89]|z3[01]).d, z19.d
>>>
>>> Very minor nit, but you could factor the z out of the alternation, such
>>> that you're only matching the register number (adding it back in again
>>> below when you have the backreference).  It would make the regex a bit
>>> tidier / more readable.  Same for the other occurrences.
>>>
>> ack, will fix :)
>>
>>
>>> OK with those changes, thanks.
>>>
>>> Alex
>>>
>>>> +**	bftmopa	za0\.h, {z0\.h - z1\.h}, z4\.h, \1\[0\]
>>>> +**	ret
>>>> +*/
>>>> +TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z4_z19_0, svbfloat16x2_t, svbfloat16_t,
>>>> +		 svtmopa_lane_za16_bf16_bf16 (0, z0, z4, z19, 0),
>>>> +		 svtmopa_lane_za16 (0, z0, z4, z19, 0))
>>>> +
>>>> +/* zk register must be one of Z20-Z23 or Z28-z31.
>>>> +** tmopa_lane_za16_bf16_bf16_0_z0_z4_z24_0:
>>>> +**	mov	(z2[0-3]|z2[89]|z3[01]).d, z24.d
>>>> +**	bftmopa	za0\.h, {z0\.h - z1\.h}, z4\.h, \1\[0\]
>>>> +**	ret
>>>> +*/
>>>> +TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z4_z24_0, svbfloat16x2_t, svbfloat16_t,
>>>> +		 svtmopa_lane_za16_bf16_bf16 (0, z0, z4, z24, 0),
>>>> +		 svtmopa_lane_za16 (0, z0, z4, z24, 0))
>>>> +
>>>> +/* zk register must be one of Z20-Z23 or Z28-z31.
>>>> +** tmopa_lane_za16_bf16_bf16_0_z0_z4_z27_0:
>>>> +**	mov	(z2[0-3]|z2[89]|z3[01]).d, z27.d
>>>> +**	bftmopa	za0\.h, {z0\.h - z1\.h}, z4\.h, \1\[0\]
>>>> +**	ret
>>>> +*/
>>>> +TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z4_z27_0, svbfloat16x2_t, svbfloat16_t,
>>>> +		 svtmopa_lane_za16_bf16_bf16 (0, z0, z4, z27, 0),
>>>> +		 svtmopa_lane_za16 (0, z0, z4, z27, 0))
>>>> +
>>>> +/* zk register must be one of Z20-Z23 or Z28-z31.
>>>> +** tmopa_lane_za16_bf16_bf16_0_z0_z4_z28_0:
>>>> +**	bftmopa	za0\.h, {z0\.h - z1\.h}, z4\.h, z28\[0\]
>>>> +**	ret
>>>> +*/
>>>> +TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z4_z28_0, svbfloat16x2_t, svbfloat16_t,
>>>> +		 svtmopa_lane_za16_bf16_bf16 (0, z0, z4, z28, 0),
>>>> +		 svtmopa_lane_za16 (0, z0, z4, z28, 0))
>>>> +
>>> <snip>
>>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.