diff --git a/llvm/include/llvm/Support/AArch64TargetParser.h b/llvm/include/llvm/Support/AArch64TargetParser.h --- a/llvm/include/llvm/Support/AArch64TargetParser.h +++ b/llvm/include/llvm/Support/AArch64TargetParser.h @@ -73,6 +73,7 @@ AEK_MOPS = 1ULL << 41, // FEAT_MOPS AEK_PERFMON = 1ULL << 42, // FEAT_PMUv3 AEK_SME2 = 1ULL << 43, // FEAT_SME2 + AEK_SVE2p1 = 1ULL << 44, // FEAT_SVE2p1 }; enum class ArchKind { diff --git a/llvm/include/llvm/Support/AArch64TargetParser.def b/llvm/include/llvm/Support/AArch64TargetParser.def --- a/llvm/include/llvm/Support/AArch64TargetParser.def +++ b/llvm/include/llvm/Support/AArch64TargetParser.def @@ -128,6 +128,7 @@ AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4") AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3") AARCH64_ARCH_EXT_NAME("sve2-bitperm", AArch64::AEK_SVE2BITPERM, "+sve2-bitperm", "-sve2-bitperm") +AARCH64_ARCH_EXT_NAME("sve2p1", AArch64::AEK_SVE2p1, "+sve2p1", "-sve2p1") AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc") AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand") AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte") diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -162,6 +162,9 @@ def FeatureSVE2BitPerm : SubtargetFeature<"sve2-bitperm", "HasSVE2BitPerm", "true", "Enable bit permutation SVE2 instructions (FEAT_SVE_BitPerm)", [FeatureSVE2]>; +def FeatureSVE2p1: SubtargetFeature<"sve2p1", "HasSVE2p1", "true", + "Enable Scalable Vector Extension 2.1 instructions", [FeatureSVE2]>; + def FeatureZCRegMove : SubtargetFeature<"zcm", "HasZeroCycleRegMove", "true", "Has zero-cycle register moves">; @@ -645,7 +648,7 @@ } def SMEUnsupported : AArch64Unsupported { - let F = [HasSME, HasSMEF64F64, HasSMEI16I64, HasSME2]; + let F = [HasSME, HasSMEF64F64, HasSMEI16I64, HasSME2, HasSVE2p1_or_HasSME2]; } include "AArch64SchedA53.td" diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -128,6 +128,8 @@ AssemblerPredicateWithAll<(all_of FeatureSVE), "sve">; def HasSVE2 : Predicate<"Subtarget->hasSVE2()">, AssemblerPredicateWithAll<(all_of FeatureSVE2), "sve2">; +def HasSVE2p1 : Predicate<"Subtarget->hasSVE2p1()">, + AssemblerPredicate<(any_of FeatureSVE2p1), "sve2p1">; def HasSVE2AES : Predicate<"Subtarget->hasSVE2AES()">, AssemblerPredicateWithAll<(all_of FeatureSVE2AES), "sve2-aes">; def HasSVE2SM4 : Predicate<"Subtarget->hasSVE2SM4()">, @@ -154,6 +156,12 @@ : Predicate<"Subtarget->hasSVE2() || Subtarget->hasSME()">, AssemblerPredicateWithAll<(any_of FeatureSVE2, FeatureSME), "sve2 or sme">; +def HasSVE2p1_or_HasSME + : Predicate<"Subtarget->hasSVE2p1() || Subtarget->hasSME()">, + AssemblerPredicate<(any_of FeatureSME, FeatureSVE2p1), "sme or sve2p1">; +def HasSVE2p1_or_HasSME2 + : Predicate<"Subtarget->hasSVE2p1() || Subtarget->hasSME2()">, + AssemblerPredicate<(any_of FeatureSME2, FeatureSVE2p1), "sme2 or sve2p1">; // A subset of NEON instructions are legal in Streaming SVE execution mode, // they should be enabled if either has been specified. def HasNEONorSME diff --git a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td @@ -229,18 +229,6 @@ def OBSCURE_COPY : Pseudo<(outs GPR64:$dst), (ins GPR64:$idx), []>, Sched<[]> { } def : Pat<(i64 (AArch64ObscureCopy (i64 GPR64:$idx))), (OBSCURE_COPY GPR64:$idx)>; - -//===----------------------------------------------------------------------===// -// SVE2 instructions -//===----------------------------------------------------------------------===// - -defm REVD_ZPmZ : sve2_int_perm_revd<"revd", AArch64revd_mt>; - -defm SCLAMP_ZZZ : sve2_clamp<"sclamp", 0b0, int_aarch64_sve_sclamp>; -defm UCLAMP_ZZZ : sve2_clamp<"uclamp", 0b1, int_aarch64_sve_uclamp>; - -defm PSEL_PPPRI : sve2_int_perm_sel_p<"psel", int_aarch64_sve_psel>; - } // End let Predicates = [HasSME] //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -3555,3 +3555,16 @@ defm BDEP_ZZZ : sve2_misc_bitwise<0b1101, "bdep", int_aarch64_sve_bdep_x>; defm BGRP_ZZZ : sve2_misc_bitwise<0b1110, "bgrp", int_aarch64_sve_bgrp_x>; } // End HasSVE2BitPerm + +//===----------------------------------------------------------------------===// +// SME or SVE2.1 instructions +//===----------------------------------------------------------------------===// + +let Predicates = [HasSVE2p1_or_HasSME] in { +defm REVD_ZPmZ : sve2_int_perm_revd<"revd", AArch64revd_mt>; + +defm SCLAMP_ZZZ : sve2_clamp<"sclamp", 0b0, int_aarch64_sve_sclamp>; +defm UCLAMP_ZZZ : sve2_clamp<"uclamp", 0b1, int_aarch64_sve_uclamp>; + +defm PSEL_PPPRI : sve2_int_perm_sel_p<"psel", int_aarch64_sve_psel>; +} // End HasSVE2p1_or_HasSME diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -3379,6 +3379,7 @@ {"sve2-sm4", {AArch64::FeatureSVE2SM4}}, {"sve2-sha3", {AArch64::FeatureSVE2SHA3}}, {"sve2-bitperm", {AArch64::FeatureSVE2BitPerm}}, + {"sve2p1", {AArch64::FeatureSVE2p1}}, {"ls64", {AArch64::FeatureLS64}}, {"xs", {AArch64::FeatureXS}}, {"pauth", {AArch64::FeaturePAuth}}, diff --git a/llvm/test/MC/AArch64/SVE2p1/directive-arch-negative.s b/llvm/test/MC/AArch64/SVE2p1/directive-arch-negative.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/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+sve2p1 +.arch armv9-a+nosve2p1 +sclamp z0.s, z1.s, z2.s +// CHECK: error: instruction requires: sme or sve2p1 +// CHECK: sclamp z0.s, z1.s, z2.s diff --git a/llvm/test/MC/AArch64/SVE2p1/directive-arch.s b/llvm/test/MC/AArch64/SVE2p1/directive-arch.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/directive-arch.s @@ -0,0 +1,5 @@ +// RUN: llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s + +.arch armv9-a+sve2p1 +sclamp z0.s, z1.s, z2.s +// CHECK: sclamp z0.s, z1.s, z2.s diff --git a/llvm/test/MC/AArch64/SVE2p1/directive-arch_extension-negative.s b/llvm/test/MC/AArch64/SVE2p1/directive-arch_extension-negative.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/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 sve2p1 +.arch_extension nosve2p1 +sclamp z0.s, z1.s, z2.s +// CHECK: error: instruction requires: sme or sve2p1 +// CHECK: sclamp z0.s, z1.s, z2.s diff --git a/llvm/test/MC/AArch64/SVE2p1/directive-arch_extension.s b/llvm/test/MC/AArch64/SVE2p1/directive-arch_extension.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/directive-arch_extension.s @@ -0,0 +1,5 @@ +// RUN: llvm-mc -triple aarch64 -filetype asm -o - %s 2>&1 | FileCheck %s + +.arch_extension sve2p1 +sclamp z0.s, z1.s, z2.s +// CHECK: sclamp z0.s, z1.s, z2.s diff --git a/llvm/test/MC/AArch64/SVE2p1/feature-sve2p1-implies-sve2.s b/llvm/test/MC/AArch64/SVE2p1/feature-sve2p1-implies-sve2.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/AArch64/SVE2p1/feature-sve2p1-implies-sve2.s @@ -0,0 +1,7 @@ +// This test verifies SVE2p1 implies SVE2. + +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2p1 2>&1 < %s \ +// RUN: | FileCheck %s + +cmla z0.b, z1.b, z2.b, #0 +// CHECK: cmla z0.b, z1.b, z2.b, #0 diff --git a/llvm/unittests/Support/TargetParserTest.cpp b/llvm/unittests/Support/TargetParserTest.cpp --- a/llvm/unittests/Support/TargetParserTest.cpp +++ b/llvm/unittests/Support/TargetParserTest.cpp @@ -1505,7 +1505,7 @@ AArch64::AEK_BRBE, AArch64::AEK_PAUTH, AArch64::AEK_FLAGM, AArch64::AEK_SME, AArch64::AEK_SMEF64F64, AArch64::AEK_SMEI16I64, AArch64::AEK_SME2, AArch64::AEK_HBC, AArch64::AEK_MOPS, - AArch64::AEK_PERFMON}; + AArch64::AEK_PERFMON, AArch64::AEK_SVE2p1}; std::vector Features; @@ -1544,6 +1544,7 @@ EXPECT_TRUE(llvm::is_contained(Features, "+sve2-sm4")); EXPECT_TRUE(llvm::is_contained(Features, "+sve2-sha3")); EXPECT_TRUE(llvm::is_contained(Features, "+sve2-bitperm")); + EXPECT_TRUE(llvm::is_contained(Features, "+sve2p1")); EXPECT_TRUE(llvm::is_contained(Features, "+rcpc")); EXPECT_TRUE(llvm::is_contained(Features, "+rand")); EXPECT_TRUE(llvm::is_contained(Features, "+mte")); @@ -1625,6 +1626,7 @@ {"sve2-aes", "nosve2-aes", "+sve2-aes", "-sve2-aes"}, {"sve2-sm4", "nosve2-sm4", "+sve2-sm4", "-sve2-sm4"}, {"sve2-sha3", "nosve2-sha3", "+sve2-sha3", "-sve2-sha3"}, + {"sve2p1", "nosve2p1", "+sve2p1", "-sve2p1"}, {"sve2-bitperm", "nosve2-bitperm", "+sve2-bitperm", "-sve2-bitperm"}, {"dotprod", "nodotprod", "+dotprod", "-dotprod"}, {"rcpc", "norcpc", "+rcpc", "-rcpc"},