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 from stdbool.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.

Previous Next