Skip to content

Commit 8e7f073

Browse files
[Clang][AArch64] Change SME attributes for shared/new/preserved state. (#76971)
This patch replaces the `__arm_new_za`, `__arm_shared_za` and `__arm_preserves_za` attributes in favour of: * `__arm_new("za")` * `__arm_in("za")` * `__arm_out("za")` * `__arm_inout("za")` * `__arm_preserves("za")` As described in ARM-software/acle#276. One change is that `__arm_in/out/inout/preserves(S)` are all mutually exclusive, whereas previously it was fine to write `__arm_shared_za __arm_preserves_za`. This case is now represented with `__arm_in("za")`. The current implementation uses the same LLVM attributes under the hood, since `__arm_in/out/inout` are all variations of "shared ZA", so can use the existing `aarch64_pstate_za_shared` attribute in LLVM. #77941 will add support for the new "zt0" state as introduced with SME2.
1 parent 06e3abc commit 8e7f073

File tree

76 files changed

+1663
-1358
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1663
-1358
lines changed

clang/include/clang/AST/Type.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4036,12 +4036,27 @@ class FunctionType : public Type {
40364036
SME_NormalFunction = 0,
40374037
SME_PStateSMEnabledMask = 1 << 0,
40384038
SME_PStateSMCompatibleMask = 1 << 1,
4039-
SME_PStateZASharedMask = 1 << 2,
4040-
SME_PStateZAPreservedMask = 1 << 3,
4041-
SME_AttributeMask = 0b111'111 // We only support maximum 6 bits because of the
4042-
// bitmask in FunctionTypeExtraBitfields.
4039+
4040+
// Describes the value of the state using ArmStateValue.
4041+
SME_ZAShift = 2,
4042+
SME_ZAMask = 0b111 << SME_ZAShift,
4043+
4044+
SME_AttributeMask = 0b111'111 // We only support maximum 6 bits because of
4045+
// the bitmask in FunctionTypeExtraBitfields.
4046+
};
4047+
4048+
enum ArmStateValue : unsigned {
4049+
ARM_None = 0,
4050+
ARM_Preserves = 1,
4051+
ARM_In = 2,
4052+
ARM_Out = 3,
4053+
ARM_InOut = 4,
40434054
};
40444055

4056+
static ArmStateValue getArmZAState(unsigned AttrBits) {
4057+
return (ArmStateValue)((AttrBits & SME_ZAMask) >> SME_ZAShift);
4058+
}
4059+
40454060
/// A simple holder for various uncommon bits which do not fit in
40464061
/// FunctionTypeBitfields. Aligned to alignof(void *) to maintain the
40474062
/// alignment of subsequent objects in TrailingObjects.

clang/include/clang/Basic/Attr.td

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,16 +2539,45 @@ def ArmStreamingCompatible : TypeAttr, TargetSpecificAttr<TargetAArch64> {
25392539
let Documentation = [ArmSmeStreamingCompatibleDocs];
25402540
}
25412541

2542-
def ArmSharedZA : TypeAttr, TargetSpecificAttr<TargetAArch64> {
2543-
let Spellings = [RegularKeyword<"__arm_shared_za">];
2542+
def ArmNew : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
2543+
let Spellings = [RegularKeyword<"__arm_new">];
2544+
let Args = [VariadicStringArgument<"NewArgs">];
2545+
let Subjects = SubjectList<[Function], ErrorDiag>;
2546+
let Documentation = [ArmNewDocs];
2547+
2548+
let AdditionalMembers = [{
2549+
bool isNewZA() const {
2550+
return llvm::is_contained(newArgs(), "za");
2551+
}
2552+
}];
2553+
}
2554+
2555+
def ArmIn : TypeAttr, TargetSpecificAttr<TargetAArch64> {
2556+
let Spellings = [RegularKeyword<"__arm_in">];
2557+
let Args = [VariadicStringArgument<"InArgs">];
2558+
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
2559+
let Documentation = [ArmInDocs];
2560+
}
2561+
2562+
def ArmOut : TypeAttr, TargetSpecificAttr<TargetAArch64> {
2563+
let Spellings = [RegularKeyword<"__arm_out">];
2564+
let Args = [VariadicStringArgument<"OutArgs">];
2565+
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
2566+
let Documentation = [ArmOutDocs];
2567+
}
2568+
2569+
def ArmInOut : TypeAttr, TargetSpecificAttr<TargetAArch64> {
2570+
let Spellings = [RegularKeyword<"__arm_inout">];
2571+
let Args = [VariadicStringArgument<"InOutArgs">];
25442572
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
2545-
let Documentation = [ArmSmeSharedZADocs];
2573+
let Documentation = [ArmInOutDocs];
25462574
}
25472575

2548-
def ArmPreservesZA : TypeAttr, TargetSpecificAttr<TargetAArch64> {
2549-
let Spellings = [RegularKeyword<"__arm_preserves_za">];
2576+
def ArmPreserves : TypeAttr, TargetSpecificAttr<TargetAArch64> {
2577+
let Spellings = [RegularKeyword<"__arm_preserves">];
2578+
let Args = [VariadicStringArgument<"PreserveArgs">];
25502579
let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>;
2551-
let Documentation = [ArmSmePreservesZADocs];
2580+
let Documentation = [ArmPreservesDocs];
25522581
}
25532582

25542583
def ArmLocallyStreaming : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
@@ -2557,14 +2586,6 @@ def ArmLocallyStreaming : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
25572586
let Documentation = [ArmSmeLocallyStreamingDocs];
25582587
}
25592588

2560-
def ArmNewZA : InheritableAttr, TargetSpecificAttr<TargetAArch64> {
2561-
let Spellings = [RegularKeyword<"__arm_new_za">];
2562-
let Subjects = SubjectList<[Function], ErrorDiag>;
2563-
let Documentation = [ArmSmeNewZADocs];
2564-
}
2565-
def : MutualExclusions<[ArmNewZA, ArmSharedZA]>;
2566-
def : MutualExclusions<[ArmNewZA, ArmPreservesZA]>;
2567-
25682589

25692590
def Pure : InheritableAttr {
25702591
let Spellings = [GCC<"pure">];

clang/include/clang/Basic/AttrDocs.td

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6861,30 +6861,73 @@ without changing modes.
68616861
}];
68626862
}
68636863

