From 80b917a085b967418222a5187260cd216be32649 Mon Sep 17 00:00:00 2001 From: Sander de Smalen Date: Fri, 20 Dec 2024 15:51:23 +0000 Subject: [PATCH] [SME] Add __arm_agnostic("sme_za_state") keyword attribute (#336) The `__arm_agnostic` keyword attribute enables the user to specify that a function is agnostic to a specified piece of architectural state. That means that the function must preserve this state when it exists, or otherwise ignores its contents. The reason for not naming this something like `__arm_za_compatible` was so that we might want use the attribute keyword for other architectural state in the future. --- main/acle.md | 62 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 10 deletions(-) diff --git a/main/acle.md b/main/acle.md index 3e434b5c..3178149f 100644 --- a/main/acle.md +++ b/main/acle.md @@ -432,6 +432,7 @@ Armv8.4-A [[ARMARMv84]](#ARMARMv84). Support is added for the Dot Product intrin [`arm_neon_sve_bridge.h`](#arm_neon_sve_bridge.h) header file, rather than the [NEON-SVE bridge](#neon-sve-bridge) intrinsics. * Removed extraneous `const` from SVE2.1 store intrinsics. +* Added [`__arm_agnostic`](#arm_agnostic) keyword attribute. ### References @@ -861,6 +862,7 @@ predefine the associated macro to a nonzero value. | **Name** | **Target** | **Predefined macro** | | ----------------------------------------------------------- | --------------------- | --------------------------------- | +| [`__arm_agnostic`](#arm_agnostic) | function type | `__ARM_FEATURE_SME` | | [`__arm_locally_streaming`](#arm_locally_streaming) | function declaration | `__ARM_FEATURE_LOCALLY_STREAMING` | | [`__arm_in`](#ways-of-sharing-state) | function type | Argument-dependent | | [`__arm_inout`](#ways-of-sharing-state) | function type | Argument-dependent | @@ -5059,6 +5061,31 @@ if such a restoration is necessary. For example: } ``` +## `__arm_agnostic` + +A function with the `__arm_agnostic` [keyword attribute](#keyword-attributes) +must preserve the architectural state that is specified by its arguments when +such state exists at runtime. The function is otherwise unconcerned with this +state. + +The `__arm_agnostic` [keyword attribute](#keyword-attributes) applies to +**function types** and accepts the following arguments: + +```"sme_za_state"``` + +* This attribute affects the ABI of a function, which must implement an + [agnostic-ZA interface](#agnostic-za). It is the compiler's responsibility + to ensure that the function's object code honors the ABI requirements. + +* The use of `__arm_agnostic("sme_za_state")` allows writing functions that + are compatible with ZA state without having to share ZA state with the + caller, as required by `__arm_preserves`. The use of this attribute + does not imply that SME is available. + +* It is not valid for a function declaration with + `__arm_agnostic("sme_za_state")` to [share](#shares-state) PSTATE.ZA state + with its caller. + ## Mapping to the Procedure Call Standard [[AAPCS64]](#AAPCS64) classifies functions as having one of the following @@ -5070,13 +5097,21 @@ interfaces: * a “shared-ZA” interface -If a C or C++ function F forms part of the object code's ABI, that -object code function has a shared-ZA interface if and only if at least -one of the following is true: + + +* an "agnostic-ZA" interface + +If a C or C++ function F forms part of the object code's ABI: -* F shares ZA with its caller +* the object code function has a shared-ZA interface if and only if at least + one of the following is true: -* F shares ZT0 with its caller + * F shares ZA with its caller + + * F shares ZT0 with its caller + +* the object code function has an agnostic-ZA interface if and only if F's type + has an `__arm_agnostic("sme_za_state")` attribute. All other functions have a private-ZA interface. @@ -5161,12 +5196,15 @@ function F if at least one of the following is true: Otherwise, ZA can be in any state on entry to A if at least one of the following is true: -* F [uses](#uses-state) `"za"` +* F [uses](#uses-state) `"za"`. + +* F [uses](#uses-state) `"zt0"`. -* F [uses](#uses-state) `"zt0"` +* F's type has an [`__arm_agnostic("sme_za_state")` attribute](#agnostic-za) + and A's clobber-list includes neither `"za"` nor `"zt0"`. -Otherwise, ZA can be off or dormant on entry to A, as for what AAPCS64 -calls “private-ZA” functions. +Otherwise, ZA can be off or dormant on entry to A, in the same way as if F were +to call what the [[AAPCS64]](#AAPCS64) describes as a "private-ZA" function. If ZA is active on entry to A then A's instructions must ensure that ZA is also active when the asm finishes. @@ -5193,7 +5231,11 @@ depend on ZT0 as well as ZA. | off | off | F's uses and A's clobbers are disjoint | | dormant | dormant | " " " | | dormant | off | " " ", and A clobbers `"za"` | -| active | active | F uses `"za"` and/or `"zt0"` | +| active | active | F uses `"za"` and/or `"zt0"`, or | +| | | F's type has an | +| | | `__arm_agnostic("sme_za_state")` | +| | | attribute with A's clobber-list | +| | | including neither `"za"` nor `"zt0"` | The [`__ARM_STATE` macros](#state-strings) indicate whether a compiler is guaranteed to support a particular clobber string. For example,