diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index 8cced94567008e28b1761ec8771589a3925f2904..d5424f98df1f5c8f206cbded097bdd2dfcd1ca8e 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -399,6 +399,13 @@ enum aarch64_builtins AARCH64_PAUTH_BUILTIN_AUTIA1716, AARCH64_PAUTH_BUILTIN_PACIA1716, AARCH64_PAUTH_BUILTIN_XPACLRI, + /* System Hint Operation Builtins for AArch64. */ + AARCH64_SYSHINTOP_BUILTIN_NOP, + AARCH64_SYSHINTOP_BUILTIN_YIELD, + AARCH64_SYSHINTOP_BUILTIN_WFE, + AARCH64_SYSHINTOP_BUILTIN_WFI, + AARCH64_SYSHINTOP_BUILTIN_SEV, + AARCH64_SYSHINTOP_BUILTIN_SEVL, AARCH64_BUILTIN_MAX }; @@ -977,6 +984,39 @@ aarch64_init_pauth_hint_builtins (void) NULL_TREE); } +/* System Hint Operation builtins for AArch64. */ +void +aarch64_init_syshintop_builtins (void) +{ + tree vtype_node + = build_function_type_list (void_type_node, NULL); + + aarch64_builtin_decls[AARCH64_SYSHINTOP_BUILTIN_NOP] + = add_builtin_function ("__builtin_aarch64_nop", vtype_node, + AARCH64_SYSHINTOP_BUILTIN_NOP, BUILT_IN_MD, NULL, + NULL_TREE); + aarch64_builtin_decls[AARCH64_SYSHINTOP_BUILTIN_YIELD] + = add_builtin_function ("__builtin_aarch64_yield", vtype_node, + AARCH64_SYSHINTOP_BUILTIN_YIELD, BUILT_IN_MD, NULL, + NULL_TREE); + aarch64_builtin_decls[AARCH64_SYSHINTOP_BUILTIN_WFE] + = add_builtin_function ("__builtin_aarch64_wfe", vtype_node, + AARCH64_SYSHINTOP_BUILTIN_WFE, BUILT_IN_MD, NULL, + NULL_TREE); + aarch64_builtin_decls[AARCH64_SYSHINTOP_BUILTIN_WFI] + = add_builtin_function ("__builtin_aarch64_wfi", vtype_node, + AARCH64_SYSHINTOP_BUILTIN_WFI, BUILT_IN_MD, NULL, + NULL_TREE); + aarch64_builtin_decls[AARCH64_SYSHINTOP_BUILTIN_SEV] + = add_builtin_function ("__builtin_aarch64_sev", vtype_node, + AARCH64_SYSHINTOP_BUILTIN_SEV, BUILT_IN_MD, NULL, + NULL_TREE); + aarch64_builtin_decls[AARCH64_SYSHINTOP_BUILTIN_SEVL] + = add_builtin_function ("__builtin_aarch64_sevl", vtype_node, + AARCH64_SYSHINTOP_BUILTIN_SEVL, BUILT_IN_MD, NULL, + NULL_TREE); +} + void aarch64_init_builtins (void) { @@ -1014,6 +1054,7 @@ aarch64_init_builtins (void) register them. */ if (!TARGET_ILP32) aarch64_init_pauth_hint_builtins (); + aarch64_init_syshintop_builtins (); } tree @@ -1395,6 +1436,29 @@ aarch64_expand_builtin (tree exp, } return target; + case AARCH64_SYSHINTOP_BUILTIN_NOP: + emit_insn (GEN_FCN (CODE_FOR_nop) ()); + return gen_reg_rtx (VOIDmode); + + case AARCH64_SYSHINTOP_BUILTIN_YIELD: + emit_insn (GEN_FCN (CODE_FOR_yield) ()); + return gen_reg_rtx (VOIDmode); + + case AARCH64_SYSHINTOP_BUILTIN_WFE: + emit_insn (GEN_FCN (CODE_FOR_wfe) ()); + return gen_reg_rtx (VOIDmode); + + case AARCH64_SYSHINTOP_BUILTIN_WFI: + emit_insn (GEN_FCN (CODE_FOR_wfi) ()); + return gen_reg_rtx (VOIDmode); + + case AARCH64_SYSHINTOP_BUILTIN_SEV: + emit_insn (GEN_FCN (CODE_FOR_sev) ()); + return gen_reg_rtx (VOIDmode); + + case AARCH64_SYSHINTOP_BUILTIN_SEVL: + emit_insn (GEN_FCN (CODE_FOR_sevl) ()); + return gen_reg_rtx (VOIDmode); } if (fcode >= AARCH64_SIMD_BUILTIN_BASE && fcode <= AARCH64_SIMD_BUILTIN_MAX) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 82af4d47f78c65880f5eec78add5a69110db7711..9b9819f9877303db7d21bcb840ab583abef14c28 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -233,6 +233,11 @@ 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 ] ) @@ -634,12 +639,47 @@ ) (define_insn "nop" - [(unspec[(const_int 0)] UNSPEC_NOP)] + [(unspec [(const_int 0)] UNSPEC_NOP)] "" "nop" [(set_attr "type" "no_insn")] ) +(define_insn "yield" + [(unspec_volatile [(const_int 0)] UNSPECV_YIELD)] + "" + "yield" + [(set_attr "type" "coproc")] +) + +(define_insn "wfe" + [(unspec_volatile [(const_int 0)] UNSPECV_WFE)] + "" + "wfe" + [(set_attr "type" "coproc")] +) + +(define_insn "wfi" + [(unspec_volatile [(const_int 0)] UNSPECV_WFI)] + "" + "wfi" + [(set_attr "type" "coproc")] +) + +(define_insn "sev" + [(unspec_volatile [(const_int 0)] UNSPECV_SEV)] + "" + "sev" + [(set_attr "type" "coproc")] +) + +(define_insn "sevl" + [(unspec_volatile [(const_int 0)] UNSPECV_SEVL)] + "" + "sevl" + [(set_attr "type" "coproc")] +) + (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 8504c3f1d7647e9217751a5bf354a884224bc1f1..326f33dfb342657156a962f502355c77714e2b5e 100644 --- a/gcc/config/aarch64/arm_acle.h +++ b/gcc/config/aarch64/arm_acle.h @@ -90,5 +90,40 @@ __crc32d (uint32_t __a, uint64_t __b) #endif #pragma GCC pop_options +__extension__ static __inline void __attribute__ ((__always_inline__)) +__nop (void) +{ + __builtin_aarch64_nop (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__yield (void) +{ + __builtin_aarch64_yield (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__sev (void) +{ + __builtin_aarch64_sev (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__sevl (void) +{ + __builtin_aarch64_sevl (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__wfi (void) +{ + __builtin_aarch64_wfi (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__wfe (void) +{ + __builtin_aarch64_wfe (); +} #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 0000000000000000000000000000000000000000..8930f1dbe5afb74036ecf34b182338ed81e5323c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/hint-1.c @@ -0,0 +1,14 @@ +/* Test the nop ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-additional-options "-O0" } */ +/* { dg-options "-march=armv8-a" } */ + +#include "arm_acle.h" + +void +test_hint (void) +{ + __nop (); +} + +/* { dg-final { scan-assembler-times "\tnop" 3 } } */ 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 0000000000000000000000000000000000000000..5b5449ee16ee121ac1799503610c57ab931d42a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/acle/hint-2.c @@ -0,0 +1,53 @@ +/* Test the yield ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-options "-march=armv8-a" } */ + +#include "arm_acle.h" + +void +test_hint1 (void) +{ + __yield (); +} + +/* { dg-final {scan-assembler "yield" } } */ + +/* Test the yield ACLE hint intrinsic */ + +void +test_hint2 (void) +{ + __wfe (); +} + +/* { dg-final {scan-assembler "wfe" } } */ + +/* Test the wfi ACLE hint intrinsic */ + +void +test_hint3 (void) +{ +__wfi (); +} + +/* { dg-final {scan-assembler "wfi" } } */ + +/* Test the sev ACLE hint intrinsic */ + +void +test_hint4 (void) +{ +__sev (); +} + +/* { dg-final {scan-assembler "sev" } } */ + +/* Test the sevl ACLE hint intrinsic */ + +void +test_hint5 (void) +{ +__sevl (); +} + +/* { dg-final {scan-assembler "sevl" } } */