6864-
def ArmSmeSharedZADocs : Documentation {
6864+
def ArmInDocs : Documentation {
68656865
let Category = DocCatArmSmeAttributes;
68666866
let Content = [{
6867-
The ``__arm_shared_za`` keyword applies to prototyped function types and specifies
6868-
that the function shares SME's matrix storage (ZA) with its caller. This
6869-
means that:
6867+
The ``__arm_in`` keyword applies to prototyped function types and specifies
6868+
that the function shares a given state S with its caller. For ``__arm_in``, the
6869+
function takes the state S as input and returns with the state S unchanged.
68706870

6871-
* the function requires that the processor implements the Scalable Matrix
6872-
Extension (SME).
6871+
The attribute takes string arguments to instruct the compiler which state
6872+
is shared. The supported states for S are:
68736873

6874-
* the function enters with ZA in an active state.
6874+
* ``"za"`` for Matrix Storage (requires SME)
68756875

6876-
* the function returns with ZA in an active state.
6876+
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
6877+
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
68776878
}];
68786879
}
68796880

6880-
def ArmSmePreservesZADocs : Documentation {
6881+
def ArmOutDocs : Documentation {
68816882
let Category = DocCatArmSmeAttributes;
68826883
let Content = [{
6883-
The ``__arm_preserves_za`` keyword applies to prototyped function types and
6884-
specifies that the function does not modify ZA state.
6884+
The ``__arm_out`` keyword applies to prototyped function types and specifies
6885+
that the function shares a given state S with its caller. For ``__arm_out``,
6886+
the function ignores the incoming state for S and returns new state for S.
6887+
6888+
The attribute takes string arguments to instruct the compiler which state
6889+
is shared. The supported states for S are:
6890+
6891+
* ``"za"`` for Matrix Storage (requires SME)
6892+
6893+
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
6894+
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
68856895
}];
68866896
}
68876897

6898+
def ArmInOutDocs : Documentation {
6899+
let Category = DocCatArmSmeAttributes;
6900+
let Content = [{
6901+
The ``__arm_inout`` keyword applies to prototyped function types and specifies
6902+
that the function shares a given state S with its caller. For ``__arm_inout``,
6903+
the function takes the state S as input and returns new state for S.
6904+
6905+
The attribute takes string arguments to instruct the compiler which state
6906+
is shared. The supported states for S are:
6907+
6908+
* ``"za"`` for Matrix Storage (requires SME)
6909+
6910+
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
6911+
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
6912+
}];
6913+
}
6914+
6915+
def ArmPreservesDocs : Documentation {
6916+
let Category = DocCatArmSmeAttributes;
6917+
let Content = [{
6918+
The ``__arm_preserves`` keyword applies to prototyped function types and
6919+
specifies that the function does not read a given state S and returns
6920+
with state S unchanged.
6921+
6922+
The attribute takes string arguments to instruct the compiler which state
6923+
is shared. The supported states for S are:
6924+
6925+
* ``"za"`` for Matrix Storage (requires SME)
6926+
6927+
The attributes ``__arm_in(S)``, ``__arm_out(S)``, ``__arm_inout(S)`` and
6928+
``__arm_preserves(S)`` are all mutually exclusive for the same state S.
6929+
}];
6930+
}
68886931

68896932
def ArmSmeLocallyStreamingDocs : Documentation {
68906933
let Category = DocCatArmSmeAttributes;
@@ -6907,13 +6950,18 @@ at the end of the function.
69076950
}];
69086951
}
69096952

