On Tue, Aug 11, 2026 at 04:11:24PM +0000, [email protected] wrote:
>
> This patch adds support for ACLE system hint intrinsics
> __yield(), __wfe(), __wfi(), __sev() and __sevl() and their
> corresponding AArch64 builtins. The ACLE specification is
> available at [1].
>
> Regression tested on aarch64-none-linux-gnu with no regressions.
>
> Ok for trunk?
>
> Thanks,
> Srinath
>
> gcc/ChangeLog:
>
> * config/aarch64/aarch64-builtins.cc (enum aarch64_builtins): Add
> AARCH64_BUILTIN_YIELD, AARCH64_BUILTIN_WFE, AARCH64_BUILTIN_WFI,
> AARCH64_BUILTIN_SEV and AARCH64_BUILTIN_SEVL.
> (aarch64_init_syshintop_builtins): New function.
> (aarch64_general_init_builtins): Call aarch64_init_syshintop_builtins.
> (aarch64_general_expand_builtin): Expand the system hint builtins.
> * config/aarch64/aarch64.md (unspecv): Add UNSPECV_YIELD, UNSPECV_WFE,
> UNSPECV_WFI, UNSPECV_SEV and UNSPECV_SEVL.
> (yield): New insn pattern.
> (wfe): Likewise.
> (wfi): Likewise.
> (sev): Likewise.
> (sevl): Likewise.
> * config/aarch64/arm_acle.h (__yield): Define hint intrinsics.
> (__wfe): Likewise.
> (__wfi): Likewise.
> (__sev): Likewise.
> (__sevl): Likewise.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.target/aarch64/acle/hint-1.c: New test.
> * gcc.target/aarch64/acle/hint-2.c: Likewise.
>
> [1] https://github.com/ARM-software/acle/blob/main/main/acle.md#hints
> ---
> gcc/config/aarch64/aarch64-builtins.cc | 51 ++++++++++++
> gcc/config/aarch64/aarch64.md | 45 +++++++++++
> gcc/config/aarch64/arm_acle.h | 16 ++++
> .../gcc.target/aarch64/acle/hint-1.c | 26 +++++++
> .../gcc.target/aarch64/acle/hint-2.c | 77 +++++++++++++++++++
> 5 files changed, 215 insertions(+)
> create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/hint-1.c
> create mode 100644 gcc/testsuite/gcc.target/aarch64/acle/hint-2.c
>
> diff --git a/gcc/config/aarch64/aarch64-builtins.cc
> b/gcc/config/aarch64/aarch64-builtins.cc
> index 8cd1bc4b1a2..5cc5d1491e5 100644
> --- a/gcc/config/aarch64/aarch64-builtins.cc
> +++ b/gcc/config/aarch64/aarch64-builtins.cc
> @@ -751,6 +751,12 @@ enum aarch64_builtins
> AARCH64_BUILTIN_STSHH_SF,
> AARCH64_BUILTIN_STSHH_DF,
> AARCH64_BUILTIN_STSHH_PTR,
> + /* System Hint Operation builtins. */
> + AARCH64_BUILTIN_YIELD,
> + AARCH64_BUILTIN_WFE,
> + AARCH64_BUILTIN_WFI,
> + AARCH64_BUILTIN_SEV,
> + AARCH64_BUILTIN_SEVL,
> AARCH64_BUILTIN_MAX
> };
>
> @@ -1261,6 +1267,30 @@ aarch64_get_attributes (unsigned int f, machine_mode
> mode)
> return aarch64_add_attribute ("leaf", attrs);
> }
>
> +/* System Hint Operation builtins. */
> +void
> +aarch64_init_syshintop_builtins (void)
> +{
> + tree vtype_node
> + = build_function_type_list (void_type_node, NULL);
> +
> + aarch64_builtin_decls[AARCH64_BUILTIN_YIELD]
> + = aarch64_general_add_builtin ("__builtin_aarch64_yield",
> + vtype_node, AARCH64_BUILTIN_YIELD);
> + aarch64_builtin_decls[AARCH64_BUILTIN_WFE]
> + = aarch64_general_add_builtin ("__builtin_aarch64_wfe",
> + vtype_node, AARCH64_BUILTIN_WFE);
> + aarch64_builtin_decls[AARCH64_BUILTIN_WFI]
> + = aarch64_general_add_builtin ("__builtin_aarch64_wfi",
> + vtype_node, AARCH64_BUILTIN_WFI);
> + aarch64_builtin_decls[AARCH64_BUILTIN_SEV]
> + = aarch64_general_add_builtin ("__builtin_aarch64_sev",
> + vtype_node, AARCH64_BUILTIN_SEV);
> + aarch64_builtin_decls[AARCH64_BUILTIN_SEVL]
> + = aarch64_general_add_builtin ("__builtin_aarch64_sevl",
> + vtype_node, AARCH64_BUILTIN_SEVL);
> +}
> +
We should define the user-facing names directly, using
aarch64_general_simulate_builtin.
> /* Due to the architecture not providing lane variant of the lane
> instructions
> for fcmla we can't use the standard simd builtin expansion code, but we
> still want the majority of the validation that would normally be done. */
> @@ -2377,6 +2407,7 @@ aarch64_general_init_builtins (void)
>
> aarch64_init_gcs_builtins ();
> aarch64_init_pcdphint_builtins ();
> + aarch64_init_syshintop_builtins ();
>
> if (in_lto_p)
> handle_arm_acle_h ();
> @@ -4354,6 +4385,26 @@ aarch64_general_expand_builtin (unsigned int fcode,
> tree exp, rtx target,
> return ops[0].value;
> }
>
> + case AARCH64_BUILTIN_YIELD:
> + emit_insn (GEN_FCN (CODE_FOR_yield) ());
> + return NULL_RTX;
> +
> + case AARCH64_BUILTIN_WFE:
> + emit_insn (GEN_FCN (CODE_FOR_wfe) ());
> + return NULL_RTX;
> +
> + case AARCH64_BUILTIN_WFI:
> + emit_insn (GEN_FCN (CODE_FOR_wfi) ());
> + return NULL_RTX;
> +
> + case AARCH64_BUILTIN_SEV:
> + emit_insn (GEN_FCN (CODE_FOR_sev) ());
> + return NULL_RTX;
> +
> + case AARCH64_BUILTIN_SEVL:
> + emit_insn (GEN_FCN (CODE_FOR_sevl) ());
> + return NULL_RTX;
> +
> case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ0_V2SF:
> case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ90_V2SF:
> case AARCH64_SIMD_BUILTIN_FCMLA_LANEQ180_V2SF:
> diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
> index 9cb55602c36..60dd72e4935 100644
> --- a/gcc/config/aarch64/aarch64.md
> +++ b/gcc/config/aarch64/aarch64.md
> @@ -425,6 +425,11 @@ (define_c_enum "unspecv" [
> UNSPECV_BLOCKAGE ; Represent a blockage
> UNSPECV_PROBE_STACK_RANGE ; Represent stack range probing.
> UNSPECV_SPECULATION_BARRIER ; Represent speculation barrier.
> + UNSPECV_YIELD ; Represent yield instruction.
> + UNSPECV_WFE ; Represent wfe instruction.
> + UNSPECV_WFI ; Represent wfi instruction.
> + UNSPECV_SEV ; Represent sev instruction.
> + UNSPECV_SEVL ; Represent sevl instruction.
> UNSPECV_BTI_NOARG ; Represent BTI.
> UNSPECV_BTI_C ; Represent BTI c.
> UNSPECV_BTI_J ; Represent BTI j.
> @@ -1334,6 +1339,46 @@ (define_insn "nop"
> [(set_attr "type" "no_insn")]
> )
>
> +(define_insn "yield"
> + [(unspec_volatile [(const_int 0)] UNSPECV_YIELD)
> + (clobber (mem:BLK (scratch)))]
> + ""
> + "yield"
> + [(set_attr "type" "nop")]
> +)
> +
> +(define_insn "wfe"
> + [(unspec_volatile [(const_int 0)] UNSPECV_WFE)
> + (clobber (mem:BLK (scratch)))]
> + ""
> + "wfe"
> + [(set_attr "type" "nop")]
> +)
> +
> +(define_insn "wfi"
> + [(unspec_volatile [(const_int 0)] UNSPECV_WFI)
> + (clobber (mem:BLK (scratch)))]
> + ""
> + "wfi"
> + [(set_attr "type" "nop")]
> +)
> +
> +(define_insn "sev"
> + [(unspec_volatile [(const_int 0)] UNSPECV_SEV)
> + (clobber (mem:BLK (scratch)))]
> + ""
> + "sev"
> + [(set_attr "type" "nop")]
> +)
> +
> +(define_insn "sevl"
> + [(unspec_volatile [(const_int 0)] UNSPECV_SEVL)
> + (clobber (mem:BLK (scratch)))]
> + ""
> + "sevl"
> + [(set_attr "type" "nop")]
> +)
> +
When do we include "aarch64" in an insn name? It might be better to avoid
potential clashes with generic names.
> (define_insn "prefetch"
> [(prefetch (match_operand:DI 0 "aarch64_prefetch_operand" "Dp")
> (match_operand:QI 1 "const_int_operand" "")
> diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h
> index b31e23e6cba..be3b2dc0552 100644
> --- a/gcc/config/aarch64/arm_acle.h
> +++ b/gcc/config/aarch64/arm_acle.h
> @@ -353,6 +353,22 @@ __rndrrs (uint64_t *__res)
>
> #pragma GCC pop_options
>
> +/* Sytem hint operations. */
> +#define __yield() \
> + __builtin_aarch64_yield ()
> +
> +#define __wfe() \
> + __builtin_aarch64_wfe ()
> +
> +#define __wfi() \
> + __builtin_aarch64_wfi ()
> +
> +#define __sev() \
> + __builtin_aarch64_sev ()
> +
> +#define __sevl() \
> + __builtin_aarch64_sevl ()
> +
> #ifdef __cplusplus
> }
> #endif
> diff --git a/gcc/testsuite/gcc.target/aarch64/acle/hint-1.c
> b/gcc/testsuite/gcc.target/aarch64/acle/hint-1.c
> new file mode 100644
> index 00000000000..17372a09617
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/acle/hint-1.c
> @@ -0,0 +1,26 @@
> +/* Test the ACLE hint intrinsics. */
> +/* { dg-do compile } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include <arm_acle.h>
> +
> +/*
> +** test_hint:
> +** ...
> +** yield
> +** wfe
> +** sev
> +** sevl
> +** wfi
> +**...
> +** ret
> +*/
> +void
> +test_hint ()
> +{
> + __yield ();
> + __wfe ();
> + __sev ();
> + __sevl ();
> + __wfi ();
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/acle/hint-2.c
> b/gcc/testsuite/gcc.target/aarch64/acle/hint-2.c
> new file mode 100644
> index 00000000000..151fd690fa2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/acle/hint-2.c
> @@ -0,0 +1,77 @@
> + /* Test the ACLE hint intrinsics effect on memory. */
> +/* { dg-do compile } */
> +/* { dg-options "-O2" } */
> +/* { dg-final { check-function-bodies "**" "" } } */
> +
> +#include <arm_acle.h>
> +
> +/*
> +** foo:
> +** ...
> +** mov w[0-9]+, 5
> +** str w[0-9]+, \[x0\]
> +** yield
> +** mov w[0-9]+, 4
> +** str w[0-9]+, \[x0\]
> +** wfe
> +** mov w[0-9]+, 3
> +** str w[0-9]+, \[x0\]
> +** sev
> +** str w[0-9]+, \[x0\]
> +** sevl
> +** mov w[0-9]+, 9
> +** str w[0-9]+, \[x0\]
> +** wfi
> +** mov w0, 0
> +** ret
> +*/
> +int foo (int* counter)
> +{
> + *counter = 5;
> + __yield();
> + *counter = 4;
> + __wfe();
> + *counter = 3;
> + __sev();
> + *counter = 4;
> + __sevl();
> + *counter = 9;
> + __wfi();
> + return 0;
> +}
> +
> +/*
> +** foo1:
> +** ...
> +** mov w[0-9]+, 5
> +** str w[0-9]+, \[x0\]
> +** yield
> +** mov w[0-9]+, 4
> +** str w[0-9]+, \[x0\]
> +** yield
> +** mov w[0-9]+, 3
> +** str w[0-9]+, \[x0\]
> +** yield
> +** mov w[0-9]+, 6
> +** str w[0-9]+, \[x0\]
> +** yield
> +** mov w[0-9]+, 9
> +** str w[0-9]+, \[x0\]
> +** yield
> +** mov w0, 0
> +** ret
> +*/
> +int foo1 (int* counter)
> +{
> + *counter = 5;
> + __yield();
> + *counter = 4;
> + __yield();
> + *counter = 3;
> + __yield();
> + *counter = 6;
> + __yield();
> + *counter = 9;
> + __yield();
> + return 0;
> +}