Hi All, This patch implements the ACLE hint intrinsics (nop,yield,wfe,wfi,sev and sevl), for all ARM targets.
The intrinsics specification will be published on the Arm website [1]. [1] http://infocenter.arm.com/help/topic/com.arm.doc.ihi0053c/IHI0053C_acle_2_0.pdf Bootstrapped on arm-none-linux-gnueabihf, regression tested on arm-none-eabi with no regressions and ran the added tests for arm, thumb-1 and thumb-2 modes. Ok for trunk? If ok, could someone commit the patch on my behalf, I don't have commit rights. Thanks, Srinath gcc/ChangeLog: 2019-01-10 Srinath Parvathaneni <srinath.parvathan...@arm.com> * config/arm/arm-builtins.c (NOP_QUALIFIERS): New qualifier. (arm_expand_builtin_args): New case. * config/arm/arm.md (yield): New pattern name. (wfe): Likewise. (wfi): Likewise. (sev): Likewise. (sevl): Likewise. * config/arm/arm_acle.h (__nop ): New inline function. (__yield): Likewise. (__sev): Likewise. (__sevl): Likewise. (__wfi): Likewise. (__wfe): Likewise. * config/arm/arm_acle_builtins.def (VAR1): (nop): New builtin definitions. (yield): Likewise. (sev): Likewise. (sevl): Likewise. (wfi): Likewise. (wfe): Likewise. * config/arm/unspecs.md (unspecv): (VUNSPEC_YIELD): New volatile unspec. (VUNSPEC_SEV): Likewise. (VUNSPEC_SEVL): Likewise. (VUNSPEC_WFI): Likewise. gcc/testsuite/ChangeLog: 2019-01-10 Srinath Parvathaneni <srinath.parvathan...@arm.com> * gcc.target/arm/acle/nop.c: New test. * gcc.target/arm/acle/sev-1.c: Likewise. * gcc.target/arm/acle/sev-2.c: Likewise. * gcc.target/arm/acle/sev-3.c: Likewise. * gcc.target/arm/acle/sevl-1.c: Likewise. * gcc.target/arm/acle/sevl-2.c: Likewise. * gcc.target/arm/acle/sevl-3.c: Likewise. * gcc.target/arm/acle/wfe-1.c: Likewise. * gcc.target/arm/acle/wfe-2.c: Likewise. * gcc.target/arm/acle/wfe-3.c: Likewise. * gcc.target/arm/acle/wfi-1.c: Likewise. * gcc.target/arm/acle/wfi-2.c: Likewise. * gcc.target/arm/acle/wfi-3.c: Likewise. * gcc.target/arm/acle/yield-1.c: Likewise. * gcc.target/arm/acle/yield-2.c: Likewise. * gcc.target/arm/acle/yield-3.c: Likewise.
diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index 563ca51dcd0d63046d2bf577ca86d5f70a466bcf..2afa9649813c0f37a803db5add1139067d83a343 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -85,6 +85,12 @@ enum arm_type_qualifiers qualifier_const_void_pointer = 0x802 }; +/* The qualifier allows generation of builtins with no operands. */ +static enum arm_type_qualifiers +arm_nop_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_void }; +#define NOP_QUALIFIERS (arm_nop_qualifiers) + /* The qualifier_internal allows generation of a unary builtin from a pattern with a third pseudo-operand such as a match_scratch. T (T). */ @@ -2343,6 +2349,10 @@ constant_arg: else switch (argc) { + case 0: + pat = GEN_FCN (icode) (); + break; + case 1: pat = GEN_FCN (icode) (op[0]); break; diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index f6196e9316898e3258e08d8f2ece8fe9640676ca..36b24cfdfa6c61d952a5c704f54d37f2b0fdd34e 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -8906,6 +8906,76 @@ (set_attr "type" "mov_reg")] ) +(define_insn "yield" + [(unspec_volatile [(const_int 0)] VUNSPEC_YIELD)] + "" +{ + if (TARGET_ARM) + return ".inst\t0xe320f001\t//yield"; + else if(TARGET_THUMB2) + return ".inst\t0xf3af8001\t//yield"; + else /* TARGET_THUMB1 */ + return ".inst\t0xbf10\t//yield"; +} + [(set_attr "type" "coproc")] +) + +(define_insn "wfe" + [(unspec_volatile [(const_int 0)] VUNSPEC_WFE)] + "" +{ + if (TARGET_ARM) + return ".inst\t0xe320f002\t//wfe"; + else if(TARGET_THUMB2) + return ".inst\t0xf3af8002\t//wfe"; + else /* TARGET_THUMB1 */ + return ".inst\t0xbf20\t//wfe"; +} + [(set_attr "type" "coproc")] +) + +(define_insn "wfi" + [(unspec_volatile [(const_int 0)] VUNSPEC_WFI)] + "" +{ + if (TARGET_ARM) + return ".inst\t0xe320f003\t//wfi"; + else if(TARGET_THUMB2) + return ".inst\t0xf3af8003\t//wfi"; + else /* TARGET_THUMB1 */ + return ".inst\t0xbf30\t//wfi"; +} + [(set_attr "type" "coproc")] +) + +(define_insn "sev" + [(unspec_volatile [(const_int 0)] VUNSPEC_SEV)] + "" +{ + if (TARGET_ARM) + return ".inst\t0xe320f004\t//sev"; + else if(TARGET_THUMB2) + return ".inst\t0xf3af8004\t//sev"; + else /* TARGET_THUMB1 */ + return ".inst\t0xbf40\t//sev"; +} + [(set_attr "type" "coproc")] +) + +(define_insn "sevl" + [(unspec_volatile [(const_int 0)] VUNSPEC_SEVL)] + "" +{ + if (TARGET_ARM) + return ".inst\t0xe320f005\t//sevl"; + else if(TARGET_THUMB2) + return ".inst\t0xf3af8005\t//sevl"; + else /* TARGET_THUMB1 */ + return ".inst\t0xbf50\t//sevl"; +} + [(set_attr "type" "coproc")] +) + (define_insn "trap" [(trap_if (const_int 1) (const_int 0))] "" diff --git a/gcc/config/arm/arm_acle.h b/gcc/config/arm/arm_acle.h index c0f6ea2d1567bbbe25045c02191a11427f250ec3..1ea1d7ecf0972c0aa796bf9b6280b6a97ec9e3c7 100644 --- a/gcc/config/arm/arm_acle.h +++ b/gcc/config/arm/arm_acle.h @@ -241,5 +241,39 @@ __crc32cd (uint32_t __a, uint64_t __b) #ifdef __cplusplus } #endif +__extension__ static __inline void __attribute__ ((__always_inline__)) +__nop (void) +{ + __builtin_arm_nop (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__yield (void) +{ + __builtin_arm_yield (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__sev (void) +{ + __builtin_arm_sev (); +} +__extension__ static __inline void __attribute__ ((__always_inline__)) +__sevl (void) +{ + __builtin_arm_sevl (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__wfi (void) +{ + __builtin_arm_wfi (); +} + +__extension__ static __inline void __attribute__ ((__always_inline__)) +__wfe (void) +{ + __builtin_arm_wfe (); +} #endif diff --git a/gcc/config/arm/arm_acle_builtins.def b/gcc/config/arm/arm_acle_builtins.def index 47370ecc5ef6b606988a5e423d6d306b038d8d60..0958dbd0adac15104ed5955f828de97a6cadabc6 100644 --- a/gcc/config/arm/arm_acle_builtins.def +++ b/gcc/config/arm/arm_acle_builtins.def @@ -42,3 +42,9 @@ VAR1 (MCRR, mcrr, void) VAR1 (MCRR, mcrr2, void) VAR1 (MRRC, mrrc, di) VAR1 (MRRC, mrrc2, di) +VAR1 (NOP, nop, void) +VAR1 (NOP, yield, void) +VAR1 (NOP, wfi, void) +VAR1 (NOP, wfe, void) +VAR1 (NOP, sev, void) +VAR1 (NOP, sevl, void) diff --git a/gcc/config/arm/unspecs.md b/gcc/config/arm/unspecs.md index 8f9dbcb08dc2547375e2d5195fe5dbb4098aa29a..b1b99c863684a87134c44ce18bb33cd51ed32cfb 100644 --- a/gcc/config/arm/unspecs.md +++ b/gcc/config/arm/unspecs.md @@ -172,6 +172,11 @@ VUNSPEC_MRRC ; Represent the coprocessor mrrc instruction. VUNSPEC_MRRC2 ; Represent the coprocessor mrrc2 instruction. VUNSPEC_SPECULATION_BARRIER ; Represents an unconditional speculation barrier. + VUNSPEC_YIELD ; Used by the intrinsic form of the YIELD instruction. + VUNSPEC_SEV ; Used by the intrinsic form of the SEV instruction. + VUNSPEC_SEVL ; Used by the intrinsic form of the SEVL instruction. + VUNSPEC_WFI ; Used by the intrinsic form of the WFI instruction. + VUNSPEC_WFE ; Used by the intrinsic form of the WFE instruction. ]) ;; Enumerators for NEON unspecs. diff --git a/gcc/testsuite/gcc.target/arm/acle/nop.c b/gcc/testsuite/gcc.target/arm/acle/nop.c new file mode 100644 index 0000000000000000000000000000000000000000..ce555bf56cc6d26511bbcce14ad21b24c1d37f50 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/nop.c @@ -0,0 +1,13 @@ +/* Test the nop ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-additional-options "-O0" } */ + +#include "arm_acle.h" + +void +test_hint (void) +{ + __nop (); +} + +/* { dg-final {scan-assembler-times "\tnop" 3 } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/sev-1.c b/gcc/testsuite/gcc.target/arm/acle/sev-1.c new file mode 100644 index 0000000000000000000000000000000000000000..02780caf0bde37995f0dfb1dad58929276df4cd4 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/sev-1.c @@ -0,0 +1,14 @@ +/* Test the sev ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-options "-marm" } */ + +#include "arm_acle.h" + +void +test_sev (void) +{ + __sev (); +} + +/* { dg-final {scan-assembler ".inst\t0xe320f004\t\/\/sev" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/sev-2.c b/gcc/testsuite/gcc.target/arm/acle/sev-2.c new file mode 100644 index 0000000000000000000000000000000000000000..63ee21c305dd7f58dc63ab03c715ddbd4a63da1e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/sev-2.c @@ -0,0 +1,14 @@ +/* Test the sev ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_sev (void) +{ + __sev (); +} + +/* { dg-final {scan-assembler ".inst\t0xbf40\t\/\/sev" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/sev-3.c b/gcc/testsuite/gcc.target/arm/acle/sev-3.c new file mode 100644 index 0000000000000000000000000000000000000000..85382fda0800b507526d7d47ae2508bbde99222e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/sev-3.c @@ -0,0 +1,14 @@ +/* Test the sev ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_sev (void) +{ + __sev (); +} + +/* { dg-final {scan-assembler ".inst\t0xf3af8004\t\/\/sev" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/sevl-1.c b/gcc/testsuite/gcc.target/arm/acle/sevl-1.c new file mode 100644 index 0000000000000000000000000000000000000000..75e176001f8cd6f9baa2fce764cc54c3d118c9d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/sevl-1.c @@ -0,0 +1,14 @@ +/* Test the sevl ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-options "-marm" } */ + +#include "arm_acle.h" + +void +test_sevl (void) +{ + __sevl (); +} + +/* { dg-final {scan-assembler ".inst\t0xe320f005\t\/\/sevl" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/sevl-2.c b/gcc/testsuite/gcc.target/arm/acle/sevl-2.c new file mode 100644 index 0000000000000000000000000000000000000000..acd3c96f5a28241fe322f132b910fa4043c93771 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/sevl-2.c @@ -0,0 +1,14 @@ +/* Test the sevl ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_sevl (void) +{ + __sevl (); +} + +/* { dg-final {scan-assembler ".inst\t0xbf50\t\/\/sevl" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/sevl-3.c b/gcc/testsuite/gcc.target/arm/acle/sevl-3.c new file mode 100644 index 0000000000000000000000000000000000000000..cc86213313a1140f870041862ea6d0a7f5b6be51 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/sevl-3.c @@ -0,0 +1,14 @@ +/* Test the sevl ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_sevl (void) +{ + __sevl (); +} + +/* { dg-final {scan-assembler ".inst\t0xf3af8005\t\/\/sevl" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/wfe-1.c b/gcc/testsuite/gcc.target/arm/acle/wfe-1.c new file mode 100644 index 0000000000000000000000000000000000000000..e806ed553e51d76aa1f42ec1aead4a05b1c46b8d --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/wfe-1.c @@ -0,0 +1,14 @@ +/* Test the wfe ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-options "-marm" } */ + +#include "arm_acle.h" + +void +test_wfe (void) +{ + __wfe (); +} + +/* { dg-final {scan-assembler ".inst\t0xe320f002\t\/\/wfe" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/wfe-2.c b/gcc/testsuite/gcc.target/arm/acle/wfe-2.c new file mode 100644 index 0000000000000000000000000000000000000000..7ebf5c2b9076bed5ab9b8a4252bc1634028248ce --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/wfe-2.c @@ -0,0 +1,14 @@ +/* Test the wfe ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_wfe (void) +{ + __wfe (); +} + +/* { dg-final {scan-assembler ".inst\t0xbf20\t\/\/wfe" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/wfe-3.c b/gcc/testsuite/gcc.target/arm/acle/wfe-3.c new file mode 100644 index 0000000000000000000000000000000000000000..248fac29885a866ee809c44a362e0ced3f9a73ff --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/wfe-3.c @@ -0,0 +1,14 @@ +/* Test the wfe ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_wfe (void) +{ + __wfe (); +} + +/* { dg-final {scan-assembler ".inst\t0xf3af8002\t\/\/wfe" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/wfi-1.c b/gcc/testsuite/gcc.target/arm/acle/wfi-1.c new file mode 100644 index 0000000000000000000000000000000000000000..cfaabed6dbbd00d212f66c7934ab1ab7734a7e92 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/wfi-1.c @@ -0,0 +1,14 @@ +/* Test the wfi ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-options "-marm" } */ + +#include "arm_acle.h" + +void +test_wfi (void) +{ + __wfi (); +} + +/* { dg-final {scan-assembler ".inst\t0xe320f003\t\/\/wfi" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/wfi-2.c b/gcc/testsuite/gcc.target/arm/acle/wfi-2.c new file mode 100644 index 0000000000000000000000000000000000000000..a66a11ada9240a162a974542a53ec7b22c01c297 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/wfi-2.c @@ -0,0 +1,14 @@ +/* Test the wfi ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_wfi (void) +{ + __wfi (); +} + +/* { dg-final {scan-assembler ".inst\t0xbf30\t\/\/wfi" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/wfi-3.c b/gcc/testsuite/gcc.target/arm/acle/wfi-3.c new file mode 100644 index 0000000000000000000000000000000000000000..40adfc4b0c30015ce8caaab31c3e743b883a3aa2 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/wfi-3.c @@ -0,0 +1,14 @@ +/* Test the wfi ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_wfi (void) +{ + __wfi (); +} + +/* { dg-final {scan-assembler ".inst\t0xf3af8003\t\/\/wfi" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/yield-1.c b/gcc/testsuite/gcc.target/arm/acle/yield-1.c new file mode 100644 index 0000000000000000000000000000000000000000..e46a35b0e2123d9d86130f639ab56d73256d6c3d --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/yield-1.c @@ -0,0 +1,14 @@ +/* Test the yield ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arm_ok } */ +/* { dg-options "-marm" } */ + +#include "arm_acle.h" + +void +test_yield (void) +{ + __yield (); +} + +/* { dg-final {scan-assembler ".inst\t0xe320f001\t\/\/yield" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/yield-2.c b/gcc/testsuite/gcc.target/arm/acle/yield-2.c new file mode 100644 index 0000000000000000000000000000000000000000..5ef53d6ed8687e8e15cff505c96de2fbdacc3005 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/yield-2.c @@ -0,0 +1,14 @@ +/* Test the yield ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_yield (void) +{ + __yield (); +} + +/* { dg-final {scan-assembler ".inst\t0xbf10\t\/\/yield" } } */ diff --git a/gcc/testsuite/gcc.target/arm/acle/yield-3.c b/gcc/testsuite/gcc.target/arm/acle/yield-3.c new file mode 100644 index 0000000000000000000000000000000000000000..7d8a2cca097f647be7263af2613b0e507fbd84cd --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/acle/yield-3.c @@ -0,0 +1,14 @@ +/* Test the yield ACLE hint intrinsic */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-additional-options "-mthumb" } */ + +#include "arm_acle.h" + +void +test_yield (void) +{ + __yield (); +} + +/* { dg-final {scan-assembler ".inst\t0xf3af8001\t\/\/yield" } } */