6910-
def ArmSmeNewZADocs : Documentation {
6953+
def ArmNewDocs : Documentation {
69116954
let Category = DocCatArmSmeAttributes;
69126955
let Content = [{
6913-
The ``__arm_new_za`` keyword applies to function declarations and specifies
6914-
that the function will be set up with a fresh ZA context.
6956+
The ``__arm_new`` keyword applies to function declarations and specifies
6957+
that the function will create a new scope for state S.
6958+
6959+
The attribute takes string arguments to instruct the compiler for which state
6960+
to create new scope. The supported states for S are:
6961+
6962+
* ``"za"`` for Matrix Storage (requires SME)
69156963

6916-
This means that:
6964+
For state ``"za"``, this means that:
69176965

69186966
* the function requires that the target processor implements the Scalable Matrix
69196967
Extension (SME).
@@ -6924,8 +6972,8 @@ This means that:
69246972

69256973
* the function will disable PSTATE.ZA (by setting it to 0) before returning.
69266974

6927-
For ``__arm_new_za`` functions Clang will set up the ZA context automatically
6928-
on entry to the function, and disable it before returning. For example, if ZA is
6975+
For ``__arm_new("za")`` functions Clang will set up the ZA context automatically
6976+
on entry to the function and disable it before returning. For example, if ZA is
69296977
in a dormant state Clang will generate the code to commit a lazy-save and set up
69306978
a new ZA state before executing user code.
69316979
}];

clang/include/clang/Basic/AttributeCommonInfo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,19 @@ class AttributeCommonInfo {
255255
return SpellingIndex != SpellingNotCalculated;
256256
}
257257
};
258+
259+
inline bool doesKeywordAttributeTakeArgs(tok::TokenKind Kind) {
260+
switch (Kind) {
261+
default:
262+
return false;
263+
#define KEYWORD_ATTRIBUTE(NAME, HASARG) \
264+
case tok::kw_##NAME: \
265+
return HASARG;
266+
#include "clang/Basic/RegularKeywordAttrInfo.inc"
267+
#undef KEYWORD_ATTRIBUTE
268+
}
269+
}
270+
258271
} // namespace clang
259272

260273
#endif // LLVM_CLANG_BASIC_ATTRIBUTECOMMONINFO_H

