On 30/06/2026 11:52, Alex Coplan wrote:
Hi Claudio,

[+CC: Artemiy, who I believe is picking this up while Claudio is away].

Thanks for working on this, and sorry that it's taken so long for a
review.


It's taken me a while to wrap my head around what I had written back then too so it's only fair that it took a while to review! Thanks for doing this by the way. The best kind of review is one that makes me question my sanity when I was writing the code!
On 14/01/2026 18:20, Claudio Bantaloukas wrote:
This patch series adds support for the following intrinsics implementing
FEAT_SME_TMOP. All of these require the +sme-tmop arch option.
A new intrinsic shape and a new register constraint is required. This patch
adds these, along with tests.


---8<---

+;; -------------------------------------------------------------------------
+;; ---- [INT] Sparse outer product
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - STMOPA
+;; - UTMOPA
+;; - SUTMOPA
+;; - USTMOPA
+;; -------------------------------------------------------------------------
+;; svtmopa_lane_za32[_s16_s16]
+;; svtmopa_lane_za32[_u16_u16]
+;; svtmopa_lane_za32[_s8_s8]
+;; svtmopa_lane_za32[_u8_u8]
+;; svtmopa_lane_za32[_s8_u8]
+;; svtmopa_lane_za32[_u8_s8]

I don't think it's usual to list all the ACLE intrinsics that target a
given pattern here, so perhaps let's drop that?

It's a change that began with Karl when he made his first contribution.
I want to give him credit because when I first started working on SVE, I had a hard time figuring out where intrinsics were implemented and which patterns they corresponded to, but didn't do something about it whereas he came up with this simple approach. In due course I learned to make the connections between instructions and intrinsics but I think this is still useful, both for new joiners and for people, like me, who don't work on intrinsics all the time. I also like that this can help disambiguate patterns for intrinsics belonging to different versions of the same instruction.

I think adding more of these comments to other patterns rather than removing them will be of service.

+(define_insn "@aarch64_sme_lane_<optab><VNx4SI_ONLY:mode><SVE_FULL_BHI:mode>"

As written, this pattern includes variants of {SU,US}TMOPA with 16-bit
element source operands, which don't exist architecturally.  So you
either need a more complicated condition to prohibit those variants, or
(my preference) pull out {SU,US}TMOPA into a separate pattern.

This will be in the next version of the patch that I'll send shortly.

+  [(set (reg:VNx4SI_ONLY ZA_REGNUM)
+       (unspec:VNx4SI_ONLY
+         [(reg:VNx4SI_ONLY ZA_REGNUM)
+          (reg:DI SME_STATE_REGNUM)
+          (match_operand:DI 0 "const_int_operand")

I'll note that this is also true of the existing outer product patterns,
but it seems that nothing constrains the value of this operand which
selects the ZA tile number.

I suppose the argument is that the pattern is only reachable via
intrinsics, and the intrinsics properly constrain the tile index
according to the mode.  However, my understanding is that we've
historically taken the belt-and-braces approach of ensuring both the
intrinsics and patterns are properly constrained.

So how about using the "aarch64_imm2" predicate instead of
"const_int_operand" to appropriately constrain this operand?

Good call, in the next version of the patch, I add two new predicates, aarch64_za16_imm and aarch64_za32_imm to make the rationale for these clearer.

+          (match_operand:<SVE_FULL_BHI:VDOUBLE> 1 "aligned_register_operand" 
"Uw2")
+          (match_operand:SVE_FULL_BHI 2 "register_operand" "w")
+          (match_operand:VNx16QI 3 "register_operand" "Uwo")
+          (match_operand:DI 4 "const_int_operand")

As with the tile selection operand, I think this can use aarch64_imm2
instead of const_int_operand.

Ack, doing this on all new intrinsics.


+         ]
+         SME_TMOP_INT))]
+   "TARGET_STREAMING_SME_TMOP"
+   "<optab>\tza%0.s, %1, %2.<SVE_FULL_BHI:Vetype>, %3[%4]"
+)
+
  ;; -------------------------------------------------------------------------
  ;; ---- [FP] Dot product
  ;; -------------------------------------------------------------------------
@@ -2719,6 +2752,75 @@ (define_insn 
"@aarch64_sme_<optab><SME_ZA_F8F16_32:mode><VNx16QI_ONLY:mode>"
    "<optab>\tza%0.<SME_ZA_F8F16_32:Vetype>, %1/m, %2/m, %3.b, %4.b"
  )
+;; -------------------------------------------------------------------------
+;; ---- [FP] Sparse outer product
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - BFTMOPA (SME_TMOP)
+;; - FTMOPA (SME_TMOP)
+;; -------------------------------------------------------------------------
+;; svtmopa_lane_za16[_bf16_bf16]
+;; svtmopa_lane_za16[_f16_f16]

Likewise, can we drop the intrinsic names here?


See above.

