[AArch64] Enable Transactional Memory Extension

Message ID 220d05bf-eccc-e12e-91c0-192accd72bf9@arm.com
State New
Headers show
Series
  • [AArch64] Enable Transactional Memory Extension
Related show

Commit Message

Sudakshina Das July 10, 2019, 6:55 p.m.
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?

Thanks
Sudi

*** gcc/ChangeLog ***

2019-xx-xx  Sudakshina Das  <sudi.das@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.das@arm.com>

	* gcc.target/aarch64/acle/tme.c: New test.
	* gcc.target/aarch64/pragma_cpp_predefs_2.c: New test.

Comments

James Greenhalgh July 22, 2019, 5:20 p.m. | #1
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.das@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.das@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;

> +}

Patch

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;
+}