clang/include/clang/Basic/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ clang_tablegen(AttrSubMatchRulesList.inc -gen-clang-attr-subject-match-rule-list
4545
SOURCE Attr.td
4646
TARGET ClangAttrSubjectMatchRuleList)
4747

48-
clang_tablegen(AttrTokenKinds.inc -gen-clang-attr-token-kinds
48+
clang_tablegen(RegularKeywordAttrInfo.inc -gen-clang-regular-keyword-attr-info
4949
-I ${CMAKE_CURRENT_SOURCE_DIR}/../../
5050
SOURCE Attr.td
51-
TARGET ClangAttrTokenKinds
51+
TARGET ClangRegularKeywordAttrInfo
5252
)
5353

5454
clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3700,6 +3700,12 @@ def err_sme_definition_using_sm_in_non_sme_target : Error<
37003700
"function executed in streaming-SVE mode requires 'sme'">;
37013701
def err_sme_definition_using_za_in_non_sme_target : Error<
37023702
"function using ZA state requires 'sme'">;
3703+
def err_conflicting_attributes_arm_state : Error<
3704+
"conflicting attributes for state '%0'">;
3705+
def err_unknown_arm_state : Error<
3706+
"unknown state '%0'">;
3707+
def err_missing_arm_state : Error<
3708+
"missing state for %0">;
37033709
def err_cconv_change : Error<
37043710
"function declared '%0' here was previously declared "
37053711
"%select{'%2'|without calling convention}1">;

clang/include/clang/Basic/TokenKinds.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,9 +761,9 @@ KEYWORD(__builtin_sycl_unique_stable_name, KEYSYCL)
761761

762762
// Keywords defined by Attr.td.
763763
#ifndef KEYWORD_ATTRIBUTE
764-
#define KEYWORD_ATTRIBUTE(X) KEYWORD(X, KEYALL)
764+
#define KEYWORD_ATTRIBUTE(X, ...) KEYWORD(X, KEYALL)
765765
#endif
766-
#include "clang/Basic/AttrTokenKinds.inc"
766+
#include "clang/Basic/RegularKeywordAttrInfo.inc"
767767

768768
// Clang-specific keywords enabled only in testing.
769769
TESTING_KEYWORD(__unknown_anytype , KEYALL)

clang/include/clang/Basic/TokenKinds.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ bool isPragmaAnnotation(TokenKind K);
109109

110110
inline constexpr bool isRegularKeywordAttribute(TokenKind K) {
111111
return (false
112-
#define KEYWORD_ATTRIBUTE(X) || (K == tok::kw_##X)
113-
#include "clang/Basic/AttrTokenKinds.inc"
112+
#define KEYWORD_ATTRIBUTE(X, ...) || (K == tok::kw_##X)
113+
#include "clang/Basic/RegularKeywordAttrInfo.inc"
114114
);
115115
}
116116

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7110,15 +7110,7 @@ class Sema final {
71107110
NestedNameSpecInfo &IdInfo,
71117111
bool EnteringContext);
71127112

7113-
/// The kind of conversion to check for. Either all attributes must match exactly,
7114-
/// or the converted type may add/drop '__arm_preserves_za'.
7115-
enum class AArch64SMECallConversionKind {
7116-
MatchExactly,
7117-
MayAddPreservesZA,
7118-
MayDropPreservesZA,
7119-
};
7120-
bool IsInvalidSMECallConversion(QualType FromType, QualType ToType,
7121-
AArch64SMECallConversionKind C);
7113+
bool IsInvalidSMECallConversion(QualType FromType, QualType ToType);
71227114

71237115
/// The parser has parsed a nested-name-specifier
71247116
/// 'template[opt] template-name < template-args >::'.

clang/lib/AST/TypePrinter.cpp

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -937,15 +937,20 @@ void TypePrinter::printFunctionProtoAfter(const FunctionProtoType *T,
937937
OS << ')';
938938

939939
FunctionType::ExtInfo Info = T->getExtInfo();
940+
unsigned SMEBits = T->getAArch64SMEAttributes();
940941

941-
if ((T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask))
942+
if (SMEBits & FunctionType::SME_PStateSMCompatibleMask)
942943
OS << " __arm_streaming_compatible";
943-
if ((T->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask))
944+
if (SMEBits & FunctionType::SME_PStateSMEnabledMask)
944945
OS << " __arm_streaming";
945-
if ((T->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask))
946-
OS << " __arm_shared_za";
947-
if ((T->getAArch64SMEAttributes() & FunctionType::SME_PStateZAPreservedMask))
948-
OS << " __arm_preserves_za";
946+
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves)
947+
OS << " __arm_preserves(\"za\")";
948+
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In)
949+
OS << " __arm_in(\"za\")";
950+
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out)
951+
OS << " __arm_out(\"za\")";
952+
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut)
953+
OS << " __arm_inout(\"za\")";
949954