+(define_insn "@aarch64_sme_lane_<optab><SVE_FULL_H:mode><SVE_FULL_HF:mode>"

This can't be right.  It allows the full cross product of
{ VNx8HI, VNx8BF, VNx8HF } x { VNx8BF, VNx8HF }, whereas I think we only want
these combinations:

output (ZA) mode | input mode | variant                      | feature
VNx8HF           | VNx8HF     | non-widening, half-precision | FEAT_SME_F16F16
VNx8BF           | VNx8BF     | non-widening                 | FEAT_SME_B16B16

Regarding the grouping of the FP patterns, it looks like we could follow
the same overall scheme as the base FMOP patterns.  Those are split as
follows:

1. "@aarch64_sme_<optab><mode><mode>": handles symmetric / non-widening cases
     with input mode = output mode, fp modes
2. "@aarch64_sme_<optab><VNx4SI_ONLY:mode><SVE_FULL_HF:mode>": widening from
     16-bit (HF and BF) to 32-bit elements
3. "@aarch64_sme_<optab><SME_ZA_F8F16_32:mode><VNx16QI_ONLY:mode>": widening
    from 8-bit (FP8) to 16- or 32-bit elements

Let's follow that precedent here?


Done.
+  [(set (reg:SVE_FULL_H ZA_REGNUM)
+       (unspec:SVE_FULL_H
+         [(reg:SVE_FULL_H ZA_REGNUM)
+          (reg:DI SME_STATE_REGNUM)
+          (match_operand:DI 0 "const_int_operand")

As for the integer patterns, can we use a tighter predicate here?
I suppose it will be slightly more complicated in the case of the symmetric
non-widening pattern, as that will have three different ZA modes, but you could
define a mode attribute, say <tile_imm>, and then give the predicate like so:

    "aarch64_imm<tile_imm>"

where tile_imm returns the correct number of bits for a tile number
immediate, given a ZA mode.

I've gone for "aarch64_za<elem_size>_imm", hope that's reasonably readable.



+          (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 "const_int_operand")

As for the integer pattern above, can we use aarch64_imm2 here instead of
const_int_operand?  Likewise for the other patterns.

Done.


+         ]
+         SME_TMOP_FP))]
+  "TARGET_STREAMING_SME_TMOP && (
+    <SVE_FULL_HF:MODE>mode == VNx8HFmode
+    ? TARGET_STREAMING_SME_F16F16
+    : TARGET_STREAMING_SME_B16B16)"

As a general principle, it's better to define custom conditional mode
iterators where the relevant modes are enabled by the corresponding
TARGET_* macro, rather than using the condition to enable/disable
certain combinations.

Similar comments apply to the other FP patterns below.


Done.

-----8<-------

diff --git a/gcc/config/aarch64/aarch64-sve-builtins-sme.cc 
b/gcc/config/aarch64/aarch64-sve-builtins-sme.cc
index 1b809492da4..d79ccdcf705 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins-sme.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins-sme.cc
@@ -461,6 +461,39 @@ public:
    }
  };
