[llvm] [AArch64][SME2] Add ZT0 attributes to SMEAttrs (PR #77607)
Kerry McLaughlin via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 10 05:42:47 PST 2024
https://github.com/kmclaughlin-arm created https://github.com/llvm/llvm-project/pull/77607
This patch extends SMEAttrs to interpret the following new attributes,
which are mutually exclusive and apply to SME2 only:
- aarch64_sme_zt0_in (ZT0_In)
- aarch64_sme_zt0_out (ZT0_Out)
- aarch64_sme_zt0_inout (ZT0_InOut)
- aarch64_sme_zt0_new (ZT0_New)
- aarch64_sme_zt0_preserved (ZT0_Preserved)
ZT0_In, ZT0_Out, ZT0_InOut & ZT0_Preserved are all considered to share
ZT0. These attributes will be required by later patches to determine
if ZT0 should be preserved around function calls, or cleared on entry
to the function.
>From 08ca20b751f6c03282647589bf45ec408553816d Mon Sep 17 00:00:00 2001
From: Kerry McLaughlin <kerry.mclaughlin at arm.com>
Date: Tue, 9 Jan 2024 11:09:29 +0000
Subject: [PATCH] [AArch64][SME2] Add ZT0 attributes to SMEAttrs
This patch extends SMEAttrs to interpret the following new attributes,
which are mutually exclusive and apply to SME2 only:
- aarch64_sme_zt0_in (ZT0_In)
- aarch64_sme_zt0_out (ZT0_Out)
- aarch64_sme_zt0_inout (ZT0_InOut)
- aarch64_sme_zt0_new (ZT0_New)
- aarch64_sme_zt0_preserved (ZT0_Preserved)
ZT0_In, ZT0_Out, ZT0_InOut & ZT0_Preserved are all considered to share
ZT0. These attributes will be required by later patches to determine
if ZT0 should be preserved around function calls, or cleared on entry
to the function.
---
.../AArch64/Utils/AArch64SMEAttributes.cpp | 18 +++
.../AArch64/Utils/AArch64SMEAttributes.h | 32 ++++--
.../Target/AArch64/SMEAttributesTest.cpp | 103 ++++++++++++++++++
3 files changed, 145 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
index 0082b4017986c6..82b07419a244a0 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
+++ b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.cpp
@@ -18,8 +18,11 @@ void SMEAttrs::set(unsigned M, bool Enable) {
else
Bitmask &= ~M;
+ // Streaming Mode Attrs
assert(!(hasStreamingInterface() && hasStreamingCompatibleInterface()) &&
"SM_Enabled and SM_Compatible are mutually exclusive");
+
+ // ZA Attrs
assert(!(hasNewZABody() && hasSharedZAInterface()) &&
"ZA_New and ZA_Shared are mutually exclusive");
assert(!(hasNewZABody() && preservesZA()) &&
@@ -28,6 +31,11 @@ void SMEAttrs::set(unsigned M, bool Enable) {
"ZA_New and ZA_NoLazySave are mutually exclusive");
assert(!(hasSharedZAInterface() && (Bitmask & ZA_NoLazySave)) &&
"ZA_Shared and ZA_NoLazySave are mutually exclusive");
+
+ // ZT0 Attrs
+ assert((!sharesZT0() || (hasNewZT0Body() ^ isZT0In() ^ isZT0InOut() ^
+ isZT0Out() ^ preservesZT0())) &&
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
}
SMEAttrs::SMEAttrs(const CallBase &CB) {
@@ -60,6 +68,16 @@ SMEAttrs::SMEAttrs(const AttributeList &Attrs) {
Bitmask |= ZA_New;
if (Attrs.hasFnAttr("aarch64_pstate_za_preserved"))
Bitmask |= ZA_Preserved;
+ if (Attrs.hasFnAttr("aarch64_sme_zt0_in"))
+ Bitmask |= ZT0_In;
+ if (Attrs.hasFnAttr("aarch64_sme_zt0_out"))
+ Bitmask |= ZT0_Out;
+ if (Attrs.hasFnAttr("aarch64_sme_zt0_inout"))
+ Bitmask |= ZT0_InOut;
+ if (Attrs.hasFnAttr("aarch64_sme_zt0_preserved"))
+ Bitmask |= ZT0_Preserved;
+ if (Attrs.hasFnAttr("aarch64_sme_zt0_new"))
+ Bitmask |= ZT0_New;
}
std::optional<bool>
diff --git a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h
index e766b778b54102..88d67ad4b51f53 100644
--- a/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h
+++ b/llvm/lib/Target/AArch64/Utils/AArch64SMEAttributes.h
@@ -29,14 +29,19 @@ class SMEAttrs {
// Enum with bitmasks for each individual SME feature.
enum Mask {
Normal = 0,
- SM_Enabled = 1 << 0, // aarch64_pstate_sm_enabled
- SM_Compatible = 1 << 1, // aarch64_pstate_sm_compatible
- SM_Body = 1 << 2, // aarch64_pstate_sm_body
- ZA_Shared = 1 << 3, // aarch64_pstate_sm_shared
- ZA_New = 1 << 4, // aarch64_pstate_sm_new
- ZA_Preserved = 1 << 5, // aarch64_pstate_sm_preserved
- ZA_NoLazySave = 1 << 6, // Used for SME ABI routines to avoid lazy saves
- All = ZA_Preserved - 1
+ SM_Enabled = 1 << 0, // aarch64_pstate_sm_enabled
+ SM_Compatible = 1 << 1, // aarch64_pstate_sm_compatible
+ SM_Body = 1 << 2, // aarch64_pstate_sm_body
+ ZA_Shared = 1 << 3, // aarch64_pstate_sm_shared
+ ZA_New = 1 << 4, // aarch64_pstate_sm_new
+ ZA_Preserved = 1 << 5, // aarch64_pstate_sm_preserved
+ ZA_NoLazySave = 1 << 6, // Used for SME ABI routines to avoid lazy saves
+ ZT0_New = 1 << 7, // aarch64_sme_zt0_new
+ ZT0_In = 1 << 8, // aarch64_sme_zt0_in
+ ZT0_Out = 1 << 9, // aarch64_sme_zt0_out
+ ZT0_InOut = 1 << 10, // aarch64_sme_zt0_inout
+ ZT0_Preserved = 1 << 11, // aarch64_sme_zt0_preserved
+ All = ZT0_Preserved - 1
};
SMEAttrs(unsigned Mask = Normal) : Bitmask(0) { set(Mask); }
@@ -86,6 +91,17 @@ class SMEAttrs {
return hasZAState() && Callee.hasPrivateZAInterface() &&
!(Callee.Bitmask & ZA_NoLazySave);
}
+
+ // Interfaces to query ZT0 State
+ bool hasNewZT0Body() const { return Bitmask & ZT0_New; }
+ bool isZT0In() const { return Bitmask & ZT0_In; }
+ bool isZT0Out() const { return Bitmask & ZT0_Out; }
+ bool isZT0InOut() const { return Bitmask & ZT0_InOut; }
+ bool preservesZT0() const { return Bitmask & ZT0_Preserved; }
+ bool sharesZT0() const {
+ return Bitmask & (ZT0_In | ZT0_Out | ZT0_InOut | ZT0_Preserved);
+ }
+ bool hasZT0State() const { return hasNewZT0Body() || sharesZT0(); }
};
} // namespace llvm
diff --git a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
index 7780c71bbc00e0..9c88ec53589a73 100644
--- a/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
+++ b/llvm/unittests/Target/AArch64/SMEAttributesTest.cpp
@@ -50,6 +50,37 @@ TEST(SMEAttributes, Constructors) {
->getFunction("foo"))
.preservesZA());
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_in\"")
+ ->getFunction("foo"))
+ .isZT0In());
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_out\"")
+ ->getFunction("foo"))
+ .isZT0Out());
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_inout\"")
+ ->getFunction("foo"))
+ .isZT0InOut());
+
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_in\"")
+ ->getFunction("foo"))
+ .sharesZT0());
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_out\"")
+ ->getFunction("foo"))
+ .sharesZT0());
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_inout\"")
+ ->getFunction("foo"))
+ .sharesZT0());
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_preserved\"")
+ ->getFunction("foo"))
+ .sharesZT0());
+
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_preserved\"")
+ ->getFunction("foo"))
+ .preservesZT0());
+
+ ASSERT_TRUE(SA(*parseIR("declare void @foo() \"aarch64_sme_zt0_new\"")
+ ->getFunction("foo"))
+ .hasNewZT0Body());
+
// Invalid combinations.
EXPECT_DEBUG_DEATH(SA(SA::SM_Enabled | SA::SM_Compatible),
"SM_Enabled and SM_Compatible are mutually exclusive");
@@ -58,6 +89,29 @@ TEST(SMEAttributes, Constructors) {
EXPECT_DEBUG_DEATH(SA(SA::ZA_New | SA::ZA_Preserved),
"ZA_New and ZA_Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_New | SA::ZT0_In),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_New | SA::ZT0_Out),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_New | SA::ZT0_InOut),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_New | SA::ZT0_Preserved),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_In | SA::ZT0_Out),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_In | SA::ZT0_InOut),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_Out | SA::ZT0_InOut),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_Preserved | SA::ZT0_In),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_Preserved | SA::ZT0_Out),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+ EXPECT_DEBUG_DEATH(SA(SA::ZT0_Preserved | SA::ZT0_InOut),
+ "ZT0_New,In,Out,InOut,Preserved are mutually exclusive");
+
// Test that the set() methods equally check validity.
EXPECT_DEBUG_DEATH(SA(SA::SM_Enabled).set(SA::SM_Compatible),
"SM_Enabled and SM_Compatible are mutually exclusive");
@@ -95,6 +149,55 @@ TEST(SMEAttributes, Basics) {
ASSERT_FALSE(SA(SA::Normal).hasNewZABody());
ASSERT_FALSE(SA(SA::Normal).hasZAState());
ASSERT_FALSE(SA(SA::Normal).preservesZA());
+
+ // Test ZT0 State interfaces
+ ASSERT_TRUE(SA(SA::ZT0_In).isZT0In());
+ ASSERT_FALSE(SA(SA::ZT0_In).isZT0Out());
+ ASSERT_FALSE(SA(SA::ZT0_In).isZT0InOut());
+ ASSERT_FALSE(SA(SA::ZT0_In).preservesZT0());
+ ASSERT_FALSE(SA(SA::ZT0_In).hasNewZT0Body());
+ ASSERT_TRUE(SA(SA::ZT0_In).sharesZT0());
+ ASSERT_TRUE(SA(SA::ZT0_In).hasZT0State());
+
+ ASSERT_TRUE(SA(SA::ZT0_Out).isZT0Out());
+ ASSERT_FALSE(SA(SA::ZT0_Out).isZT0In());
+ ASSERT_FALSE(SA(SA::ZT0_Out).isZT0InOut());
+ ASSERT_FALSE(SA(SA::ZT0_Out).preservesZT0());
+ ASSERT_FALSE(SA(SA::ZT0_Out).hasNewZT0Body());
+ ASSERT_TRUE(SA(SA::ZT0_Out).sharesZT0());
+ ASSERT_TRUE(SA(SA::ZT0_Out).hasZT0State());
+
+ ASSERT_TRUE(SA(SA::ZT0_InOut).isZT0InOut());
+ ASSERT_FALSE(SA(SA::ZT0_InOut).isZT0In());
+ ASSERT_FALSE(SA(SA::ZT0_InOut).isZT0Out());
+ ASSERT_FALSE(SA(SA::ZT0_InOut).preservesZT0());
+ ASSERT_FALSE(SA(SA::ZT0_InOut).hasNewZT0Body());
+ ASSERT_TRUE(SA(SA::ZT0_InOut).sharesZT0());
+ ASSERT_TRUE(SA(SA::ZT0_InOut).hasZT0State());
+
+ ASSERT_TRUE(SA(SA::ZT0_Preserved).preservesZT0());
+ ASSERT_FALSE(SA(SA::ZT0_Preserved).isZT0In());
+ ASSERT_FALSE(SA(SA::ZT0_Preserved).isZT0Out());
+ ASSERT_FALSE(SA(SA::ZT0_Preserved).isZT0InOut());
+ ASSERT_FALSE(SA(SA::ZT0_Preserved).hasNewZT0Body());
+ ASSERT_TRUE(SA(SA::ZT0_Preserved).sharesZT0());
+ ASSERT_TRUE(SA(SA::ZT0_Preserved).hasZT0State());
+
+ ASSERT_TRUE(SA(SA::ZT0_New).hasNewZT0Body());
+ ASSERT_FALSE(SA(SA::ZT0_New).isZT0In());
+ ASSERT_FALSE(SA(SA::ZT0_New).isZT0Out());
+ ASSERT_FALSE(SA(SA::ZT0_New).isZT0InOut());
+ ASSERT_FALSE(SA(SA::ZT0_New).preservesZT0());
+ ASSERT_FALSE(SA(SA::ZT0_New).sharesZT0());
+ ASSERT_TRUE(SA(SA::ZT0_New).hasZT0State());
+
+ ASSERT_FALSE(SA(SA::Normal).isZT0In());
+ ASSERT_FALSE(SA(SA::Normal).isZT0Out());
+ ASSERT_FALSE(SA(SA::Normal).isZT0InOut());
+ ASSERT_FALSE(SA(SA::Normal).preservesZT0());
+ ASSERT_FALSE(SA(SA::Normal).hasNewZT0Body());
+ ASSERT_FALSE(SA(SA::Normal).sharesZT0());
+ ASSERT_FALSE(SA(SA::Normal).hasZT0State());
}
TEST(SMEAttributes, Transitions) {
More information about the llvm-commits
mailing list