950955
printFunctionAfter(Info, OS);
951956

@@ -1788,14 +1793,6 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
17881793
OS << "__arm_streaming_compatible";
17891794
return;
17901795
}
1791-
if (T->getAttrKind() == attr::ArmSharedZA) {
1792-
OS << "__arm_shared_za";
1793-
return;
1794-
}
1795-
if (T->getAttrKind() == attr::ArmPreservesZA) {
1796-
OS << "__arm_preserves_za";
1797-
return;
1798-
}
17991796

18001797
OS << " __attribute__((";
18011798
switch (T->getAttrKind()) {
@@ -1839,8 +1836,10 @@ void TypePrinter::printAttributedAfter(const AttributedType *T,
18391836
case attr::WebAssemblyFuncref:
18401837
case attr::ArmStreaming:
18411838
case attr::ArmStreamingCompatible:
1842-
case attr::ArmSharedZA:
1843-
case attr::ArmPreservesZA:
1839+
case attr::ArmIn:
1840+
case attr::ArmOut:
1841+
case attr::ArmInOut:
1842+
case attr::ArmPreserves:
18441843
llvm_unreachable("This attribute should have been handled already");
18451844

18461845
case attr::NSReturnsRetained:

clang/lib/CodeGen/CGCall.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,14 +1767,21 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
17671767
FPT->isNothrow())
17681768
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
17691769

1770-
if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateSMEnabledMask)
1770+
unsigned SMEBits = FPT->getAArch64SMEAttributes();
1771+
if (SMEBits & FunctionType::SME_PStateSMEnabledMask)
17711772
FuncAttrs.addAttribute("aarch64_pstate_sm_enabled");
1772-
if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateSMCompatibleMask)
1773+
if (SMEBits & FunctionType::SME_PStateSMCompatibleMask)
17731774
FuncAttrs.addAttribute("aarch64_pstate_sm_compatible");
1774-
if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateZASharedMask)
1775+
1776+
// ZA
1777+
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Out ||
1778+
FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_InOut)
1779+
FuncAttrs.addAttribute("aarch64_pstate_za_shared");
1780+
if (FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_Preserves ||
1781+
FunctionType::getArmZAState(SMEBits) == FunctionType::ARM_In) {
17751782
FuncAttrs.addAttribute("aarch64_pstate_za_shared");
1776-
if (FPT->getAArch64SMEAttributes() & FunctionType::SME_PStateZAPreservedMask)
17771783
FuncAttrs.addAttribute("aarch64_pstate_za_preserved");
1784+
}
17781785
}
17791786

17801787
static void AddAttributesFromAssumes(llvm::AttrBuilder &FuncAttrs,
@@ -2446,9 +2453,6 @@ void CodeGenModule::ConstructAttributeList(StringRef Name,
24462453

24472454
if (TargetDecl->hasAttr<ArmLocallyStreamingAttr>())
24482455
FuncAttrs.addAttribute("aarch64_pstate_sm_body");
2449-
2450-
if (TargetDecl->hasAttr<ArmNewZAAttr>())
2451-
FuncAttrs.addAttribute("aarch64_pstate_za_new");
24522456
}
24532457

24542458
// Attach "no-builtins" attributes to:

0 commit comments

Comments
 (0)