Program conventions: macros, types, and functions
The Arm C Language Extensions (ACLE) enable C/C++ programmers to exploit the Arm architecture with minimal restrictions on source code portability. The ACLE includes a set of macros, types, and functions to make features of the Arm architecture directly available in C and C++ programs.
This section of the guides provides an overview of these features.
For more detailed information, the Neon macros, types, and functions are described in the Arm C Language Extensions (ACLE). The SVE macros, types, and functions are described in the Arm C Language Extensions for SVE specification.
Macros
The feature test macros allow programmers to determine the availability of target architectural features. For example, to use the Neon or SVE intrinsics, the target platform must support the Advanced SIMD or SVE architecture. When a macro is defined and equal to 1, the corresponding feature is available.
Note: The lists in this section are not exhaustive. Other macros are described on the Arm C Language Extensions web page.
Neon macros
The following table lists the macros that indicate whether particular Neon features are available or not:
Macro | Feature |
---|---|
__aarch64__ |
Selection of architecture-dependent source at compile time Always 1 for AArch64. |
_ARM_NEON |
Advanced SIMD is supported by the compiler. Always 1 for AArch64. |
_ARM_NEON_FP |
Neon floating-point operations are supported. Always 1 for AArch64. |
_ARM_FEATURE_CRYPTO |
Crypto instructions are available. Cryptographic Neon intrinsics are therefore available. |
_ARM_FEATURE_FMA |
The fused multiply accumulate instructions are available. Neon intrinsics which use these instructions are therefore available. |
SVE macros
The following table lists the macro that indicates whether SVE is available or not:
Macro | Feature |
---|---|
_ARM_FEATURE_SVE |
Always 1 if SVE is supported. The SVE instructions are available. SVE intrinsics which use these are therefore available. |
Data types
The ACLE defines several data types that support SIMD processing. These data types are different for Neon and for SVE.
Neon data types
For Neon, there are three main categories of data type available in arm_neon.h
. These data types are named according to the following patterns:
Data type | Description |
---|---|
<base><W>_t |
Scalar data types. For example, int64_t . |
<base><W>x<L>_t |
Vector data types. For example, int32x2_t |
<base><W>x<L>x<N>_t |
Vector array data types. For example, int16x4x2_t |
Where:
<base>
refers to the fundamental data type.<W>
is the width of the fundamental type.<L>
is the number of scalar data type instances in a vector data type, for example an array of scalars.<N>
is the number of vector data type instances in a vector array type, for example a struct of arrays of scalars.
Generally, <W>
and <L>
are values where the vector data types are 64 bits or 128 bits long, and so fit completely into a Neon register. <N>
corresponds with those instructions which operate on multiple registers at the same time.
SVE data types
For SVE, there is no existing mechanism that maps directly to the concept of an SVE vector or predicate. The ACLE classifies SVE vectors and predicates as belonging to a new category of type called sizeless data types. Sizeless data types are composed of vector types and predicate types, and have the prefix sv
, for example svint64_t
.
The following table shows the different data types that the ACLE defines:
Data type | Description |
---|---|
<base><W>_t |
Scalar data types. SVE adds support for float16_t , float32_t , and float64_t . |
sv<base><W>_t |
Sizeless scalar data types for single vectors. For example, svint64_t . |
sv<base><W>x<N>_t |
Sizeless vector data types for two, three, and four vectors. For example, svint64x2_t . |
svbool_t |
Sizeless single predicate data type which has enough bits to control an operation on a vector of bytes. |
Where:
<base>
refers to the fundamental data type.bool
refers to the bool type fromstdbool.h
.<W>
is the width of the fundamental type.<N>
is the number of vector data type instances in a vector array type, for example a struct of arrays of scalars.
Functions
Neon and SVE intrinsics are provided as function prototypes in the header files arm_neon.h
and arm_sve.h
respectively. These functions follow common naming patterns.
Neon functions
For Neon, the function prototypes from arm_neon.h
follow a common naming pattern. This is similar to the naming pattern of the ACLE.
At the most general level, this naming pattern is:
ret v[p][q][r]name[u][n][q][x][_high][_lane | laneq][_n][_result]_type(args)
For example:
int8x16_t vmulq_s8 (int8x16_t a, int8x16_t b)
The mul
in the function name is a hint that this intrinsic uses the MUL
instruction. The types of the arguments and the return value (sixteen bytes of signed integers) map to the following instruction:
MUL Vd.16B, Vn.16B, Vm.16B
This function multiplies corresponding elements of a
and b
and returns the result.
Some of the letters and names are overloaded, but the meaning of the elements in the order they appear in the naming pattern is as follows:
Pattern element | Description |
---|---|
ret |
The return type of the function. |
v |
Short for vector and is present on all the intrinsics. |
p |
Indicates a pairwise operation. ([value] means value might be present). |
q |
Indicates a saturating operation (except for vqtb[l][x] in AArch64 operations, where the q indicates 128-bit index and result operands). |
r |
Indicates a rounding operation. |
name |
The descriptive name of the basic operation. Often, this is an Advanced SIMD instruction, but it does not have to be. |
u |
Indicates signed-to-unsigned saturation. |
n |
Indicates a narrowing operation. |
q |
Post fixing the name indicates an operation on 128-bit vectors. |
x |
Indicates an Advanced SIMD scalar operation in AArch64. It can be one of b , h , s , or d (that is, 8, 16, 32, or 64 bits). |
_high |
In AArch64, used for widening and narrowing operations involving 128-bit operands. For widening 128-bit operands, high refers to the top 64 bits of the source operand (or operands). For narrowing, it refers to the top 64 bits of the destination operand. |
_n |
Indicates a scalar operand that is supplied as an argument. |
_lane |
Indicates a scalar operand taken from the lane of a vector. _laneq indicates a scalar operand that is taken from the lane of an input vector of 128-bit width. left | right means only left or right would appear. |
type |
The primary operand type in short form. |
args |
The arguments of the function. |
SVE functions
For SVE, the function prototypes from arm_sve.h
follow a common pattern. At the most general level, this is:
svbase[_disambiguator][_type0][_type1]...[_predication]
For example, svclz[_u16]_m
says that the full name is svclz_u16_m
and that its overloaded alias is svclz_m
.
The following table describes the different pattern elements:
Pattern element | Description |
---|---|
Base |
The lowercase name of an SVE instruction, with some adjustments |
_disambiguator |
Distinguishes between different forms of a function |
_type0|_type1|... |
Lists the types of vectors and predicates, starting with the return type and continuing with the argument types. |
_predication |
A suffix which describes the inactive elements in the result of a predicated operation. It can be one of z (zero predication), m (merge predication), or x ('Do not care' predication). |
For more information about the individual function parts, see Arm C Language Extensions for SVE specification.