diff --git a/clang/test/Driver/aarch64-v97a.c b/clang/test/Driver/aarch64-v97a.c index 8518d6b069556..a607c1f92ed07 100644 --- a/clang/test/Driver/aarch64-v97a.c +++ b/clang/test/Driver/aarch64-v97a.c @@ -6,7 +6,7 @@ // RUN: %clang -target aarch64 -mlittle-endian -march=armv9.7-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A %s // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.7a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A %s // RUN: %clang -target aarch64_be -mlittle-endian -march=armv9.7-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A %s -// GENERICV97A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} +// GENERICV97A: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+sve2p3" // RUN: %clang -target aarch64_be -march=armv9.7a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A-BE %s // RUN: %clang -target aarch64_be -march=armv9.7-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A-BE %s @@ -14,10 +14,18 @@ // RUN: %clang -target aarch64 -mbig-endian -march=armv9.7-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A-BE %s // RUN: %clang -target aarch64_be -mbig-endian -march=armv9.7a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A-BE %s // RUN: %clang -target aarch64_be -mbig-endian -march=armv9.7-a -### -c %s 2>&1 | FileCheck -check-prefix=GENERICV97A-BE %s -// GENERICV97A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} +// GENERICV97A-BE: "-cc1"{{.*}} "-triple" "aarch64_be{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+sve2p3" // ===== Features supported on aarch64 ===== +// RUN: %clang -target aarch64 -march=armv9.7a+sme2p3 -### -c %s 2>&1 | FileCheck -check-prefix=V97A-SME2p3 %s +// RUN: %clang -target aarch64 -march=armv9.7-a+sme2p3 -### -c %s 2>&1 | FileCheck -check-prefix=V97A-SME2p3 %s +// V97A-SME2p3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+sme2p3" + +// RUN: %clang -target aarch64 -march=armv9.7a+sve2p3 -### -c %s 2>&1 | FileCheck -check-prefix=V97A-SVE2p3 %s +// RUN: %clang -target aarch64 -march=armv9.7-a+sve2p3 -### -c %s 2>&1 | FileCheck -check-prefix=V97A-SVE2p3 %s +// V97A-SVE2p3: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+sve2p3" + // RUN: %clang -target aarch64 -march=armv9.7a+cmh -### -c %s 2>&1 | FileCheck -check-prefix=V97A-CMH %s // RUN: %clang -target aarch64 -march=armv9.7-a+cmh -### -c %s 2>&1 | FileCheck -check-prefix=V97A-CMH %s // V97A-CMH: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "generic" "-target-feature" "+v9.7a"{{.*}} "-target-feature" "+cmh" diff --git a/clang/test/Driver/print-supported-extensions-aarch64.c b/clang/test/Driver/print-supported-extensions-aarch64.c index 1516ed8b30912..ef53f9fba4c43 100644 --- a/clang/test/Driver/print-supported-extensions-aarch64.c +++ b/clang/test/Driver/print-supported-extensions-aarch64.c @@ -81,6 +81,7 @@ // CHECK-NEXT: sme2 FEAT_SME2 Enable Scalable Matrix Extension 2 (SME2) instructions // CHECK-NEXT: sme2p1 FEAT_SME2p1 Enable Scalable Matrix Extension 2.1 instructions // CHECK-NEXT: sme2p2 FEAT_SME2p2 Enable Armv9.6-A Scalable Matrix Extension 2.2 instructions +// CHECK-NEXT: sme2p3 FEAT_SME2p3 Enable Armv9.7-A Scalable Matrix Extension 2.3 instructions // CHECK-NEXT: profile FEAT_SPE Enable Statistical Profiling extension // CHECK-NEXT: predres2 FEAT_SPECRES2 Enable Speculation Restriction Instruction // CHECK-NEXT: ssbs FEAT_SSBS, FEAT_SSBS2 Enable Speculative Store Bypass Safe bit @@ -106,6 +107,7 @@ // CHECK-NEXT: sve2-sm4 Shorthand for +sve2+sve-sm4 // CHECK-NEXT: sve2p1 FEAT_SVE2p1 Enable Scalable Vector Extension 2.1 instructions // CHECK-NEXT: sve2p2 FEAT_SVE2p2 Enable Armv9.6-A Scalable Vector Extension 2.2 instructions +// CHECK-NEXT: sve2p3 FEAT_SVE2p3 Enable Armv9.7-A Scalable Vector Extension 2.3 instructions // CHECK-NEXT: the FEAT_THE Enable Armv8.9-A Translation Hardening Extension // CHECK-NEXT: tlbid FEAT_TLBID Enable Armv9.7-A TLBI Domains extension // CHECK-NEXT: tlbiw FEAT_TLBIW Enable Armv9.5-A TLBI VMALL for Dirty State diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index 86f95488e6bb7..463465310c95b 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -73,9 +73,16 @@ def SVEUnsupported : AArch64Unsupported { SVE2Unsupported.F); } -let F = [HasSME2p2, HasSVE2p2_or_SME2p2, HasNonStreamingSVE_or_SME2p2, - HasNonStreamingSVE2p2_or_SME2p2] in -def SME2p2Unsupported : AArch64Unsupported; +def SME2p3Unsupported : AArch64Unsupported { + let F = [HasSVE2p3_or_SME2p3]; +} + +def SME2p2Unsupported : AArch64Unsupported { + let F = !listconcat([HasSME2p2, HasSVE2p2_or_SME2p2, + HasNonStreamingSVE_or_SME2p2, + HasNonStreamingSVE2p2_or_SME2p2], + SME2p3Unsupported.F); +} def SME2p1Unsupported : AArch64Unsupported { let F = !listconcat([HasSME2p1, HasSVE2p1_or_SME2p1, diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td index 0b117a22f5721..22e1e6ea3de4a 100644 --- a/llvm/lib/Target/AArch64/AArch64Features.td +++ b/llvm/lib/Target/AArch64/AArch64Features.td @@ -607,6 +607,12 @@ def FeatureMTETC: ExtensionWithMArch<"mtetc", "MTETC", "FEAT_MTETC", def FeatureGCIE: ExtensionWithMArch<"gcie", "GCIE", "FEAT_GCIE", "Enable Armv9.7-A GICv5 (Generic Interrupt Controller) CPU Interface Extension", [FeatureNMI]>; +def FeatureSVE2p3 : ExtensionWithMArch<"sve2p3", "SVE2p3", "FEAT_SVE2p3", + "Enable Armv9.7-A Scalable Vector Extension 2.3 instructions", [FeatureSVE2p2]>; + +def FeatureSME2p3 : ExtensionWithMArch<"sme2p3", "SME2p3", "FEAT_SME2p3", + "Enable Armv9.7-A Scalable Matrix Extension 2.3 instructions", [FeatureSME2p2]>; + //===----------------------------------------------------------------------===// // Other Features //===----------------------------------------------------------------------===// @@ -966,8 +972,8 @@ def HasV9_6aOps : Architecture64<9, 6, "a", "v9.6a", !listconcat(HasV9_5aOps.DefaultExts, [FeatureCMPBR, FeatureFPRCVT, FeatureSVE2p2, FeatureLSUI, FeatureOCCMO])>; def HasV9_7aOps : Architecture64<9, 7, "a", "v9.7a", - [HasV9_6aOps], - !listconcat(HasV9_6aOps.DefaultExts, [])>; + [HasV9_6aOps, FeatureSVE2p3], + !listconcat(HasV9_6aOps.DefaultExts, [FeatureSVE2p3])>; 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 334be86014c06..6bdfbecaa2759 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -315,6 +315,10 @@ def HasSVE2p2_or_SME2p2 : Predicate<"Subtarget->isSVEorStreamingSVEAvailable() && (Subtarget->hasSVE2p2() || Subtarget->hasSME2p2())">, AssemblerPredicateWithAll<(any_of FeatureSME2p2, FeatureSVE2p2), "sme2p2 or sve2p2">; +def HasSVE2p3_or_SME2p3 + : Predicate<"Subtarget->isSVEorStreamingSVEAvailable() && (Subtarget->hasSVE2p3() || Subtarget->hasSME2p3())">, + AssemblerPredicateWithAll<(any_of FeatureSME2p3, FeatureSVE2p3), + "sme2p3 or sve2p3">; def HasNonStreamingSVE2p2_or_SME2p2 : Predicate<"(Subtarget->isSVEAvailable() && Subtarget->hasSVE2p2()) ||" "(Subtarget->isSVEorStreamingSVEAvailable() && Subtarget->hasSME2p2())">, diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index bc6b9310686a6..0d82e8c7798cf 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -4615,6 +4615,24 @@ let Predicates = [HasSVE2p2_or_SME2p2] in { defm REVD_ZPzZ : sve_int_perm_rev_revd_z<"revd", AArch64revd_mt>; } // End HasSME2p2orSVE2p2 + +//===----------------------------------------------------------------------===// +// SME2.3 or SVE2.3 instructions +//===----------------------------------------------------------------------===// +let Predicates = [HasSVE2p3_or_SME2p3] in { + // SVE2 Add pairwise within quadword vector segments (unpredicated) + defm ADDQP_ZZZ : sve2_int_mul<0b110, "addqp", null_frag>; + + // SVE2 Add subtract/subtract pairwise + defm ADDSUBP_ZZZ : sve2_int_mul<0b111, "addsubp", null_frag>; + defm SUBP_ZPmZ : sve2_int_arith_pred<0b100001, "subp", null_frag>; + + // SVE2 integer absolute difference and accumulate long + defm SABAL_ZZZ : sve2_int_two_way_absdiff_accum_long<0b0, "sabal">; + defm UABAL_ZZZ : sve2_int_two_way_absdiff_accum_long<0b1, "uabal">; + +} // End HasSME2p3orSVE2p3 + //===----------------------------------------------------------------------===// // SME2.2 or SVE2.2 instructions - Legal in streaming mode iff target has SME2p2 //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index 86a56e842bc82..4bfc74f7aa984 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -3890,6 +3890,8 @@ static const struct Extension { {"mpamv2", {AArch64::FeatureMPAMv2}}, {"mtetc", {AArch64::FeatureMTETC}}, {"gcie", {AArch64::FeatureGCIE}}, + {"sme2p3", {AArch64::FeatureSME2p3}}, + {"sve2p3", {AArch64::FeatureSVE2p3}}, }; static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) { diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 3cdd505f12116..337c6b694a505 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -4085,7 +4085,7 @@ class sve2_int_arith_pred sz, bits<6> opc, string asm, bits<5> Zdn; let Inst{31-24} = 0b01000100; let Inst{23-22} = sz; - let Inst{21-20} = 0b01; + let Inst{21} = 0b0; let Inst{20-16} = opc{5-1}; let Inst{15-14} = 0b10; let Inst{13} = opc{0}; @@ -4590,15 +4590,15 @@ multiclass sve2_int_cadd { def : SVE_3_Op_Imm_Pat(NAME # _D)>; } -class sve2_int_absdiff_accum sz, bits<4> opc, string asm, +class sve2_int_absdiff_accum sz, bits<4> opc, string asm, ZPRRegOp zprty1, ZPRRegOp zprty2> : I<(outs zprty1:$Zda), (ins zprty1:$_Zda, zprty2:$Zn, zprty2:$Zm), asm, "\t$Zda, $Zn, $Zm", "", []>, Sched<[]> { bits<5> Zda; bits<5> Zn; bits<5> Zm; - let Inst{31-24} = 0b01000101; - let Inst{23-22} = sz; + let Inst{31-25} = 0b0100010; + let Inst{24-22} = sz; let Inst{21} = 0b0; let Inst{20-16} = Zm; let Inst{15-14} = 0b11; @@ -4613,10 +4613,10 @@ class sve2_int_absdiff_accum sz, bits<4> opc, string asm, } multiclass sve2_int_absdiff_accum { - def _B : sve2_int_absdiff_accum<0b00, { 0b111, opc }, asm, ZPR8, ZPR8>; - def _H : sve2_int_absdiff_accum<0b01, { 0b111, opc }, asm, ZPR16, ZPR16>; - def _S : sve2_int_absdiff_accum<0b10, { 0b111, opc }, asm, ZPR32, ZPR32>; - def _D : sve2_int_absdiff_accum<0b11, { 0b111, opc }, asm, ZPR64, ZPR64>; + def _B : sve2_int_absdiff_accum<0b100, { 0b111, opc }, asm, ZPR8, ZPR8>; + def _H : sve2_int_absdiff_accum<0b101, { 0b111, opc }, asm, ZPR16, ZPR16>; + def _S : sve2_int_absdiff_accum<0b110, { 0b111, opc }, asm, ZPR32, ZPR32>; + def _D : sve2_int_absdiff_accum<0b111, { 0b111, opc }, asm, ZPR64, ZPR64>; def : SVE_3_Op_Pat(NAME # _B)>; def : SVE_3_Op_Pat(NAME # _H)>; @@ -4626,20 +4626,26 @@ multiclass sve2_int_absdiff_accum { multiclass sve2_int_absdiff_accum_long opc, string asm, SDPatternOperator op> { - def _H : sve2_int_absdiff_accum<0b01, { 0b00, opc }, asm, ZPR16, ZPR8>; - def _S : sve2_int_absdiff_accum<0b10, { 0b00, opc }, asm, ZPR32, ZPR16>; - def _D : sve2_int_absdiff_accum<0b11, { 0b00, opc }, asm, ZPR64, ZPR32>; + def _H : sve2_int_absdiff_accum<0b101, { 0b00, opc }, asm, ZPR16, ZPR8>; + def _S : sve2_int_absdiff_accum<0b110, { 0b00, opc }, asm, ZPR32, ZPR16>; + def _D : sve2_int_absdiff_accum<0b111, { 0b00, opc }, asm, ZPR64, ZPR32>; def : SVE_3_Op_Pat(NAME # _H)>; def : SVE_3_Op_Pat(NAME # _S)>; def : SVE_3_Op_Pat(NAME # _D)>; } +multiclass sve2_int_two_way_absdiff_accum_long { + def _BtoH : sve2_int_absdiff_accum<0b001, { 0b01, U, 0b1 }, asm, ZPR16, ZPR8>; + def _HtoS : sve2_int_absdiff_accum<0b010, { 0b01, U, 0b1 }, asm, ZPR32, ZPR16>; + def _StoD : sve2_int_absdiff_accum<0b011, { 0b01, U, 0b1 }, asm, ZPR64, ZPR32>; +} + multiclass sve2_int_addsub_long_carry opc, string asm, SDPatternOperator op> { - def _S : sve2_int_absdiff_accum<{ opc{1}, 0b0 }, { 0b010, opc{0} }, asm, + def _S : sve2_int_absdiff_accum<{ 0b1, opc{1}, 0b0 }, { 0b010, opc{0} }, asm, ZPR32, ZPR32>; - def _D : sve2_int_absdiff_accum<{ opc{1}, 0b1 }, { 0b010, opc{0} }, asm, + def _D : sve2_int_absdiff_accum<{ 0b1, opc{1}, 0b1 }, { 0b010, opc{0} }, asm, ZPR64, ZPR64>; def : SVE_3_Op_Pat(NAME # _S)>; diff --git a/llvm/test/MC/AArch64/SVE2p3/arithmetic-diagnostics.s b/llvm/test/MC/AArch64/SVE2p3/arithmetic-diagnostics.s new file mode 100644 index 0000000000000..05ee1ee2d13db --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p3/arithmetic-diagnostics.s @@ -0,0 +1,147 @@ +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 2>&1 < %s| FileCheck %s + +// --------------------------------------------------------------------------// +// Test addqp + +addqp z0.h, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addqp z0.h, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addqp z0.s, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addqp z0.s, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addqp z0.d, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addqp z0.d, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addqp z0.b, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addqp z0.b, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Test addsubp + +addsubp z0.h, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addsubp z0.h, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addsubp z0.s, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addsubp z0.s, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addsubp z0.d, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addsubp z0.d, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +addsubp z0.b, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: addsubp z0.b, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Test sabal + +sabal z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabal z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabal z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabal z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabal z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabal z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +sabal z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: sabal z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Test uabal + +uabal z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabal z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabal z0.h, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabal z0.h, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabal z0.s, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabal z0.s, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +uabal z0.d, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: uabal z0.d, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Test subp + +subp z0.h, p0/m, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subp z0.h, p0/m, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subp z0.s, p0/m, z0.h, z0.h +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subp z0.s, p0/m, z0.h, z0.h +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subp z0.d, p0/m, z0.s, z0.s +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subp z0.d, p0/m, z0.s, z0.s +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +subp z0.b, p0/m, z0.d, z0.d +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid element width +// CHECK-NEXT: subp z0.b, p0/m, z0.d, z0.d +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Predicate not in restricted predicate range + +subp z0.h, p8/m, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: invalid restricted predicate register, expected p0..p7 (without element suffix) +// CHECK-NEXT: subp z0.h, p8/m, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Operand must match destination register + +subp z0.b, p0/m, z1.b, z2.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: operand must match destination register +// CHECK-NEXT: subp z0.b, p0/m, z1.b, z2.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +// --------------------------------------------------------------------------// +// Negative tests for instructions that are incompatible with movprfx + +movprfx z0, z7 +addqp z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: addqp z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +movprfx z0, z7 +addsubp z0.b, z0.b, z0.b +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: instruction is unpredictable when following a movprfx, suggest replacing movprfx with mov +// CHECK-NEXT: addsubp z0.b, z0.b, z0.b +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: diff --git a/llvm/test/MC/AArch64/SVE2p3/arithmetic.s b/llvm/test/MC/AArch64/SVE2p3/arithmetic.s new file mode 100644 index 0000000000000..12df18de60381 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p3/arithmetic.s @@ -0,0 +1,275 @@ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sme2p3 < %s \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +// RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ +// RUN: | FileCheck %s --check-prefix=CHECK-ERROR +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2p3 < %s \ +// RUN: | llvm-objdump -d --mattr=+sve2p3 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2p3 < %s \ +// RUN: | llvm-objdump -d --mattr=-sve2p3 --no-print-imm-hex - | FileCheck %s --check-prefix=CHECK-UNKNOWN +// Disassemble encoding and check the re-encoding (-show-encoding) matches. +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p3 < %s \ +// RUN: | sed '/.text/d' | sed 's/.*encoding: //g' \ +// RUN: | llvm-mc -triple=aarch64 -mattr=+sve2p3 -disassemble -show-encoding \ +// RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST + +addqp z0.b, z0.b, z0.b +// CHECK-INST: addqp z0.b, z0.b, z0.b +// CHECK-ENCODING: encoding: [0x00,0x78,0x20,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04207800 + +addqp z31.b, z31.b, z31.b +// CHECK-INST: addqp z31.b, z31.b, z31.b +// CHECK-ENCODING: encoding: [0xff,0x7b,0x3f,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 043f7bff + +addqp z0.h, z0.h, z0.h +// CHECK-INST: addqp z0.h, z0.h, z0.h +// CHECK-ENCODING: encoding: [0x00,0x78,0x60,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04607800 + +addqp z31.h, z31.h, z31.h +// CHECK-INST: addqp z31.h, z31.h, z31.h +// CHECK-ENCODING: encoding: [0xff,0x7b,0x7f,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 047f7bff + +addqp z0.s, z0.s, z0.s +// CHECK-INST: addqp z0.s, z0.s, z0.s +// CHECK-ENCODING: encoding: [0x00,0x78,0xa0,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04a07800 + +addqp z31.s, z31.s, z31.s +// CHECK-INST: addqp z31.s, z31.s, z31.s +// CHECK-ENCODING: encoding: [0xff,0x7b,0xbf,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04bf7bff + +addqp z0.d, z0.d, z0.d +// CHECK-INST: addqp z0.d, z0.d, z0.d +// CHECK-ENCODING: encoding: [0x00,0x78,0xe0,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04e07800 + +addqp z31.d, z31.d, z31.d +// CHECK-INST: addqp z31.d, z31.d, z31.d +// CHECK-ENCODING: encoding: [0xff,0x7b,0xff,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04ff7bff + +// --------------------------------------------------------------------------// +// Test addsubp + +addsubp z0.b, z0.b, z0.b +// CHECK-INST: addsubp z0.b, z0.b, z0.b +// CHECK-ENCODING: encoding: [0x00,0x7c,0x20,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04207c00 + +addsubp z31.b, z31.b, z31.b +// CHECK-INST: addsubp z31.b, z31.b, z31.b +// CHECK-ENCODING: encoding: [0xff,0x7f,0x3f,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 043f7fff + +addsubp z0.h, z0.h, z0.h +// CHECK-INST: addsubp z0.h, z0.h, z0.h +// CHECK-ENCODING: encoding: [0x00,0x7c,0x60,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04607c00 + +addsubp z31.h, z31.h, z31.h +// CHECK-INST: addsubp z31.h, z31.h, z31.h +// CHECK-ENCODING: encoding: [0xff,0x7f,0x7f,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 047f7fff + +addsubp z0.s, z0.s, z0.s +// CHECK-INST: addsubp z0.s, z0.s, z0.s +// CHECK-ENCODING: encoding: [0x00,0x7c,0xa0,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04a07c00 + +addsubp z31.s, z31.s, z31.s +// CHECK-INST: addsubp z31.s, z31.s, z31.s +// CHECK-ENCODING: encoding: [0xff,0x7f,0xbf,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04bf7fff + +addsubp z0.d, z0.d, z0.d +// CHECK-INST: addsubp z0.d, z0.d, z0.d +// CHECK-ENCODING: encoding: [0x00,0x7c,0xe0,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04e07c00 + +addsubp z31.d, z31.d, z31.d +// CHECK-INST: addsubp z31.d, z31.d, z31.d +// CHECK-ENCODING: encoding: [0xff,0x7f,0xff,0x04] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 04ff7fff + +// --------------------------------------------------------------------------// +// Test sabal + +sabal z0.h, z0.b, z0.b +// CHECK-INST: sabal z0.h, z0.b, z0.b +// CHECK-ENCODING: encoding: [0x00,0xd4,0x40,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4440d400 + +sabal z31.h, z31.b, z31.b +// CHECK-INST: sabal z31.h, z31.b, z31.b +// CHECK-ENCODING: encoding: [0xff,0xd7,0x5f,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 445fd7ff + +sabal z0.s, z0.h, z0.h +// CHECK-INST: sabal z0.s, z0.h, z0.h +// CHECK-ENCODING: encoding: [0x00,0xd4,0x80,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4480d400 + +sabal z31.s, z31.h, z31.h +// CHECK-INST: sabal z31.s, z31.h, z31.h +// CHECK-ENCODING: encoding: [0xff,0xd7,0x9f,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 449fd7ff + +sabal z0.d, z0.s, z0.s +// CHECK-INST: sabal z0.d, z0.s, z0.s +// CHECK-ENCODING: encoding: [0x00,0xd4,0xc0,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 44c0d400 + +sabal z31.d, z31.s, z31.s +// CHECK-INST: sabal z31.d, z31.s, z31.s +// CHECK-ENCODING: encoding: [0xff,0xd7,0xdf,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 44dfd7ff + +movprfx z0, z7 +sabal z0.h, z1.b, z2.b +// CHECK-INST: movprfx z0, z7 +// CHECK-INST: sabal z0.h, z1.b, z2.b +// CHECK-ENCODING: encoding: [0x20,0xd4,0x42,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4442d420 + +// --------------------------------------------------------------------------// +// Test uabal + +uabal z0.h, z0.b, z0.b +// CHECK-INST: uabal z0.h, z0.b, z0.b +// CHECK-ENCODING: encoding: [0x00,0xdc,0x40,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4440dc00 + +uabal z31.h, z31.b, z31.b +// CHECK-INST: uabal z31.h, z31.b, z31.b +// CHECK-ENCODING: encoding: [0xff,0xdf,0x5f,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 445fdfff + +uabal z0.s, z0.h, z0.h +// CHECK-INST: uabal z0.s, z0.h, z0.h +// CHECK-ENCODING: encoding: [0x00,0xdc,0x80,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4480dc00 + +uabal z31.s, z31.h, z31.h +// CHECK-INST: uabal z31.s, z31.h, z31.h +// CHECK-ENCODING: encoding: [0xff,0xdf,0x9f,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 449fdfff + +uabal z0.d, z0.s, z0.s +// CHECK-INST: uabal z0.d, z0.s, z0.s +// CHECK-ENCODING: encoding: [0x00,0xdc,0xc0,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 44c0dc00 + +uabal z31.d, z31.s, z31.s +// CHECK-INST: uabal z31.d, z31.s, z31.s +// CHECK-ENCODING: encoding: [0xff,0xdf,0xdf,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 44dfdfff + +movprfx z0, z7 +uabal z0.h, z1.b, z2.b +// CHECK-INST: movprfx z0, z7 +// CHECK-INST: uabal z0.h, z1.b, z2.b +// CHECK-ENCODING: encoding: [0x20,0xdc,0x42,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4442dc20 + +// --------------------------------------------------------------------------// +// Test subp + +subp z0.b, p0/m, z0.b, z0.b +// CHECK-INST: subp z0.b, p0/m, z0.b, z0.b +// CHECK-ENCODING: encoding: [0x00,0xa0,0x10,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4410a000 + +subp z31.b, p7/m, z31.b, z31.b +// CHECK-INST: subp z31.b, p7/m, z31.b, z31.b +// CHECK-ENCODING: encoding: [0xff,0xbf,0x10,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4410bfff + +subp z0.h, p0/m, z0.h, z0.h +// CHECK-INST: subp z0.h, p0/m, z0.h, z0.h +// CHECK-ENCODING: encoding: [0x00,0xa0,0x50,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4450a000 + +subp z31.h, p7/m, z31.h, z31.h +// CHECK-INST: subp z31.h, p7/m, z31.h, z31.h +// CHECK-ENCODING: encoding: [0xff,0xbf,0x50,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4450bfff + +subp z0.s, p0/m, z0.s, z0.s +// CHECK-INST: subp z0.s, p0/m, z0.s, z0.s +// CHECK-ENCODING: encoding: [0x00,0xa0,0x90,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4490a000 + +subp z31.s, p7/m, z31.s, z31.s +// CHECK-INST: subp z31.s, p7/m, z31.s, z31.s +// CHECK-ENCODING: encoding: [0xff,0xbf,0x90,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4490bfff + +subp z0.d, p0/m, z0.d, z0.d +// CHECK-INST: subp z0.d, p0/m, z0.d, z0.d +// CHECK-ENCODING: encoding: [0x00,0xa0,0xd0,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 44d0a000 + +subp z31.d, p7/m, z31.d, z31.d +// CHECK-INST: subp z31.d, p7/m, z31.d, z31.d +// CHECK-ENCODING: encoding: [0xff,0xbf,0xd0,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 44d0bfff + +movprfx z0.b, p0/m, z7.b +subp z0.b, p0/m, z0.b, z1.b +// CHECK-INST: movprfx z0.b, p0/m, z7.b +// CHECK-INST: subp z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: encoding: [0x20,0xa0,0x10,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4410a020 + +movprfx z0, z7 +subp z0.b, p0/m, z0.b, z1.b +// CHECK-INST: movprfx z0, z7 +// CHECK-INST: subp z0.b, p0/m, z0.b, z1.b +// CHECK-ENCODING: encoding: [0x20,0xa0,0x10,0x44] +// CHECK-ERROR: instruction requires: sme2p3 or sve2p3 +// CHECK-UNKNOWN: 4410a020 diff --git a/llvm/test/MC/AArch64/SVE2p3/directive-arch-negative.s b/llvm/test/MC/AArch64/SVE2p3/directive-arch-negative.s new file mode 100644 index 0000000000000..0a12cf85cb007 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p3/directive-arch-negative.s @@ -0,0 +1,7 @@ +// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s + +.arch armv9-a+sve2p3 +.arch armv9-a+nosve2p3 +addqp z0.b, z0.b, z0.b +// CHECK: error: instruction requires: sme2p3 or sve2p3 +// CHECK-NEXT: addqp z0.b, z0.b, z0.b diff --git a/llvm/test/MC/AArch64/SVE2p3/directive-arch_extension-negative.s b/llvm/test/MC/AArch64/SVE2p3/directive-arch_extension-negative.s new file mode 100644 index 0000000000000..1af6245abe16d --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p3/directive-arch_extension-negative.s @@ -0,0 +1,7 @@ +// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s + +.arch_extension sve2p3 +.arch_extension nosve2p3 +addqp z0.b, z0.b, z0.b +// CHECK: error: instruction requires: sme2p3 or sve2p3 +// CHECK-NEXT: addqp z0.b, z0.b, z0.b diff --git a/llvm/test/MC/AArch64/SVE2p3/directive-cpu-negative.s b/llvm/test/MC/AArch64/SVE2p3/directive-cpu-negative.s new file mode 100644 index 0000000000000..f3dac045d4cfd --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p3/directive-cpu-negative.s @@ -0,0 +1,7 @@ +// RUN: not llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s + +.cpu generic+sve2p3 +.cpu generic+nosve2p3 +addqp z0.b, z0.b, z0.b +// CHECK: error: instruction requires: sme2p3 or sve2p3 +// CHECK-NEXT: addqp z0.b, z0.b, z0.b diff --git a/llvm/unittests/TargetParser/TargetParserTest.cpp b/llvm/unittests/TargetParser/TargetParserTest.cpp index 5a14e01d21e6a..3c4ccef151260 100644 --- a/llvm/unittests/TargetParser/TargetParserTest.cpp +++ b/llvm/unittests/TargetParser/TargetParserTest.cpp @@ -1446,7 +1446,8 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { AArch64::AEK_SVESM4, AArch64::AEK_CMH, AArch64::AEK_LSCP, AArch64::AEK_TLBID, AArch64::AEK_MPAMV2, AArch64::AEK_MTETC, - AArch64::AEK_GCIE, + AArch64::AEK_GCIE, AArch64::AEK_SME2P3, + AArch64::AEK_SVE2P3, }; std::vector Features; @@ -1564,6 +1565,8 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { EXPECT_TRUE(llvm::is_contained(Features, "+mpamv2")); EXPECT_TRUE(llvm::is_contained(Features, "+mtetc")); EXPECT_TRUE(llvm::is_contained(Features, "+gcie")); + EXPECT_TRUE(llvm::is_contained(Features, "+sme2p3")); + EXPECT_TRUE(llvm::is_contained(Features, "+sve2p3")); // Assuming we listed every extension above, this should produce the same // result. @@ -1736,6 +1739,8 @@ TEST(TargetParserTest, AArch64ArchExtFeature) { {"mpamv2", "nompamv2", "+mpamv2", "-mpamv2"}, {"mtetc", "nomtetc", "+mtetc", "-mtetc"}, {"gcie", "nogcie", "+gcie", "-gcie"}, + {"sme2p3", "nosme2p3", "+sme2p3", "-sme2p3"}, + {"sve2p3", "nosve2p3", "+sve2p3", "-sve2p3"}, }; for (unsigned i = 0; i < std::size(ArchExt); i++) { @@ -2054,6 +2059,10 @@ AArch64ExtensionDependenciesBaseArchTestParams {AArch64::ARMV9_6A, {"nosve2p1", "sve2p2"}, {"sve2p1", "sve2p2"}, {}}, {AArch64::ARMV9_6A, {"sve2p2", "nosve2p1"}, {}, {"sve2p1", "sve2p2"}}, + // sve2p2 -> {sve2p3} + {AArch64::ARMV9_7A, {"nosve2p2", "sve2p3"}, {"sve2p2", "sve2p3"}, {}}, + {AArch64::ARMV9_7A, {"sve2p3", "nosve2p2"}, {}, {"sve2p2", "sve2p3"}}, + // sme -> {sme2, sme-f16f16, sme-f64f64, sme-i16i64, sme-fa64} {AArch64::ARMV8A, {"nosme", "sme2"}, {"sme", "sme2"}, {}}, {AArch64::ARMV8A, {"sme2", "nosme"}, {}, {"sme", "sme2"}}, @@ -2107,6 +2116,10 @@ AArch64ExtensionDependenciesBaseArchTestParams {AArch64::ARMV9_6A, {"nosme2p1", "sme2p2"}, {"sme2p2", "sme2p1"}, {}}, {AArch64::ARMV9_6A, {"sme2p2", "nosme2p1"}, {}, {"sme2p1", "sme2p2"}}, + // sme2p2 -> {sme2p3} + {AArch64::ARMV9_7A, {"nosme2p2", "sme2p3"}, {"sme2p3", "sme2p2"}, {}}, + {AArch64::ARMV9_7A, {"sme2p3", "nosme2p2"}, {}, {"sme2p2", "sme2p3"}}, + // fp8 -> {sme-f8f16, sme-f8f32, f8f16mm, f8f32mm, fp8dot4, fp8dot2, // ssve-fp8dot4, ssve-fp8dot2} {AArch64::ARMV8A, {"nofp8", "sme-f8f16"}, {"fp8", "sme-f8f16"}, {}},