From fcd545863d27148f26a3ef98bd20501a4df48ec5 Mon Sep 17 00:00:00 2001 From: David Sherwood Date: Tue, 18 Oct 2022 16:43:44 +0000 Subject: [PATCH] [AArch64] Add SVE2.1 target feature for Armv9-A 2022 Architecture Extension First patch in a series adding MC layer support for SVE2.1. This patch adds the following feature: sve2p1 Some of the existing SVE instructions added for SME are now also available under the sve2p1 feature, which are now guarded by the HasSVE2p1orSME predicate. The reference can be found here: https://developer.arm.com/documentation/ddi0602/2022-09 Differential Revision: https://reviews.llvm.org/D136352 --- llvm/include/llvm/Support/AArch64TargetParser.def | 1 + llvm/include/llvm/Support/AArch64TargetParser.h | 1 + llvm/lib/Target/AArch64/AArch64.td | 5 ++++- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 8 ++++++++ llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td | 12 ------------ llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td | 13 +++++++++++++ llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp | 1 + llvm/test/MC/AArch64/SVE2p1/directive-arch-negative.s | 7 +++++++ llvm/test/MC/AArch64/SVE2p1/directive-arch.s | 5 +++++ .../MC/AArch64/SVE2p1/directive-arch_extension-negative.s | 7 +++++++ llvm/test/MC/AArch64/SVE2p1/directive-arch_extension.s | 5 +++++ llvm/test/MC/AArch64/SVE2p1/feature-sve2p1-implies-sve2.s | 7 +++++++ llvm/unittests/Support/TargetParserTest.cpp | 4 +++- 13 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 llvm/test/MC/AArch64/SVE2p1/directive-arch-negative.s create mode 100644 llvm/test/MC/AArch64/SVE2p1/directive-arch.s create mode 100644 llvm/test/MC/AArch64/SVE2p1/directive-arch_extension-negative.s create mode 100644 llvm/test/MC/AArch64/SVE2p1/directive-arch_extension.s create mode 100644 llvm/test/MC/AArch64/SVE2p1/feature-sve2p1-implies-sve2.s diff --git a/llvm/include/llvm/Support/AArch64TargetParser.def b/llvm/include/llvm/Support/AArch64TargetParser.def index e5cb9b8..49ed806 100644 --- a/llvm/include/llvm/Support/AArch64TargetParser.def +++ b/llvm/include/llvm/Support/AArch64TargetParser.def @@ -128,6 +128,7 @@ AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", 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/include/llvm/Support/AArch64TargetParser.h b/llvm/include/llvm/Support/AArch64TargetParser.h index 8de7eb3..f4e157c 100644 --- a/llvm/include/llvm/Support/AArch64TargetParser.h +++ b/llvm/include/llvm/Support/AArch64TargetParser.h @@ -73,6 +73,7 @@ enum ArchExtKind : uint64_t { 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/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index 80115aa..03759f5 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -162,6 +162,9 @@ def FeatureSVE2SHA3 : SubtargetFeature<"sve2-sha3", "HasSVE2SHA3", "true", 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 PAUnsupported : AArch64Unsupported { } 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 index 56c30f4..3d439a2 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -128,6 +128,8 @@ def HasSVE : Predicate<"Subtarget->hasSVE()">, 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 @@ def HasSVE2orSME : 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 index 3dec59f..1272036 100644 --- a/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SMEInstrInfo.td @@ -229,18 +229,6 @@ def : Pat<(i64 (int_aarch64_sme_get_tpidr2)), 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 index 98dc3a2..f9b4e5d 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -3555,3 +3555,16 @@ let Predicates = [HasSVE2BitPerm] in { 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 index 74c01c0..84f0f79 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -3379,6 +3379,7 @@ static const struct Extension { {"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 index 0000000..7f1fa8f --- /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 index 0000000..c52f271 --- /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 index 0000000..29de56c --- /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 index 0000000..3eb39c0 --- /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 index 0000000..96193f1 --- /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 index 16d9b5d..e93f169 100644 --- a/llvm/unittests/Support/TargetParserTest.cpp +++ b/llvm/unittests/Support/TargetParserTest.cpp @@ -1505,7 +1505,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { 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 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { 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 @@ TEST(TargetParserTest, AArch64ArchExtFeature) { {"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"}, -- 2.7.4