[llvm-branch-commits] [clang] [llvm] [AArch64][llvm] Armv9.8-A: Add support for FEAT_SVE_PERM256 (PR #231433)

Martin Wehking via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Oct 14 02:20:25 PDT 2026


https://github.com/MartinWehking updated https://github.com/llvm/llvm-project/pull/231433

>From 80d2b0a3101be05e8b65857eb9b7bdda9920d7bf Mon Sep 17 00:00:00 2001
From: Martin Wehking <martin.wehking at arm.com>
Date: Tue, 15 Sep 2026 10:17:29 +0000
Subject: [PATCH 1/2] [AArch64][llvm] Armv9.8-A: Add support for
 FEAT_SVE_PERM256

Add support for FEAT_SVE_PERM256 (SVE 128-bit element permute
instructions), which enables already existing instructions,
independently of FEAT_F64MM
---
 clang/test/Driver/aarch64-v98a.c              |  4 ++
 .../print-supported-extensions-aarch64.c      |  1 +
 llvm/lib/Target/AArch64/AArch64.td            |  1 +
 llvm/lib/Target/AArch64/AArch64Features.td    |  7 +-
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  7 ++
 .../lib/Target/AArch64/AArch64SVEInstrInfo.td |  4 +-
 .../AArch64/AsmParser/AArch64AsmParser.cpp    |  1 +
 .../MC/AArch64/SVE/matrix-multiply-fp64.s     | 48 --------------
 llvm/test/MC/AArch64/SVE/permute.s            | 66 +++++++++++++++++++
 .../MC/AArch64/SVE2/directive-arch-negative.s |  5 ++
 llvm/test/MC/AArch64/SVE2/directive-arch.s    |  4 ++
 .../SVE2/directive-arch_extension-negative.s  |  6 ++
 .../AArch64/SVE2/directive-arch_extension.s   |  4 ++
 .../TargetParser/TargetParserTest.cpp         |  5 +-
 14 files changed, 110 insertions(+), 53 deletions(-)
 create mode 100644 llvm/test/MC/AArch64/SVE/permute.s

diff --git a/clang/test/Driver/aarch64-v98a.c b/clang/test/Driver/aarch64-v98a.c
index 1a41a97610e59..af37e6f8b77ad 100644
--- a/clang/test/Driver/aarch64-v98a.c
+++ b/clang/test/Driver/aarch64-v98a.c
@@ -29,3 +29,7 @@
 // RUN: %clang -target aarch64 -march=armv9.8a+sve-rcpc -### -c %s 2>&1 | FileCheck -check-prefix=V98A-SVE-RCPC %s
 // RUN: %clang -target aarch64 -march=armv9.8-a+sve-rcpc -### -c %s 2>&1 | FileCheck -check-prefix=V98A-SVE-RCPC %s
 // V98A-SVE-RCPC: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.8a"{{.*}} "-target-feature" "+sve-rcpc"
+//
+// RUN: %clang -target aarch64 -march=armv9.8a+sve-perm256 -### -c %s 2>&1 | FileCheck -check-prefix=V98A-SVE-PERM256 %s
+// RUN: %clang -target aarch64 -march=armv9.8-a+sve-perm256 -### -c %s 2>&1 | FileCheck -check-prefix=V98A-SVE-PERM256 %s
+// V98A-SVE-PERM256: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.8a"{{.*}} "-target-feature" "+sve-perm256"
diff --git a/clang/test/Driver/print-supported-extensions-aarch64.c b/clang/test/Driver/print-supported-extensions-aarch64.c
index e334d2e8dcee0..4ee6e1d7d80cb 100644
--- a/clang/test/Driver/print-supported-extensions-aarch64.c
+++ b/clang/test/Driver/print-supported-extensions-aarch64.c
@@ -106,6 +106,7 @@
 // CHECK-NEXT:     sve-bitperm         FEAT_SVE_BitPerm                                       Enable bit permutation SVE2 instructions
 // CHECK-NEXT:     sve-f16f32mm        FEAT_SVE_F16F32MM                                      Enable Armv9.6-A FP16 to FP32 Matrix Multiply
 // CHECK-NEXT:     sve-rcpc            FEAT_SVE_LRCPC                                         Enable Armv9.8-A SVE weaker Release Consistency processor consistent (RCpc) model
+// CHECK-NEXT:     sve-perm256         FEAT_SVE_PERM256                                       Enable Armv9.8-A SVE 128-bit element permute instructions
 // CHECK-NEXT:     sve-sha3            FEAT_SVE_SHA3                                          Enable SVE SHA3 instructions
 // CHECK-NEXT:     sve-sm4             FEAT_SVE_SM4                                           Enable SVE SM4 instructions
 // CHECK-NEXT:     sve2                FEAT_SVE2                                              Enable Scalable Vector Extension 2 (SVE2) instructions
diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index 9750fa837c180..d3cbf32413c0b 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -111,6 +111,7 @@ def SME2Unsupported : AArch64Unsupported {
 
 def SMEUnsupported : AArch64Unsupported {
   let F = !listconcat([HasSME, HasSMEI16I64, HasSMEF16F16, HasSMEF64F64, HasSMEFA64,
+                      HasMatMulFP64_or_SVE_PERM256,
                        HasSMEandIsNonStreamingSafe],
                       SME2Unsupported.F);
 }
diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td
index 0434ec5d26ee8..3410d2eb3d42f 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -631,6 +631,9 @@ def FeatureSVE_RCPC: ExtensionWithMArch<"sve-rcpc", "SVE_RCPC", "FEAT_SVE_LRCPC"
   "Enable Armv9.8-A SVE weaker Release Consistency processor consistent (RCpc) model",
    [FeatureSVE2, FeatureRCPC3]>;
 
+def FeatureSVE_PERM256: ExtensionWithMArch<"sve-perm256", "SVE_PERM256", "FEAT_SVE_PERM256",
+  "Enable Armv9.8-A SVE 128-bit element permute instructions">;
+
 //===----------------------------------------------------------------------===//
 //  Future Architecture Technologies
 //===----------------------------------------------------------------------===//
@@ -1136,8 +1139,8 @@ def HasV9_7aOps : Architecture64<9, 7, "a", "v9.7a",
   !listconcat(HasV9_6aOps.DefaultExts, [FeatureSVE2p3, FeatureFPRCVT,
     FeatureF16F32DOT])>;
 def HasV9_8aOps : Architecture64<9, 8, "a", "v9.8a",
-  [HasV9_7aOps],
-  HasV9_7aOps.DefaultExts>;
+  [HasV9_7aOps, FeatureSVE_PERM256],
+  !listconcat(HasV9_7aOps.DefaultExts, [FeatureSVE_PERM256])>;
 def HasV8_0rOps : Architecture64<8, 0, "r", "v8r",
   [ //v8.1
     FeatureCRC, FeaturePAN, FeatureLSE, FeatureCONTEXTIDREL2,
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 07d8d79555b84..9fc0a7fe5a70d 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -243,6 +243,8 @@ def HasLSC64B        : Predicate<"Subtarget->hasLSC64B()">,
                                  AssemblerPredicateWithAll<(all_of FeatureLSC64B), "lsc64b">;
 def HasSVE_RCPC      : Predicate<"Subtarget->isSVEAvailable() && Subtarget->hasSVE_RCPC()">,
                                  AssemblerPredicateWithAll<(all_of FeatureSVE_RCPC), "sve-rcpc">;
+def HasSVE_PERM256     : Predicate<"Subtarget->hasSVE_PERM256()">,
+                                 AssemblerPredicateWithAll<(all_of FeatureSVE_PERM256), "sve-perm256">;
 
 // A subset of SVE(2) instructions are legal in Streaming SVE execution mode,
 // they should be enabled if either has been specified.
@@ -322,6 +324,11 @@ def HasNonStreamingSVE2p2_or_SME2p2
                 AssemblerPredicateWithAll<(any_of FeatureSVE2p2, FeatureSME2p2),
                 "sme2p2 or sve2p2">;
 
+def HasMatMulFP64_or_SVE_PERM256
+    : Predicate<"Subtarget->hasSVE_PERM256() || (Subtarget->isSVEAvailable() && Subtarget->hasMatMulFP64())">,
+                AssemblerPredicateWithAll<(any_of FeatureMatMulFP64, FeatureSVE_PERM256),
+                "f64mm or sve-perm256">;
+
 def HasSMEF16F16_or_SMEF8F16
     : Predicate<"Subtarget->isStreaming() && (Subtarget->hasSMEF16F16() || Subtarget->hasSMEF8F16())">,
                 AssemblerPredicateWithAll<(any_of FeatureSMEF16F16, FeatureSMEF8F16),
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index 9662d7a0cb9f9..e5332dab0080e 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -3957,14 +3957,14 @@ let Predicates = [HasSVE, HasMatMulFP64] in {
   defm LD1RO_D     : sve_mem_ldor_ss<0b11, "ld1rod", Z_d, ZPR64, GPR64NoXZRshifted64, nxv2i64, nxv2i1,  AArch64ld1ro_z, am_sve_regreg_lsl3>;
 } // End HasSVE, HasMatMulFP64
 
-let Predicates = [HasSVE_or_SME, HasMatMulFP64] in {
+let Predicates = [HasSVE_or_SME, HasMatMulFP64_or_SVE_PERM256] in {
   defm ZIP1_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b00, 0, "zip1", int_aarch64_sve_zip1q>;
   defm ZIP2_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b00, 1, "zip2", int_aarch64_sve_zip2q>;
   defm UZP1_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b01, 0, "uzp1", int_aarch64_sve_uzp1q>;
   defm UZP2_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b01, 1, "uzp2", int_aarch64_sve_uzp2q>;
   defm TRN1_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b11, 0, "trn1", int_aarch64_sve_trn1q>;
   defm TRN2_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b11, 1, "trn2", int_aarch64_sve_trn2q>;
-} // End HasSVE_or_SME, HasMatMulFP64
+} // End HasSVE_or_SME, HasMatMulFP64_or_SVE_PERM256
 
 let Predicates = [HasSVE2_or_SME] in {
   // SVE2 integer multiply-add (indexed)
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
index ce50ff30f14cb..0807906fe4510 100644
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -3765,6 +3765,7 @@ constexpr EnumStringDef<FeatureBitset> ExtensionDefs[] = {
     {{"cflt"}, {AArch64::FeatureCFLT}},
     {{"lsc64b"}, {AArch64::FeatureLSC64B}},
     {{"sve-rcpc"}, {AArch64::FeatureSVE_RCPC}},
+    {{"sve-perm256"}, {AArch64::FeatureSVE_PERM256}},
 };
 constexpr auto ExtensionMap = BUILD_ENUM_STRINGS(ExtensionDefs);
 
diff --git a/llvm/test/MC/AArch64/SVE/matrix-multiply-fp64.s b/llvm/test/MC/AArch64/SVE/matrix-multiply-fp64.s
index 14637da848558..c9871c34254c4 100644
--- a/llvm/test/MC/AArch64/SVE/matrix-multiply-fp64.s
+++ b/llvm/test/MC/AArch64/SVE/matrix-multiply-fp64.s
@@ -231,51 +231,3 @@ ld1rod z0.d, p1/z, [x2, x3, lsl #3]
 // CHECK-ENCODING: [0x40,0x04,0xa3,0xa5]
 // CHECK-ERROR: instruction requires: f64mm sve
 // CHECK-UNKNOWN: a5a30440 <unknown>
-
-
-// --------------------------------------------------------------------------//
-// ZIP1, ZIP2 (SVE, 128-bit element)
-
-zip1 z0.q, z1.q, z2.q
-// CHECK-INST: zip1 z0.q, z1.q, z2.q
-// CHECK-ENCODING: [0x20,0x00,0xa2,0x05]
-// CHECK-ERROR: instruction requires: f64mm sve or sme
-// CHECK-UNKNOWN: 05a20020 <unknown>
-
-zip2 z0.q, z1.q, z2.q
-// CHECK-INST: zip2 z0.q, z1.q, z2.q
-// CHECK-ENCODING: [0x20,0x04,0xa2,0x05]
-// CHECK-ERROR: instruction requires: f64mm sve or sme
-// CHECK-UNKNOWN: 05a20420 <unknown>
-
-
-// --------------------------------------------------------------------------//
-// UZP1, UZP2 (SVE, 128-bit element)
-
-uzp1 z0.q, z1.q, z2.q
-// CHECK-INST: uzp1 z0.q, z1.q, z2.q
-// CHECK-ENCODING: [0x20,0x08,0xa2,0x05]
-// CHECK-ERROR: instruction requires: f64mm sve or sme
-// CHECK-UNKNOWN: 05a20820 <unknown>
-
-uzp2 z0.q, z1.q, z2.q
-// CHECK-INST: uzp2 z0.q, z1.q, z2.q
-// CHECK-ENCODING: [0x20,0x0c,0xa2,0x05]
-// CHECK-ERROR: instruction requires: f64mm sve or sme
-// CHECK-UNKNOWN: 05a20c20 <unknown>
-
-
-// --------------------------------------------------------------------------//
-// TRN1, TRN2 (SVE, 128-bit element)
-
-trn1 z0.q, z1.q, z2.q
-// CHECK-INST: trn1 z0.q, z1.q, z2.q
-// CHECK-ENCODING: [0x20,0x18,0xa2,0x05]
-// CHECK-ERROR: instruction requires: f64mm sve or sme
-// CHECK-UNKNOWN: 05a21820 <unknown>
-
-trn2 z0.q, z1.q, z2.q
-// CHECK-INST: trn2 z0.q, z1.q, z2.q
-// CHECK-ENCODING: [0x20,0x1c,0xa2,0x05]
-// CHECK-ERROR: instruction requires: f64mm sve or sme
-// CHECK-UNKNOWN: 05a21c20 <unknown>
diff --git a/llvm/test/MC/AArch64/SVE/permute.s b/llvm/test/MC/AArch64/SVE/permute.s
new file mode 100644
index 0000000000000..5dd3c94258bcc
--- /dev/null
+++ b/llvm/test/MC/AArch64/SVE/permute.s
@@ -0,0 +1,66 @@
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve,+f64mm < %s \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve,+sve-perm256 < %s \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve < %s 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CHECK-ERROR
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve,+sve-perm256 < %s \
+// RUN:   | llvm-objdump --no-print-imm-hex -d --mattr=+sve,+sve-perm256 - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve,+sve-perm256 < %s \
+// RUN:   | llvm-objdump --no-print-imm-hex -d --mattr=+sve,-sve-perm256,-f64mm - \
+// RUN:   | FileCheck %s --check-prefix=CHECK-UNKNOWN
+// Disassemble encoding and check the re-encoding (-show-encoding) matches.
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve,+sve-perm256 < %s \
+// RUN:   | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:   | llvm-mc -triple=aarch64 -mattr=+sve,+sve-perm256 -disassemble -show-encoding \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+v9.8a < %s \
+// RUN:   | sed '/.text/d' | sed 's/.*encoding: //g' \
+// RUN:   | llvm-mc -triple=aarch64 -mattr=+v9.8a -disassemble -show-encoding \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST
+
+// --------------------------------------------------------------------------//
+// ZIP1, ZIP2
+
+zip1 z0.q, z1.q, z2.q
+// CHECK-INST: zip1 z0.q, z1.q, z2.q
+// CHECK-ENCODING: [0x20,0x00,0xa2,0x05]
+// CHECK-ERROR: instruction requires: f64mm or sve-perm256
+// CHECK-UNKNOWN: 05a20020 <unknown>
+
+zip2 z0.q, z1.q, z2.q
+// CHECK-INST: zip2 z0.q, z1.q, z2.q
+// CHECK-ENCODING: [0x20,0x04,0xa2,0x05]
+// CHECK-ERROR: instruction requires: f64mm or sve-perm256
+// CHECK-UNKNOWN: 05a20420 <unknown>
+
+// --------------------------------------------------------------------------//
+// UZP1, UZP2
+
+uzp1 z0.q, z1.q, z2.q
+// CHECK-INST: uzp1 z0.q, z1.q, z2.q
+// CHECK-ENCODING: [0x20,0x08,0xa2,0x05]
+// CHECK-ERROR: instruction requires: f64mm or sve-perm256
+// CHECK-UNKNOWN: 05a20820 <unknown>
+
+uzp2 z0.q, z1.q, z2.q
+// CHECK-INST: uzp2 z0.q, z1.q, z2.q
+// CHECK-ENCODING: [0x20,0x0c,0xa2,0x05]
+// CHECK-ERROR: instruction requires: f64mm or sve-perm256
+// CHECK-UNKNOWN: 05a20c20 <unknown>
+
+// --------------------------------------------------------------------------//
+// TRN1, TRN2
+
+trn1 z0.q, z1.q, z2.q
+// CHECK-INST: trn1 z0.q, z1.q, z2.q
+// CHECK-ENCODING: [0x20,0x18,0xa2,0x05]
+// CHECK-ERROR: instruction requires: f64mm or sve-perm256
+// CHECK-UNKNOWN: 05a21820 <unknown>
+
+trn2 z0.q, z1.q, z2.q
+// CHECK-INST: trn2 z0.q, z1.q, z2.q
+// CHECK-ENCODING: [0x20,0x1c,0xa2,0x05]
+// CHECK-ERROR: instruction requires: f64mm or sve-perm256
+// CHECK-UNKNOWN: 05a21c20 <unknown>
diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s b/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s
index f0d47664f08a7..7f8f2186fbcc1 100644
--- a/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s
+++ b/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s
@@ -70,3 +70,8 @@ bfscale z0.h, p0/m, z0.h, z0.h
 ldapro z0, [x0]
 // CHECK: error: instruction requires: sve-rcpc
 // CHECK-NEXT: ldapro z0, [x0]
+
+.arch armv9.8-a+nosve-perm256
+uzp1 z0.q, z1.q, z2.q
+# CHECK: error: instruction requires: f64mm or sve-perm256
+# CHECK-NEXT:   uzp1 z0.q, z1.q, z2.q
diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch.s b/llvm/test/MC/AArch64/SVE2/directive-arch.s
index 5f042ca386623..7f1b6def2f3a7 100644
--- a/llvm/test/MC/AArch64/SVE2/directive-arch.s
+++ b/llvm/test/MC/AArch64/SVE2/directive-arch.s
@@ -47,3 +47,7 @@ bfscale z0.h, p0/m, z0.h, z0.h
 .arch armv9.6-a+sve-rcpc
 ldapro z0, [x0]
 // CHECK: ldapro z0, [x0]
+
+.arch armv9.8-a
+zip1 z0.q, z1.q, z2.q
+// CHECK: zip1 z0.q, z1.q, z2.q
diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s b/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s
index c03e7deb6490b..f1bd2b6cc6eac 100644
--- a/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s
+++ b/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s
@@ -66,3 +66,9 @@ bfscale z0.h, p0/m, z0.h, z0.h
 ldapro z0, [x0]
 // CHECK: error: instruction requires: sve-rcpc
 // CHECK-NEXT: ldapro z0, [x0]
+
+.arch_extension sve-perm256
+.arch_extension nosve-perm256
+zip1 z0.q, z1.q, z2.q
+// CHECK: error: instruction requires: f64mm or sve-perm256
+// CHECK-NEXT: zip1 z0.q, z1.q, z2.q
diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s b/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s
index 940d7f179f5e2..43a00abd1a48c 100644
--- a/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s
+++ b/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s
@@ -43,3 +43,7 @@ bfscale z0.h, p0/m, z0.h, z0.h
 .arch_extension sve-rcpc
 ldapro z0, [x0]
 // CHECK: ldapro z0, [x0]
+
+.arch_extension sve-perm256
+zip1 z0.q, z1.q, z2.q
+// CHECK: zip1 z0.q, z1.q, z2.q
diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp
index ca977888ed3f7..192f22fb5b79d 100644
--- a/llvm/unittests/TargetParser/TargetParserTest.cpp
+++ b/llvm/unittests/TargetParser/TargetParserTest.cpp
@@ -1509,7 +1509,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
       AArch64::AEK_POPS,         AArch64::AEK_SVESM4,
       AArch64::AEK_MTETC,        AArch64::AEK_HINTE,
       AArch64::AEK_CFLT,         AArch64::AEK_LSC64B,
-      AArch64::AEK_SVE_RCPC,
+      AArch64::AEK_SVE_RCPC,     AArch64::AEK_SVE_PERM256,
   };
 
   std::vector<StringRef> Features;
@@ -1637,6 +1637,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {
   EXPECT_TRUE(llvm::is_contained(Features, "+cflt"));
   EXPECT_TRUE(llvm::is_contained(Features, "+lsc64b"));
   EXPECT_TRUE(llvm::is_contained(Features, "+sve-rcpc"));
+  EXPECT_TRUE(llvm::is_contained(Features, "+sve-perm256"));
 
   // Assuming we listed every extension above, this should produce the same
   // result.
@@ -1821,6 +1822,7 @@ TEST(TargetParserTest, AArch64ArchExtFeature) {
       {"cflt", "nocflt", "+cflt", "-cflt"},
       {"lsc64b", "nolsc64b", "+lsc64b", "-lsc64b"},
       {"sve-rcpc", "nosve-rcpc", "+sve-rcpc", "-sve-rcpc"},
+      {"sve-perm256", "nosve-perm256", "+sve-perm256", "-sve-perm256"},
   };
 
   for (unsigned i = 0; i < std::size(ArchExt); i++) {
@@ -1967,6 +1969,7 @@ AArch64ExtensionDependenciesBaseArchTestParams
          {}},
         {AArch64::ARMV9_5A, {}, {"v9.5a", "mops", "cpa"}, {}},
         {AArch64::ARMV9_7A, {}, {"v9.7a", "f16f32dot"}, {}},
+        {AArch64::ARMV9_8A, {}, {"v9.8a", "sve-perm256"}, {}},
 
         // Positive modifiers
         {AArch64::ARMV8A, {"fp16"}, {"fullfp16"}, {}},

>From 3d32432c68721324ab7032051530643a7c2df62e Mon Sep 17 00:00:00 2001
From: Martin Wehking <martin.wehking at arm.com>
Date: Wed, 14 Oct 2026 09:01:54 +0000
Subject: [PATCH 2/2] fixup! Make predicate more condensed

Remove the sve_perm256 predicate and replace the only other predicate
using it with a more condensed one and make it capture the entire
condition.
---
 llvm/lib/Target/AArch64/AArch64.td             | 2 +-
 llvm/lib/Target/AArch64/AArch64InstrInfo.td    | 6 ++----
 llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 4 ++--
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td
index d3cbf32413c0b..c0a5253fa32e0 100644
--- a/llvm/lib/Target/AArch64/AArch64.td
+++ b/llvm/lib/Target/AArch64/AArch64.td
@@ -111,7 +111,7 @@ def SME2Unsupported : AArch64Unsupported {
 
 def SMEUnsupported : AArch64Unsupported {
   let F = !listconcat([HasSME, HasSMEI16I64, HasSMEF16F16, HasSMEF64F64, HasSMEFA64,
-                      HasMatMulFP64_or_SVE_PERM256,
+                      HasNonStreamingMatMulFP64_or_SVE_PERM256,
                        HasSMEandIsNonStreamingSafe],
                       SME2Unsupported.F);
 }
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 9fc0a7fe5a70d..4446e4c0186a7 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -243,8 +243,6 @@ def HasLSC64B        : Predicate<"Subtarget->hasLSC64B()">,
                                  AssemblerPredicateWithAll<(all_of FeatureLSC64B), "lsc64b">;
 def HasSVE_RCPC      : Predicate<"Subtarget->isSVEAvailable() && Subtarget->hasSVE_RCPC()">,
                                  AssemblerPredicateWithAll<(all_of FeatureSVE_RCPC), "sve-rcpc">;
-def HasSVE_PERM256     : Predicate<"Subtarget->hasSVE_PERM256()">,
-                                 AssemblerPredicateWithAll<(all_of FeatureSVE_PERM256), "sve-perm256">;
 
 // A subset of SVE(2) instructions are legal in Streaming SVE execution mode,
 // they should be enabled if either has been specified.
@@ -324,8 +322,8 @@ def HasNonStreamingSVE2p2_or_SME2p2
                 AssemblerPredicateWithAll<(any_of FeatureSVE2p2, FeatureSME2p2),
                 "sme2p2 or sve2p2">;
 
-def HasMatMulFP64_or_SVE_PERM256
-    : Predicate<"Subtarget->hasSVE_PERM256() || (Subtarget->isSVEAvailable() && Subtarget->hasMatMulFP64())">,
+def HasNonStreamingMatMulFP64_or_SVE_PERM256
+    : Predicate<"(Subtarget->isSVEorStreamingSVEAvailable()  && Subtarget->hasSVE_PERM256()) || (Subtarget->isSVEAvailable() && Subtarget->hasMatMulFP64())">,
                 AssemblerPredicateWithAll<(any_of FeatureMatMulFP64, FeatureSVE_PERM256),
                 "f64mm or sve-perm256">;
 
diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
index e5332dab0080e..da49e3278339b 100644
--- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td
@@ -3957,14 +3957,14 @@ let Predicates = [HasSVE, HasMatMulFP64] in {
   defm LD1RO_D     : sve_mem_ldor_ss<0b11, "ld1rod", Z_d, ZPR64, GPR64NoXZRshifted64, nxv2i64, nxv2i1,  AArch64ld1ro_z, am_sve_regreg_lsl3>;
 } // End HasSVE, HasMatMulFP64
 
-let Predicates = [HasSVE_or_SME, HasMatMulFP64_or_SVE_PERM256] in {
+let Predicates = [HasSVE_or_SME, HasNonStreamingMatMulFP64_or_SVE_PERM256] in {
   defm ZIP1_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b00, 0, "zip1", int_aarch64_sve_zip1q>;
   defm ZIP2_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b00, 1, "zip2", int_aarch64_sve_zip2q>;
   defm UZP1_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b01, 0, "uzp1", int_aarch64_sve_uzp1q>;
   defm UZP2_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b01, 1, "uzp2", int_aarch64_sve_uzp2q>;
   defm TRN1_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b11, 0, "trn1", int_aarch64_sve_trn1q>;
   defm TRN2_ZZZ_Q  : sve_int_perm_bin_perm_128_zz<0b11, 1, "trn2", int_aarch64_sve_trn2q>;
-} // End HasSVE_or_SME, HasMatMulFP64_or_SVE_PERM256
+} // End HasSVE_or_SME, HasNonStreamingMatMulFP64_or_SVE_PERM256
 
 let Predicates = [HasSVE2_or_SME] in {
   // SVE2 integer multiply-add (indexed)



More information about the llvm-branch-commits mailing list