On Wed, Jul 10, 2019 at 07:55:42PM +0100, Sudakshina Das wrote: > Hi > > This patch enables the new Transactional Memory Extension announced > recently as part of Arm's new architecture technologies. > We introduce a new optional extension "tme" to enable this. The > following instructions are part of the extension: > * tstart <Xt> > * ttest <Xt> > * tcommit > * tcancel #<imm> > The documentation for the above can be found here: > https://developer.arm.com/docs/ddi0602/latest/base-instructions-alphabetic-order > > We have also added ACLE intrinsics for the instructions above according to: > https://developer.arm.com/docs/101028/latest/transactional-memory-extension-tme-intrinsics > > Builds and regression tested on aarch64-none-linux-gnu and added new > tests for the new instructions. > > Is this okay for trunk?
This looks good to me. OK for trunk. Thanks, James > > Thanks > Sudi > > *** gcc/ChangeLog *** > > 2019-xx-xx Sudakshina Das <sudi....@arm.com> > > * config/aarch64/aarch64-builtins.c (enum aarch64_builtins): Add > AARCH64_TME_BUILTIN_TSTART, AARCH64_TME_BUILTIN_TCOMMIT, > AARCH64_TME_BUILTIN_TTEST and AARCH64_TME_BUILTIN_TCANCEL. > (aarch64_init_tme_builtins): New. > (aarch64_init_builtins): Call aarch64_init_tme_builtins. > (aarch64_expand_builtin_tme): New. > (aarch64_expand_builtin): Handle TME builtins. > * config/aarch64/aarch64-c.c (aarch64_update_cpp_builtins): Define > __ARM_FEATURE_TME when enabled. > * config/aarch64/aarch64-option-extensions.def: Add "tme". > * config/aarch64/aarch64.h (AARCH64_FL_TME, AARCH64_ISA_TME): New. > (TARGET_TME): New. > * config/aarch64/aarch64.md (define_c_enum "unspec"): Add UNSPEC_TTEST. > (define_c_enum "unspecv"): Add UNSPECV_TSTART, UNSPECV_TCOMMIT and > UNSPECV_TCANCEL. > (tstart, ttest, tcommit, tcancel): New instructions. > * config/aarch64/arm_acle.h (__tstart, __tcommit): New. > (__tcancel, __ttest): New. > (_TMFAILURE_REASON, _TMFAILURE_RTRY, _TMFAILURE_CNCL): New macro. > (_TMFAILURE_MEM, _TMFAILURE_IMP, _TMFAILURE_ERR): Likewise. > (_TMFAILURE_SIZE, _TMFAILURE_NEST, _TMFAILURE_DBG): Likewise. > (_TMFAILURE_INT, _TMFAILURE_TRIVIAL): Likewise. > * config/arm/types.md: Add new tme type attr. > * doc/invoke.texi: Document "tme". > > *** gcc/testsuite/ChangeLog *** > > 2019-xx-xx Sudakshina Das <sudi....@arm.com> > > * gcc.target/aarch64/acle/tme.c: New test. > * gcc.target/aarch64/pragma_cpp_predefs_2.c: New test. > diff --git a/gcc/config/aarch64/aarch64-builtins.c > b/gcc/config/aarch64/aarch64-builtins.c > index > 549a6c249243372eacb5d29923b5d1abce4ac79a..16c1d42ea2be0f477692be592e30ba8ce27f05a7 > 100644 > --- a/gcc/config/aarch64/aarch64-builtins.c > +++ b/gcc/config/aarch64/aarch64-builtins.c > @@ -438,6 +438,11 @@ enum aarch64_builtins > /* Special cased Armv8.3-A Complex FMA by Lane quad Builtins. */ > AARCH64_SIMD_FCMLA_LANEQ_BUILTIN_BASE, > AARCH64_SIMD_FCMLA_LANEQ_BUILTINS > + /* TME builtins. */ > + AARCH64_TME_BUILTIN_TSTART, > + AARCH64_TME_BUILTIN_TCOMMIT, > + AARCH64_TME_BUILTIN_TTEST, > + AARCH64_TME_BUILTIN_TCANCEL, > AARCH64_BUILTIN_MAX > }; > > @@ -1067,6 +1072,35 @@ aarch64_init_pauth_hint_builtins (void) > NULL_TREE); > } > > +/* Initialize the transactional memory extension (TME) builtins. */ > +static void > +aarch64_init_tme_builtins (void) > +{ > + tree ftype_uint64_void > + = build_function_type_list (uint64_type_node, NULL); > + tree ftype_void_void > + = build_function_type_list (void_type_node, NULL); > + tree ftype_void_uint64 > + = build_function_type_list (void_type_node, uint64_type_node, NULL); > + > + aarch64_builtin_decls[AARCH64_TME_BUILTIN_TSTART] > + = add_builtin_function ("__builtin_aarch64_tstart", ftype_uint64_void, > + AARCH64_TME_BUILTIN_TSTART, BUILT_IN_MD, > + NULL, NULL_TREE); > + aarch64_builtin_decls[AARCH64_TME_BUILTIN_TTEST] > + = add_builtin_function ("__builtin_aarch64_ttest", ftype_uint64_void, > + AARCH64_TME_BUILTIN_TTEST, BUILT_IN_MD, > + NULL, NULL_TREE); > + aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCOMMIT] > + = add_builtin_function ("__builtin_aarch64_tcommit", ftype_void_void, > + AARCH64_TME_BUILTIN_TCOMMIT, BUILT_IN_MD, > + NULL, NULL_TREE); > + aarch64_builtin_decls[AARCH64_TME_BUILTIN_TCANCEL] > + = add_builtin_function ("__builtin_aarch64_tcancel", ftype_void_uint64, > + AARCH64_TME_BUILTIN_TCANCEL, BUILT_IN_MD, > + NULL, NULL_TREE); > +} > + > void > aarch64_init_builtins (void) > { > @@ -1104,6 +1138,9 @@ aarch64_init_builtins (void) > register them. */ > if (!TARGET_ILP32) > aarch64_init_pauth_hint_builtins (); > + > + if (TARGET_TME) > + aarch64_init_tme_builtins (); > } > > tree > @@ -1507,6 +1544,47 @@ aarch64_expand_fcmla_builtin (tree exp, rtx target, > int fcode) > return target; > } > > +/* Function to expand an expression EXP which calls one of the Transactional > + Memory Extension (TME) builtins FCODE with the result going to TARGET. */ > +static rtx > +aarch64_expand_builtin_tme (int fcode, tree exp, rtx target) > +{ > + switch (fcode) > + { > + case AARCH64_TME_BUILTIN_TSTART: > + target = gen_reg_rtx (DImode); > + emit_insn (GEN_FCN (CODE_FOR_tstart) (target)); > + break; > + > + case AARCH64_TME_BUILTIN_TTEST: > + target = gen_reg_rtx (DImode); > + emit_insn (GEN_FCN (CODE_FOR_ttest) (target)); > + break; > + > + case AARCH64_TME_BUILTIN_TCOMMIT: > + emit_insn (GEN_FCN (CODE_FOR_tcommit) ()); > + break; > + > + case AARCH64_TME_BUILTIN_TCANCEL: > + { > + tree arg0 = CALL_EXPR_ARG (exp, 0); > + rtx op0 = expand_normal (arg0); > + if (CONST_INT_P (op0) && UINTVAL (op0) <= 65536) > + emit_insn (GEN_FCN (CODE_FOR_tcancel) (op0)); > + else > + { > + error ("%Kargument must be a 16-bit constant immediate", exp); > + return const0_rtx; > + } > + } > + break; > + > + default : > + gcc_unreachable (); > + } > + return target; > +} > + > /* Expand an expression EXP that calls a built-in function, > with result going to TARGET if that's convenient. */ > rtx > @@ -1627,6 +1705,12 @@ aarch64_expand_builtin (tree exp, > || fcode == AARCH64_BUILTIN_RSQRT_V4SF) > return aarch64_expand_builtin_rsqrt (fcode, exp, target); > > + if (fcode == AARCH64_TME_BUILTIN_TSTART > + || fcode == AARCH64_TME_BUILTIN_TCOMMIT > + || fcode == AARCH64_TME_BUILTIN_TTEST > + || fcode == AARCH64_TME_BUILTIN_TCANCEL) > + return aarch64_expand_builtin_tme (fcode, exp, target); > + > gcc_unreachable (); > } > > diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c > index > 5af65b1d2f344842564b227a12f24ad04edd7271..e532c6cd142f64f050d7b5da8ab01e1f5ac3b909 > 100644 > --- a/gcc/config/aarch64/aarch64-c.c > +++ b/gcc/config/aarch64/aarch64-c.c > @@ -157,6 +157,8 @@ aarch64_update_cpp_builtins (cpp_reader *pfile) > aarch64_def_or_undef (TARGET_SM4, "__ARM_FEATURE_SM4", pfile); > aarch64_def_or_undef (TARGET_F16FML, "__ARM_FEATURE_FP16_FML", pfile); > > + aarch64_def_or_undef (TARGET_TME, "__ARM_FEATURE_TME", pfile); > + > /* Not for ACLE, but required to keep "float.h" correct if we switch > target between implementations that do or do not support ARMv8.2-A > 16-bit floating-point extensions. */ > diff --git a/gcc/config/aarch64/aarch64-option-extensions.def > b/gcc/config/aarch64/aarch64-option-extensions.def > index > 4b10c62d20401a66374eb68e36531d73df300af1..27ace6abe7b197b9c42b955a0eef439aae145728 > 100644 > --- a/gcc/config/aarch64/aarch64-option-extensions.def > +++ b/gcc/config/aarch64/aarch64-option-extensions.def > @@ -158,4 +158,7 @@ AARCH64_OPT_EXTENSION("sve2-sha3", AARCH64_FL_SVE2_SHA3, > AARCH64_FL_SHA3 | AARCH > Disabling "bitperm" just disables "bitperm". */ > AARCH64_OPT_EXTENSION("bitperm", AARCH64_FL_SVE2_BITPERM, AARCH64_FL_SIMD | > AARCH64_FL_F16 | AARCH64_FL_FP | AARCH64_FL_SVE | AARCH64_FL_SVE2, 0, false, > "") > > +/* Enabling or disabling "tme" only changes "tme". */ > +AARCH64_OPT_EXTENSION("tme", AARCH64_FL_TME, 0, 0, false, "") > + > #undef AARCH64_OPT_EXTENSION > diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h > index > 92e38a87a768fe54d3f02beecb919d97223474d9..34fca9003ccba20f1cb11e35ca2676f81a7251db > 100644 > --- a/gcc/config/aarch64/aarch64.h > +++ b/gcc/config/aarch64/aarch64.h > @@ -199,6 +199,9 @@ extern unsigned aarch64_architecture_version; > #define AARCH64_FL_SVE2_SHA3 (1ULL << 31) > #define AARCH64_FL_SVE2_BITPERM (1ULL << 32) > > +/* Transactional Memory Extension. */ > +#define AARCH64_FL_TME (1ULL << 33) /* Has TME instructions. */ > + > /* Has FP and SIMD. */ > #define AARCH64_FL_FPSIMD (AARCH64_FL_FP | AARCH64_FL_SIMD) > > @@ -243,6 +246,7 @@ extern unsigned aarch64_architecture_version; > #define AARCH64_ISA_F16FML (aarch64_isa_flags & AARCH64_FL_F16FML) > #define AARCH64_ISA_RCPC8_4 (aarch64_isa_flags & AARCH64_FL_RCPC8_4) > #define AARCH64_ISA_V8_5 (aarch64_isa_flags & AARCH64_FL_V8_5) > +#define AARCH64_ISA_TME (aarch64_isa_flags & AARCH64_FL_TME) > > /* Crypto is an optional extension to AdvSIMD. */ > #define TARGET_CRYPTO (TARGET_SIMD && AARCH64_ISA_CRYPTO) > @@ -287,6 +291,9 @@ extern unsigned aarch64_architecture_version; > /* Armv8.3-a Complex number extension to AdvSIMD extensions. */ > #define TARGET_COMPLEX (TARGET_SIMD && TARGET_ARMV8_3) > > +/* TME instructions are enabled. */ > +#define TARGET_TME (AARCH64_ISA_TME) > + > /* Make sure this is always defined so we don't have to check for ifdefs > but rather use normal ifs. */ > #ifndef TARGET_FIX_ERR_A53_835769_DEFAULT > diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md > index > 7026b3a3b92be94cb916dfcc1d45930dff93177b..7baa662c69cc48b4750867799e1249af43790b18 > 100644 > --- a/gcc/config/aarch64/aarch64.md > +++ b/gcc/config/aarch64/aarch64.md > @@ -235,6 +235,7 @@ > UNSPEC_REV_SUBREG > UNSPEC_SPECULATION_TRACKER > UNSPEC_COPYSIGN > + UNSPEC_TTEST ; Represent transaction test. > ]) > > (define_c_enum "unspecv" [ > @@ -250,6 +251,9 @@ > UNSPECV_BTI_C ; Represent BTI c. > UNSPECV_BTI_J ; Represent BTI j. > UNSPECV_BTI_JC ; Represent BTI jc. > + UNSPECV_TSTART ; Represent transaction start. > + UNSPECV_TCOMMIT ; Represent transaction commit. > + UNSPECV_TCANCEL ; Represent transaction cancel. > ] > ) > > @@ -7237,6 +7241,43 @@ > (set_attr "speculation_barrier" "true")] > ) > > +;; Transactional Memory Extension (TME) instructions. > + > +(define_insn "tstart" > + [(set (match_operand:DI 0 "register_operand" "=r") > + (unspec_volatile:DI [(const_int 0)] UNSPECV_TSTART)) > + (clobber (mem:BLK (scratch)))] > + "TARGET_TME" > + "tstart\\t%0" > + [(set_attr "type" "tme")] > +) > + > +(define_insn "ttest" > + [(set (match_operand:DI 0 "register_operand" "=r") > + (unspec_volatile:DI [(const_int 0)] UNSPEC_TTEST)) > + (clobber (mem:BLK (scratch)))] > + "TARGET_TME" > + "ttest\\t%0" > + [(set_attr "type" "tme")] > +) > + > +(define_insn "tcommit" > + [(unspec_volatile:BLK [(const_int 0)] UNSPECV_TCOMMIT) > + (clobber (mem:BLK (scratch)))] > + "TARGET_TME" > + "tcommit" > + [(set_attr "type" "tme")] > +) > + > +(define_insn "tcancel" > + [(unspec_volatile:BLK > + [(match_operand 0 "const_int_operand" "n")] UNSPECV_TCANCEL) > + (clobber (mem:BLK (scratch)))] > + "TARGET_TME && (UINTVAL (operands[0]) <= 65535)" > + "tcancel\\t#%0" > + [(set_attr "type" "tme")] > +) > + > ;; AdvSIMD Stuff > (include "aarch64-simd.md") > > diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h > index > 534a989c39af1db6ada37a703e8b98300941e094..d4de691eec5e45d7aa6b1f904ec0765916015c6f > 100644 > --- a/gcc/config/aarch64/arm_acle.h > +++ b/gcc/config/aarch64/arm_acle.h > @@ -29,14 +29,14 @@ > > #include <stdint.h> > > -#pragma GCC push_options > - > -#pragma GCC target ("+nothing+crc") > - > #ifdef __cplusplus > extern "C" { > #endif > > +#pragma GCC push_options > + > +#pragma GCC target ("+nothing+crc") > + > __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) > __crc32b (uint32_t __a, uint8_t __b) > { > @@ -85,10 +85,53 @@ __crc32d (uint32_t __a, uint64_t __b) > return __builtin_aarch64_crc32x (__a, __b); > } > > -#ifdef __cplusplus > +#pragma GCC pop_options > + > +#ifdef __ARM_FEATURE_TME > +#pragma GCC push_options > +#pragma GCC target ("+nothing+tme") > + > +#define _TMFAILURE_REASON 0x00007fffu > +#define _TMFAILURE_RTRY 0x00008000u > +#define _TMFAILURE_CNCL 0x00010000u > +#define _TMFAILURE_MEM 0x00020000u > +#define _TMFAILURE_IMP 0x00040000u > +#define _TMFAILURE_ERR 0x00080000u > +#define _TMFAILURE_SIZE 0x00100000u > +#define _TMFAILURE_NEST 0x00200000u > +#define _TMFAILURE_DBG 0x00400000u > +#define _TMFAILURE_INT 0x00800000u > +#define _TMFAILURE_TRIVIAL 0x01000000u > + > +__extension__ static __inline uint64_t __attribute__ ((__always_inline__)) > +__tstart (void) > +{ > + return __builtin_aarch64_tstart (); > +} > + > +__extension__ static __inline void __attribute__ ((__always_inline__)) > +__tcommit (void) > +{ > + __builtin_aarch64_tcommit (); > +} > + > +__extension__ static __inline void __attribute__ ((__always_inline__)) > +__tcancel (const uint64_t __reason) > +{ > + __builtin_aarch64_tcancel (__reason); > +} > + > +__extension__ static __inline uint64_t __attribute__ ((__always_inline__)) > +__ttest (void) > +{ > + return __builtin_aarch64_ttest (); > } > -#endif > > #pragma GCC pop_options > +#endif > + > +#ifdef __cplusplus > +} > +#endif > > #endif > diff --git a/gcc/config/arm/types.md b/gcc/config/arm/types.md > index > f8f8dd09077a5c9d3691c95c6676ee36114786e4..03d6b67c30d514b0ba09554d52fed24b9bd91e88 > 100644 > --- a/gcc/config/arm/types.md > +++ b/gcc/config/arm/types.md > @@ -546,6 +546,10 @@ > ; The classification below is for coprocessor instructions > ; > ; coproc > +; > +; The classification below is for TME instructions > +; > +; tme > > (define_attr "type" > "adc_imm,\ > @@ -1091,7 +1095,8 @@ > crypto_sha3,\ > crypto_sm3,\ > crypto_sm4,\ > - coproc" > + coproc,\ > + tme" > (const_string "untyped")) > > ; Is this an (integer side) multiply with a 32-bit (or smaller) result? > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > index > 6382a840281ff3cbc7e45016b2e4f7a38b265068..9458ad10f2e0e73a54c146dc678f3dd84fd96a67 > 100644 > --- a/gcc/doc/invoke.texi > +++ b/gcc/doc/invoke.texi > @@ -16075,6 +16075,8 @@ Enable SVE2 aes instructions. This also enables SVE2 > instructions. > @item sve2-sha3 > Enable SVE2 sha3 instructions. This also enables SVE2 instructions. > @option{-march=armv8.5-a}. > +@item tme > +Enable the Transactional Memory Extension. > > @end table > > diff --git a/gcc/testsuite/gcc.target/aarch64/acle/tme.c > b/gcc/testsuite/gcc.target/aarch64/acle/tme.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..5df93b1dcb101a01a864b6b81ed9ed7ee297dd69 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/acle/tme.c > @@ -0,0 +1,34 @@ > +/* Test the TME intrinsics. */ > + > +/* { dg-do compile } */ > +/* { dg-options "-save-temps -O2 -march=armv8-a+tme" } */ > + > +#include "arm_acle.h" > + > +#define tcancel_reason 0x234 > + > +unsigned > +check_tme (void) > +{ > + unsigned status = __tstart (); > + if (status == 0) > + { > + if (__ttest () == 2) > + { > + __tcancel (tcancel_reason & _TMFAILURE_REASON); > + return tcancel_reason; > + } > + > + __tcommit (); > + return 0; > + } > + else if (status & _TMFAILURE_NEST) > + return _TMFAILURE_NEST; > + else if (status & _TMFAILURE_TRIVIAL) > + return _TMFAILURE_TRIVIAL; > +} > + > +/* { dg-final { scan-assembler "tstart\tx..?\n" } } */ > +/* { dg-final { scan-assembler "tcancel\t#564\n" } } */ > +/* { dg-final { scan-assembler "ttest\tx..?\n" } } */ > +/* { dg-final { scan-assembler "tcommit\n" } } */ > diff --git a/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c > b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c > new file mode 100644 > index > 0000000000000000000000000000000000000000..608b89d19ce54851cb6abad227c32b081ca03dab > --- /dev/null > +++ b/gcc/testsuite/gcc.target/aarch64/pragma_cpp_predefs_2.c > @@ -0,0 +1,20 @@ > +/* { dg-do compile } */ > +/* { dg-options "-O2" } */ > + > +#pragma GCC push_options > +#pragma GCC target ("arch=armv8-a+tme") > +#ifndef __ARM_FEATURE_TME > +#error "__ARM_FEATURE_TME is not defined but should be!" > +#endif > + > +#pragma GCC pop_options > + > +#ifdef __ARM_FEATURE_TME > +#error "__ARM_FEATURE_TME is defined but should not be!" > +#endif > + > +int > +foo (int a) > +{ > + return a; > +}