+class svtmopa_lane_za_impl: public read_write_za<function_base>
+{
+public:
+  int
+  unspec_for (const function_instance &instance) const
+  {
+    if (instance.fpm_mode == FPM_set)
+      return UNSPEC_SME_FTMOPA_FP8;
+    auto &suffix1 = instance.type_suffix (1);

I think the right type will be deduced as is, but stylistically I think
it might be better to declare this as:

   const auto &suffix1 = ...

just to show the intent locally that we don't plan on modifying these.
Same for suffix2 below.

Done.


+    if (!suffix1.integer_p)
+      return UNSPEC_SME_FTMOPA;
+    auto &suffix2 = instance.type_suffix (2);
+    if (suffix1.unsigned_p && suffix2.unsigned_p)
+      return UNSPEC_SME_UTMOPA;
+    else if (!suffix1.unsigned_p && !suffix2.unsigned_p)
+      return UNSPEC_SME_STMOPA;
+    else if (suffix1.unsigned_p && !suffix2.unsigned_p)
+      return UNSPEC_SME_USTMOPA;
+    else
+      return UNSPEC_SME_SUTMOPA;
+  }
+
+  rtx
+  expand (function_expander &e) const override
+  {
+    insn_code icode;
+    machine_mode za_mode = e.vector_mode (0);
+    machine_mode v_mode = e.tuple_mode (2);
+    icode = code_for_aarch64_sme_lane (unspec_for (e), za_mode, v_mode);

This looks wrong in that it uses the initial value of za_mode regardless of
whether the za and operand element widths are equal.  Thus za is always
referenced in an integer vector mode.

I think we want to follow the convention used by e.g. svmopa, whereby:
1. If the source vectors have the same operand width as the ZA access, then we
    use the source operand mode for ZA (which may be an fp mode).
2. Otherwise (e.g. for a widening insn), we use the appropriate I mode for ZA.

See aarch64-sve-builtins-functions.h:sme_2mode_function_t::expand.


Ack, this makes sense based on the form of the insns above. I tried extending sme_2mode_function_t but that would have required making unspec_for virtual or introducing further complexity to the unspec_based_function class so I ended up copying over its behaviour.

------8<---------

diff --git a/gcc/config/aarch64/constraints.md 
b/gcc/config/aarch64/constraints.md
index 3d166fe3a17..7e0f7670c24 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -64,6 +64,10 @@ (define_register_constraint "Uwt" "FP_REGS"
    "@internal The first register in a tuple of 4 strided FPRs."
    "(regno & 0xc) == 0")
+(define_register_constraint "Uwo" "FP_REGS"

It would be good to check with LLVM folks if they plan on exposing a constraint
for this, and if so, we should make sure to agree on the same name.


Checked, neither of us plan on exposing this.

+  "@internal Control Vector Register (One of Z20-Z23 or Z28-Z31)."
+  "(regno & 0x14) == 0x14")
+
  (define_register_constraint "Upa" "PR_REGS"
    "SVE predicate registers p0 - p15.")
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index b425b0ed2ca..cf327056449 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -527,6 +527,9 @@ (define_mode_iterator SVE_FULL_BHSI [VNx16QI VNx8HI VNx4SI])
  ;; Pairs of the above.
  (define_mode_iterator SVE_FULL_BHSIx2 [VNx32QI VNx16HI VNx8SI])
+;; Fully-packed SVE vector modes that have 16-bit elements.
+(define_mode_iterator SVE_FULL_H [VNx8HI VNx8BF VNx8HF])
+

I think this will no longer be needed with the changes to the patterns.


Removed.

-----8<--------

diff --git a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/test_sme2_acle.h 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/test_sme2_acle.h
index ff237983ad9..55b217ae0fe 100644
--- a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/test_sme2_acle.h
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/test_sme2_acle.h
@@ -121,4 +121,26 @@
      INVOKE (CODE1, CODE2);                                    \
    }
+#define TEST_ZA_TMOP(NAME, TYPE1, TYPE2, CODE1, CODE2) \
+  PROTO (NAME, void, (fpm_t fpm0))                             \
+  {                                                            \
+    register TYPE1 z0 __asm ("z0");                          \
+    register TYPE1 z1 __asm ("z1");                          \
+    register TYPE1 z2 __asm ("z2");                          \
+    register TYPE2 z3 __asm ("z3");                          \

Given that TYPE1 is typically a tuple of two vectors, I'm not sure if it
makes sense for z3 to be of TYPE2, since it will overlap with the second
half of the tuple for z2.

Good catch. I believe it's legal but likely not very useful to have overlapping registers like that. Will rename to z4.


+    register TYPE1 z16 __asm ("z16");                                \
+    register TYPE2 z17 __asm ("z17");                                \

Same here, is the overlap intentional?


Nope, actually some of these registers are never used. I'll just remove them from the define.

+    register svuint8_t z19 __asm ("z19");                    \
+    register svuint8_t z20 __asm ("z20");                    \
+    register svuint8_t z23 __asm ("z23");                    \
+    register svuint8_t z24 __asm ("z24");                    \
+    register svuint8_t z27 __asm ("z27");                    \
+    register svuint8_t z28 __asm ("z28");                    \
+    __asm volatile ("" : "=w" (z0), "=w" (z1), "=w" (z2),      \
+                   "=w" (z3), "=w" (z16), "=w" (z17),            \
+                   "=w" (z19), "=w" (z20), "=w" (z23),           \
+                   "=w" (z24), "=w" (z27), "=w" (z28));  \
+    INVOKE (CODE1, CODE2);                                     \
+  }
+
  #endif
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..84a9b64c41a
--- /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_z3_z20_0:
+**     bftmopa za0\.h, {z0\.h - z1\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z3_z20_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za16_bf16_bf16 (0, z0, z3, z20, 0),
+                svtmopa_lane_za16 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with different values.
+** tmopa_lane_za16_bf16_bf16_1_z2_z3_z20_3:
+**     bftmopa za1\.h, {z2\.h - z3\.h}, z3\.h, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_1_z2_z3_z20_3, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za16_bf16_bf16 (1, z2, z3, z20, 3),
+                svtmopa_lane_za16 (1, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za16_bf16_bf16_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     bftmopa za0\.h, {\1\.h - \2\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z1_z3_z20_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za16_bf16_bf16 (0, z1, z3, z20, 0),
+                svtmopa_lane_za16 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_bf16_bf16_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d

It might be nice to actually match for those ranges with a regex.
Same with the other occurrences.


Done

Otherwise this LGTM, but please send another version with the fixes.
Will do shortly.

Thanks for reviewing all this! :)
Thanks,
Alex

+**     bftmopa za0\.h, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z3_z19_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za16_bf16_bf16 (0, z0, z3, z19, 0),
+                svtmopa_lane_za16 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_bf16_bf16_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     bftmopa za0\.h, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z3_z24_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za16_bf16_bf16 (0, z0, z3, z24, 0),
+                svtmopa_lane_za16 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_bf16_bf16_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     bftmopa za0\.h, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z3_z27_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za16_bf16_bf16 (0, z0, z3, z27, 0),
+                svtmopa_lane_za16 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_bf16_bf16_0_z0_z3_z28_0:
+**     bftmopa za0\.h, {z0\.h - z1\.h}, z3\.h, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_bf16_bf16_0_z0_z3_z28_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za16_bf16_bf16 (0, z0, z3, z28, 0),
+                svtmopa_lane_za16 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_f16_f16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_f16_f16.c
new file mode 100644
index 00000000000..7b0aeefe45e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_f16_f16.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target { aarch64_asm_sme-f16f16_ok && 
aarch64_asm_sme-tmop_ok}  } } */
+/* { dg-do compile { target { ! { aarch64_asm_sme-f16f16_ok && 
aarch64_asm_sme-tmop_ok } } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop+sme-f16f16"
+
+/*
+** tmopa_lane_za16_f16_f16_0_z0_z3_z20_0:
+**     ftmopa  za0\.h, {z0\.h - z1\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_f16_f16_0_z0_z3_z20_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za16_f16_f16 (0, z0, z3, z20, 0),
+                svtmopa_lane_za16 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with different values.
+** tmopa_lane_za16_f16_f16_1_z2_z3_z20_3:
+**     ftmopa  za1\.h, {z2\.h - z3\.h}, z3\.h, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_f16_f16_1_z2_z3_z20_3, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za16_f16_f16 (1, z2, z3, z20, 3),
+                svtmopa_lane_za16 (1, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za16_f16_f16_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     ftmopa  za0\.h, {\1\.h - \2\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_f16_f16_0_z1_z3_z20_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za16_f16_f16 (0, z1, z3, z20, 0),
+                svtmopa_lane_za16 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_f16_f16_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     ftmopa  za0\.h, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_f16_f16_0_z0_z3_z19_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za16_f16_f16 (0, z0, z3, z19, 0),
+                svtmopa_lane_za16 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_f16_f16_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     ftmopa  za0\.h, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_f16_f16_0_z0_z3_z24_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za16_f16_f16 (0, z0, z3, z24, 0),
+                svtmopa_lane_za16 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_f16_f16_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     ftmopa  za0\.h, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_f16_f16_0_z0_z3_z27_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za16_f16_f16 (0, z0, z3, z27, 0),
+                svtmopa_lane_za16 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_f16_f16_0_z0_z3_z28_0:
+**     ftmopa  za0\.h, {z0\.h - z1\.h}, z3\.h, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_f16_f16_0_z0_z3_z28_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za16_f16_f16 (0, z0, z3, z28, 0),
+                svtmopa_lane_za16 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_mf8_mf8.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_mf8_mf8.c
new file mode 100644
index 00000000000..b5381ce37b9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za16_mf8_mf8.c
@@ -0,0 +1,83 @@
+/* { dg-do assemble { target { aarch64_asm_sme-f16f16_ok && 
aarch64_asm_sme-tmop_ok}  } } */
+/* { dg-do compile { target { ! { aarch64_asm_sme-f16f16_ok && 
aarch64_asm_sme-tmop_ok } } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop+sme-f8f16"
+
+/*
+** tmopa_lane_za16_mf8_mf8_0_z0_z3_z20_0:
+**     msr     fpmr, x0
+**     ftmopa  za0\.h, {z0\.b - z1\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_mf8_mf8_0_z0_z3_z20_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za16_mf8_mf8_fpm (0, z0, z3, z20, 0, fpm0),
+                svtmopa_lane_za16_fpm (0, z0, z3, z20, 0, fpm0))
+
+/* ZA slice and offset with different values.
+** tmopa_lane_za16_mf8_mf8_1_z2_z3_z20_3:
+**     msr     fpmr, x0
+**     ftmopa  za1\.h, {z2\.b - z3\.b}, z3\.b, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_mf8_mf8_1_z2_z3_z20_3, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za16_mf8_mf8_fpm (1, z2, z3, z20, 3, fpm0),
+                svtmopa_lane_za16_fpm (1, z2, z3, z20, 3, fpm0))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za16_mf8_mf8_0_z1_z3_z20_0:
+**     msr     fpmr, x0
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     ftmopa  za0\.h, {\1\.b - \2\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_mf8_mf8_0_z1_z3_z20_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za16_mf8_mf8_fpm (0, z1, z3, z20, 0, fpm0),
+                svtmopa_lane_za16_fpm (0, z1, z3, z20, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_mf8_mf8_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     msr     fpmr, x0
+**     ftmopa  za0\.h, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_mf8_mf8_0_z0_z3_z19_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za16_mf8_mf8_fpm (0, z0, z3, z19, 0, fpm0),
+                svtmopa_lane_za16_fpm (0, z0, z3, z19, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_mf8_mf8_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     msr     fpmr, x0
+**     ftmopa  za0\.h, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_mf8_mf8_0_z0_z3_z24_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za16_mf8_mf8_fpm (0, z0, z3, z24, 0, fpm0),
+                svtmopa_lane_za16_fpm (0, z0, z3, z24, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_mf8_mf8_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     msr     fpmr, x0
+**     ftmopa  za0\.h, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_mf8_mf8_0_z0_z3_z27_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za16_mf8_mf8_fpm (0, z0, z3, z27, 0, fpm0),
+                svtmopa_lane_za16_fpm (0, z0, z3, z27, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za16_mf8_mf8_0_z0_z3_z28_0:
+**     msr     fpmr, x0
+**     ftmopa  za0\.h, {z0\.b - z1\.b}, z3\.b, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za16_mf8_mf8_0_z0_z3_z28_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za16_mf8_mf8_fpm (0, z0, z3, z28, 0, fpm0),
+                svtmopa_lane_za16_fpm (0, z0, z3, z28, 0, fpm0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_bf16_bf16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_bf16_bf16.c
new file mode 100644
index 00000000000..854961df988
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_bf16_bf16.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_bf16_bf16_0_z0_z3_z20_0:
+**     bftmopa za0\.s, {z0\.h - z1\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_bf16_bf16_0_z0_z3_z20_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za32_bf16_bf16 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_bf16_bf16_3_z2_z3_z20_3:
+**     bftmopa za3\.s, {z2\.h - z3\.h}, z3\.h, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_bf16_bf16_3_z2_z3_z20_3, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za32_bf16_bf16 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_bf16_bf16_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     bftmopa za0\.s, {\1\.h - \2\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_bf16_bf16_0_z1_z3_z20_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za32_bf16_bf16 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_bf16_bf16_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     bftmopa za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_bf16_bf16_0_z0_z3_z19_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za32_bf16_bf16 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_bf16_bf16_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     bftmopa za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_bf16_bf16_0_z0_z3_z24_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za32_bf16_bf16 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_bf16_bf16_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     bftmopa za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_bf16_bf16_0_z0_z3_z27_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za32_bf16_bf16 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_bf16_bf16_0_z0_z3_z28_0:
+**     bftmopa za0\.s, {z0\.h - z1\.h}, z3\.h, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_bf16_bf16_0_z0_z3_z28_0, svbfloat16x2_t, 
svbfloat16_t,
+                svtmopa_lane_za32_bf16_bf16 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_f16_f16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_f16_f16.c
new file mode 100644
index 00000000000..dad5daac214
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_f16_f16.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_f16_f16_0_z0_z3_z20_0:
+**     ftmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f16_f16_0_z0_z3_z20_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za32_f16_f16 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_f16_f16_3_z2_z3_z20_3:
+**     ftmopa  za3\.s, {z2\.h - z3\.h}, z3\.h, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f16_f16_3_z2_z3_z20_3, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za32_f16_f16 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_f16_f16_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     ftmopa  za0\.s, {\1\.h - \2\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f16_f16_0_z1_z3_z20_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za32_f16_f16 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f16_f16_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     ftmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f16_f16_0_z0_z3_z19_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za32_f16_f16 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f16_f16_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     ftmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f16_f16_0_z0_z3_z24_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za32_f16_f16 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f16_f16_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     ftmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f16_f16_0_z0_z3_z27_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za32_f16_f16 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f16_f16_0_z0_z3_z28_0:
+**     ftmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f16_f16_0_z0_z3_z28_0, svfloat16x2_t, 
svfloat16_t,
+                svtmopa_lane_za32_f16_f16 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_f32_f32.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_f32_f32.c
new file mode 100644
index 00000000000..c61d2f08ed5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_f32_f32.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_f32_f32_0_z0_z3_z20_0:
+**     ftmopa  za0\.s, {z0\.s - z1\.s}, z3\.s, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f32_f32_0_z0_z3_z20_0, svfloat32x2_t, 
svfloat32_t,
+                svtmopa_lane_za32_f32_f32 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_f32_f32_3_z2_z3_z20_3:
+**     ftmopa  za3\.s, {z2\.s - z3\.s}, z3\.s, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f32_f32_3_z2_z3_z20_3, svfloat32x2_t, 
svfloat32_t,
+                svtmopa_lane_za32_f32_f32 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_f32_f32_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     ftmopa  za0\.s, {\1\.s - \2\.s}, z3\.s, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f32_f32_0_z1_z3_z20_0, svfloat32x2_t, 
svfloat32_t,
+                svtmopa_lane_za32_f32_f32 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f32_f32_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     ftmopa  za0\.s, {z0\.s - z1\.s}, z3\.s, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f32_f32_0_z0_z3_z19_0, svfloat32x2_t, 
svfloat32_t,
+                svtmopa_lane_za32_f32_f32 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f32_f32_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     ftmopa  za0\.s, {z0\.s - z1\.s}, z3\.s, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f32_f32_0_z0_z3_z24_0, svfloat32x2_t, 
svfloat32_t,
+                svtmopa_lane_za32_f32_f32 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f32_f32_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     ftmopa  za0\.s, {z0\.s - z1\.s}, z3\.s, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f32_f32_0_z0_z3_z27_0, svfloat32x2_t, 
svfloat32_t,
+                svtmopa_lane_za32_f32_f32 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_f32_f32_0_z0_z3_z28_0:
+**     ftmopa  za0\.s, {z0\.s - z1\.s}, z3\.s, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_f32_f32_0_z0_z3_z28_0, svfloat32x2_t, 
svfloat32_t,
+                svtmopa_lane_za32_f32_f32 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_mf8_mf8.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_mf8_mf8.c
new file mode 100644
index 00000000000..5eca7c6c477
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_mf8_mf8.c
@@ -0,0 +1,83 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop+sme-f8f32"
+
+/*
+** tmopa_lane_za32_mf8_mf8_0_z0_z3_z20_0:
+**     msr     fpmr, x0
+**     ftmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_mf8_mf8_0_z0_z3_z20_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za32_mf8_mf8_fpm (0, z0, z3, z20, 0, fpm0),
+                svtmopa_lane_za32_fpm (0, z0, z3, z20, 0, fpm0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_mf8_mf8_3_z2_z3_z20_3:
+**     msr     fpmr, x0
+**     ftmopa  za3\.s, {z2\.b - z3\.b}, z3\.b, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_mf8_mf8_3_z2_z3_z20_3, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za32_mf8_mf8_fpm (3, z2, z3, z20, 3, fpm0),
+                svtmopa_lane_za32_fpm (3, z2, z3, z20, 3, fpm0))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_mf8_mf8_0_z1_z3_z20_0:
+**     msr     fpmr, x0
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     ftmopa  za0\.s, {\1\.b - \2\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_mf8_mf8_0_z1_z3_z20_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za32_mf8_mf8_fpm (0, z1, z3, z20, 0, fpm0),
+                svtmopa_lane_za32_fpm (0, z1, z3, z20, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_mf8_mf8_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     msr     fpmr, x0
+**     ftmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_mf8_mf8_0_z0_z3_z19_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za32_mf8_mf8_fpm (0, z0, z3, z19, 0, fpm0),
+                svtmopa_lane_za32_fpm (0, z0, z3, z19, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_mf8_mf8_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     msr     fpmr, x0
+**     ftmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_mf8_mf8_0_z0_z3_z24_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za32_mf8_mf8_fpm (0, z0, z3, z24, 0, fpm0),
+                svtmopa_lane_za32_fpm (0, z0, z3, z24, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_mf8_mf8_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     msr     fpmr, x0
+**     ftmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_mf8_mf8_0_z0_z3_z27_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za32_mf8_mf8_fpm (0, z0, z3, z27, 0, fpm0),
+                svtmopa_lane_za32_fpm (0, z0, z3, z27, 0, fpm0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_mf8_mf8_0_z0_z3_z28_0:
+**     msr     fpmr, x0
+**     ftmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_mf8_mf8_0_z0_z3_z28_0, svmfloat8x2_t, 
svmfloat8_t,
+                svtmopa_lane_za32_mf8_mf8_fpm (0, z0, z3, z28, 0, fpm0),
+                svtmopa_lane_za32_fpm (0, z0, z3, z28, 0, fpm0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s16_s16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s16_s16.c
new file mode 100644
index 00000000000..c8533a76d46
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s16_s16.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_s16_s16_0_z0_z3_z20_0:
+**     stmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s16_s16_0_z0_z3_z20_0, svint16x2_t, svint16_t,
+                svtmopa_lane_za32_s16_s16 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_s16_s16_3_z2_z3_z20_3:
+**     stmopa  za3\.s, {z2\.h - z3\.h}, z3\.h, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s16_s16_3_z2_z3_z20_3, svint16x2_t, svint16_t,
+                svtmopa_lane_za32_s16_s16 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_s16_s16_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     stmopa  za0\.s, {\1\.h - \2\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s16_s16_0_z1_z3_z20_0, svint16x2_t, svint16_t,
+                svtmopa_lane_za32_s16_s16 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s16_s16_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     stmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s16_s16_0_z0_z3_z19_0, svint16x2_t, svint16_t,
+                svtmopa_lane_za32_s16_s16 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s16_s16_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     stmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s16_s16_0_z0_z3_z24_0, svint16x2_t, svint16_t,
+                svtmopa_lane_za32_s16_s16 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s16_s16_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     stmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s16_s16_0_z0_z3_z27_0, svint16x2_t, svint16_t,
+                svtmopa_lane_za32_s16_s16 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s16_s16_0_z0_z3_z28_0:
+**     stmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s16_s16_0_z0_z3_z28_0, svint16x2_t, svint16_t,
+                svtmopa_lane_za32_s16_s16 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s8_s8.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s8_s8.c
new file mode 100644
index 00000000000..65a4e976797
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s8_s8.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_s8_s8_0_z0_z3_z20_0:
+**     stmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_s8_0_z0_z3_z20_0, svint8x2_t, svint8_t,
+                svtmopa_lane_za32_s8_s8 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_s8_s8_3_z2_z3_z20_3:
+**     stmopa  za3\.s, {z2\.b - z3\.b}, z3\.b, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_s8_3_z2_z3_z20_3, svint8x2_t, svint8_t,
+                svtmopa_lane_za32_s8_s8 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_s8_s8_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     stmopa  za0\.s, {\1\.b - \2\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_s8_0_z1_z3_z20_0, svint8x2_t, svint8_t,
+                svtmopa_lane_za32_s8_s8 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_s8_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     stmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_s8_0_z0_z3_z19_0, svint8x2_t, svint8_t,
+                svtmopa_lane_za32_s8_s8 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_s8_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     stmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_s8_0_z0_z3_z24_0, svint8x2_t, svint8_t,
+                svtmopa_lane_za32_s8_s8 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_s8_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     stmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_s8_0_z0_z3_z27_0, svint8x2_t, svint8_t,
+                svtmopa_lane_za32_s8_s8 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_s8_0_z0_z3_z28_0:
+**     stmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_s8_0_z0_z3_z28_0, svint8x2_t, svint8_t,
+                svtmopa_lane_za32_s8_s8 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s8_u8.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s8_u8.c
new file mode 100644
index 00000000000..8bf14909516
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_s8_u8.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_s8_u8_0_z0_z3_z20_0:
+**     sutmopa za0\.s, {z0\.b - z1\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_u8_0_z0_z3_z20_0, svint8x2_t, svuint8_t,
+                svtmopa_lane_za32_s8_u8 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_s8_u8_3_z2_z3_z20_3:
+**     sutmopa za3\.s, {z2\.b - z3\.b}, z3\.b, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_u8_3_z2_z3_z20_3, svint8x2_t, svuint8_t,
+                svtmopa_lane_za32_s8_u8 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_s8_u8_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     sutmopa za0\.s, {\1\.b - \2\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_u8_0_z1_z3_z20_0, svint8x2_t, svuint8_t,
+                svtmopa_lane_za32_s8_u8 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_u8_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     sutmopa za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_u8_0_z0_z3_z19_0, svint8x2_t, svuint8_t,
+                svtmopa_lane_za32_s8_u8 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_u8_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     sutmopa za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_u8_0_z0_z3_z24_0, svint8x2_t, svuint8_t,
+                svtmopa_lane_za32_s8_u8 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_u8_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     sutmopa za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_u8_0_z0_z3_z27_0, svint8x2_t, svuint8_t,
+                svtmopa_lane_za32_s8_u8 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_s8_u8_0_z0_z3_z28_0:
+**     sutmopa za0\.s, {z0\.b - z1\.b}, z3\.b, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_s8_u8_0_z0_z3_z28_0, svint8x2_t, svuint8_t,
+                svtmopa_lane_za32_s8_u8 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u16_u16.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u16_u16.c
new file mode 100644
index 00000000000..a871cbc1aef
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u16_u16.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_u16_u16_0_z0_z3_z20_0:
+**     utmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u16_u16_0_z0_z3_z20_0, svuint16x2_t, svuint16_t,
+                svtmopa_lane_za32_u16_u16 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_u16_u16_3_z2_z3_z20_3:
+**     utmopa  za3\.s, {z2\.h - z3\.h}, z3\.h, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u16_u16_3_z2_z3_z20_3, svuint16x2_t, svuint16_t,
+                svtmopa_lane_za32_u16_u16 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_u16_u16_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     utmopa  za0\.s, {\1\.h - \2\.h}, z3\.h, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u16_u16_0_z1_z3_z20_0, svuint16x2_t, svuint16_t,
+                svtmopa_lane_za32_u16_u16 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u16_u16_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     utmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u16_u16_0_z0_z3_z19_0, svuint16x2_t, svuint16_t,
+                svtmopa_lane_za32_u16_u16 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u16_u16_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     utmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u16_u16_0_z0_z3_z24_0, svuint16x2_t, svuint16_t,
+                svtmopa_lane_za32_u16_u16 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u16_u16_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     utmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u16_u16_0_z0_z3_z27_0, svuint16x2_t, svuint16_t,
+                svtmopa_lane_za32_u16_u16 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u16_u16_0_z0_z3_z28_0:
+**     utmopa  za0\.s, {z0\.h - z1\.h}, z3\.h, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u16_u16_0_z0_z3_z28_0, svuint16x2_t, svuint16_t,
+                svtmopa_lane_za32_u16_u16 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u8_s8.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u8_s8.c
new file mode 100644
index 00000000000..3d06044989a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u8_s8.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_u8_s8_0_z0_z3_z20_0:
+**     ustmopa za0\.s, {z0\.b - z1\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_s8_0_z0_z3_z20_0, svuint8x2_t, svint8_t,
+                svtmopa_lane_za32_u8_s8 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_u8_s8_3_z2_z3_z20_3:
+**     ustmopa za3\.s, {z2\.b - z3\.b}, z3\.b, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_s8_3_z2_z3_z20_3, svuint8x2_t, svint8_t,
+                svtmopa_lane_za32_u8_s8 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_u8_s8_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     ustmopa za0\.s, {\1\.b - \2\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_s8_0_z1_z3_z20_0, svuint8x2_t, svint8_t,
+                svtmopa_lane_za32_u8_s8 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_s8_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     ustmopa za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_s8_0_z0_z3_z19_0, svuint8x2_t, svint8_t,
+                svtmopa_lane_za32_u8_s8 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_s8_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     ustmopa za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_s8_0_z0_z3_z24_0, svuint8x2_t, svint8_t,
+                svtmopa_lane_za32_u8_s8 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_s8_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     ustmopa za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_s8_0_z0_z3_z27_0, svuint8x2_t, svint8_t,
+                svtmopa_lane_za32_u8_s8 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_s8_0_z0_z3_z28_0:
+**     ustmopa za0\.s, {z0\.b - z1\.b}, z3\.b, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_s8_0_z0_z3_z28_0, svuint8x2_t, svint8_t,
+                svtmopa_lane_za32_u8_s8 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u8_u8.c 
b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u8_u8.c
new file mode 100644
index 00000000000..bd2519e0ea0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sme2/acle-asm/tmopa_lane_za32_u8_u8.c
@@ -0,0 +1,76 @@
+/* { dg-do assemble { target aarch64_asm_sme-tmop_ok } } */
+/* { dg-do compile { target { ! aarch64_asm_sme-tmop_ok } } } */
+/* { dg-final { check-function-bodies "**" "" "-DCHECK_ASM" } } */
+
+#include "test_sme2_acle.h"
+
+#pragma GCC target "+sme-tmop"
+
+/*
+** tmopa_lane_za32_u8_u8_0_z0_z3_z20_0:
+**     utmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_u8_0_z0_z3_z20_0, svuint8x2_t, svuint8_t,
+                svtmopa_lane_za32_u8_u8 (0, z0, z3, z20, 0),
+                svtmopa_lane_za32 (0, z0, z3, z20, 0))
+
+/* ZA slice and offset with maximum values.
+** tmopa_lane_za32_u8_u8_3_z2_z3_z20_3:
+**     utmopa  za3\.s, {z2\.b - z3\.b}, z3\.b, z20\[3\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_u8_3_z2_z3_z20_3, svuint8x2_t, svuint8_t,
+                svtmopa_lane_za32_u8_u8 (3, z2, z3, z20, 3),
+                svtmopa_lane_za32 (3, z2, z3, z20, 3))
+
+/* The first register on the second argument must be even.
+** tmopa_lane_za32_u8_u8_0_z1_z3_z20_0:
+**     mov     (z\d+)\.d, z1\.d
+**     mov     (z\d+)\.d, z2\.d
+**     utmopa  za0\.s, {\1\.b - \2\.b}, z3\.b, z20\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_u8_0_z1_z3_z20_0, svuint8x2_t, svuint8_t,
+                svtmopa_lane_za32_u8_u8 (0, z1, z3, z20, 0),
+                svtmopa_lane_za32 (0, z1, z3, z20, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_u8_0_z0_z3_z19_0:
+**     mov     (z\d+).d, z19.d
+**     utmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_u8_0_z0_z3_z19_0, svuint8x2_t, svuint8_t,
+                svtmopa_lane_za32_u8_u8 (0, z0, z3, z19, 0),
+                svtmopa_lane_za32 (0, z0, z3, z19, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_u8_0_z0_z3_z24_0:
+**     mov     (z\d+).d, z24.d
+**     utmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_u8_0_z0_z3_z24_0, svuint8x2_t, svuint8_t,
+                svtmopa_lane_za32_u8_u8 (0, z0, z3, z24, 0),
+                svtmopa_lane_za32 (0, z0, z3, z24, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_u8_0_z0_z3_z27_0:
+**     mov     (z\d+).d, z27.d
+**     utmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, \1\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_u8_0_z0_z3_z27_0, svuint8x2_t, svuint8_t,
+                svtmopa_lane_za32_u8_u8 (0, z0, z3, z27, 0),
+                svtmopa_lane_za32 (0, z0, z3, z27, 0))
+
+/* zk register must be one of Z20-Z23 or Z28-Z31.
+** tmopa_lane_za32_u8_u8_0_z0_z3_z28_0:
+**     utmopa  za0\.s, {z0\.b - z1\.b}, z3\.b, z28\[0\]
+**     ret
+*/
+TEST_ZA_TMOP (tmopa_lane_za32_u8_u8_0_z0_z3_z28_0, svuint8x2_t, svuint8_t,
+                svtmopa_lane_za32_u8_u8 (0, z0, z3, z28, 0),
+                svtmopa_lane_za32 (0, z0, z3, z28, 0))
+
diff --git 
a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_za_uint_dual_single_1.c
 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_za_uint_dual_single_1.c
new file mode 100644
index 00000000000..f1b170bb70a
--- /dev/null
+++ 
b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_za_uint_dual_single_1.c
@@ -0,0 +1,87 @@
+/* { dg-do compile } */
+
+#include <arm_sme.h>
+
+#pragma GCC target ("arch=armv9-a+sme-tmop")
+
+void
+f1 (uint64_t u64,
+    svfloat32x2_t f32x2, svfloat32_t f32,
+    svfloat16x2_t f16x2, svfloat16_t f16,
+    svint8x2_t s8x2, svint8_t s8,
+    svuint8x2_t u8x2, svuint8_t u8,
+    svint16_t s16, svuint16_t u16)
+  __arm_streaming __arm_inout("za")
+{
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8, 0);
+
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8); /* { dg-error {too few 
arguments to function 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8, 0, 0); /* { dg-error {too many 
arguments to function 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (u64, f32x2, f32, u8, 0); /* { dg-error {argument 
1 of 'svtmopa_lane_za32_f32_f32' must be an integer constant expression} } */
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8, u64); /* { dg-error {argument 
5 of 'svtmopa_lane_za32_f32_f32' must be an integer constant expression} } */
+
+  svtmopa_lane_za32_f32_f32 (-1, f32x2, f32, u8, 0); /* { dg-error {passing -1 
to argument 1 of 'svtmopa_lane_za32_f32_f32', which expects a value in the 
range \[0, 3\]} } */
+  svtmopa_lane_za32_f32_f32 (4, f32x2, f32, u8, 0); /* { dg-error {passing 4 
to argument 1 of 'svtmopa_lane_za32_f32_f32', which expects a value in the 
range \[0, 3\]} } */
+
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8, -1); /* { dg-error {passing -1 
to argument 5 of 'svtmopa_lane_za32_f32_f32', which expects a value in the 
range \[0, 3\]} } */
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8, 4); /* { dg-error {passing 4 
to argument 5 of 'svtmopa_lane_za32_f32_f32', which expects a value in the 
range \[0, 3\]} } */
+
+  svtmopa_lane_za32_f32_f32 (0, u8, f32, u8, 0); /* { dg-error {incompatible 
type for argument 2 of 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (0, f32, f32, u8, 0); /* { dg-error {incompatible 
type for argument 2 of 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (0, f16x2, f32, u8, 0); /* { dg-error 
{incompatible type for argument 2 of 'svtmopa_lane_za32_f32_f32'} } */
+
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f16, u8, 0); /* { dg-error 
{incompatible type for argument 3 of 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32x2, u8, 0); /* { dg-error 
{incompatible type for argument 3 of 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (0, f32x2, u8, u8, 0); /* { dg-error {incompatible 
type for argument 3 of 'svtmopa_lane_za32_f32_f32'} } */
+
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u16, 0); /* { dg-error 
{incompatible type for argument 4 of 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, 0, 0); /* { dg-error {incompatible 
type for argument 4 of 'svtmopa_lane_za32_f32_f32'} } */
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, f32, 0); /* { dg-error 
{incompatible type for argument 4 of 'svtmopa_lane_za32_f32_f32'} } */
+
+  svtmopa_lane_za32_s8_u8(0, s8x2, u8, u8, 0);
+  svtmopa_lane_za32_s8_u8(0, u8x2, u8, u8, 0); /* { dg-error {incompatible 
type for argument 2 of 'svtmopa_lane_za32_s8_u8'} } */
+  svtmopa_lane_za32_s8_u8(0, s8x2, s8, u8, 0); /* { dg-error {incompatible 
type for argument 3 of 'svtmopa_lane_za32_s8_u8'} } */
+  svtmopa_lane_za32_u8_s8(0, s8x2, s8, u8, 0); /* { dg-error {incompatible 
type for argument 2 of 'svtmopa_lane_za32_u8_s8'} } */
+  svtmopa_lane_za32_u8_s8(0, u8x2, u8, u8, 0); /* { dg-error {incompatible 
type for argument 3 of 'svtmopa_lane_za32_u8_s8'} } */
+}
+
+void
+f2 (svfloat32x2_t f32x2, svfloat32_t f32, svuint8_t u8) __arm_streaming
+{
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8, 0); /* { dg-error {ACLE 
function 'svtmopa_lane_za32_f32_f32' can only be called from a function that 
has 'za' state} } */
+}
+
+void
+f3 (svfloat32x2_t f32x2, svfloat32_t f32, svuint8_t u8) __arm_inout("za")
+{
+  svtmopa_lane_za32_f32_f32 (0, f32x2, f32, u8, 0); /* { dg-error {ACLE 
function 'svtmopa_lane_za32_f32_f32' can only be called when SME streaming mode 
is enabled} } */
+}
+
+#pragma GCC target ("arch=armv9-a+sme-tmop+sme-f8f16")
+
+void
+f4 (svmfloat8x2_t mf8x2, svmfloat8_t mf8, svuint8_t u8, fpm_t fpm)
+  __arm_streaming __arm_inout("za")
+{
+
+  svtmopa_lane_za16_mf8_mf8_fpm (0, mf8x2, mf8, u8); /* { dg-error {too few 
arguments to function 'svtmopa_lane_za16_mf8_mf8_fpm'} } */
+  svtmopa_lane_za16_mf8_mf8_fpm (0, mf8x2, mf8, u8, 0, 0, fpm); /* { dg-error 
{too many arguments to function 'svtmopa_lane_za16_mf8_mf8_fpm'} } */
+  svtmopa_lane_za16_mf8_mf8_fpm (-1, mf8x2, mf8, u8, 0, fpm); /* { dg-error 
{passing -1 to argument 1 of 'svtmopa_lane_za16_mf8_mf8_fpm', which expects a 
value in the range \[0, 1\]} } */
+  svtmopa_lane_za16_mf8_mf8_fpm (2,  mf8x2, mf8, u8, 0, fpm); /* { dg-error 
{passing 2 to argument 1 of 'svtmopa_lane_za16_mf8_mf8_fpm', which expects a 
value in the range \[0, 1\]} } */
+  svtmopa_lane_za16_mf8_mf8_fpm (0, mf8x2, mf8, u8, 0, mf8); /* { dg-error 
{incompatible type for argument 6 of 'svtmopa_lane_za16_mf8_mf8_fpm'} } */
+}
+
+#pragma GCC target ("arch=armv9-a+sme-tmop+sme-f16f16")
+
+void
+f5 (svfloat16x2_t f16x2, svfloat16_t f16,
+    svuint8_t u8)
+  __arm_streaming __arm_inout("za")
+{
+  svtmopa_lane_za16_f16_f16 (-1, f16x2, f16, u8, 0); /* { dg-error {passing -1 
to argument 1 of 'svtmopa_lane_za16_f16_f16', which expects a value in the 
range \[0, 1\]} } */
+  svtmopa_lane_za16_f16_f16 (2, f16x2, f16, u8, 0); /* { dg-error {passing 2 
to argument 1 of 'svtmopa_lane_za16_f16_f16', which expects a value in the 
range \[0, 1\]} } */
+
+  svtmopa_lane_za16_f16_f16 (1, f16x2, f16, u8, -1); /* { dg-error {passing -1 
to argument 5 of 'svtmopa_lane_za16_f16_f16', which expects a value in the 
range \[0, 3\]} } */
+  svtmopa_lane_za16_f16_f16 (1, f16x2, f16, u8, 4); /* { dg-error {passing 4 
to argument 5 of 'svtmopa_lane_za16_f16_f16', which expects a value in the 
range \[0, 3\]} } */
+}
+
diff --git a/gcc/testsuite/lib/target-supports.exp 
b/gcc/testsuite/lib/target-supports.exp
index 2b450669c3d..066ef42d440 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -12683,6 +12683,7 @@ set exts_sve2 {
      "sme-f8f16" "sme-f8f32"
      "sme-b16b16" "sme-f16f16" "sme-i16i64" "sme" "sme2" "sme2p1"
      "ssve-fp8dot2" "ssve-fp8dot4" "ssve-fp8fma"
+    "sme-tmop"
  }
foreach { aarch64_ext } $exts {
--
2.51.0


Reply via email to