From cca8d9e5be2ffffd6ef7276234e1097763b15e19 Mon Sep 17 00:00:00 2001 From: Kyrylo Tkachov Date: Tue, 13 Jun 2023 10:17:24 +0100 Subject: [PATCH] arm: Extend -mtp= arguments After discussing the -mtp= option with Arm's LLVM developers we'd like to extend the functionality of the option somewhat. There are actually 3 system registers that can be accessed for the thread pointer in aarch32: tpidrurw, tpidruro, tpidrprw. They are all read through the CP15 co-processor mechanism. The current -mtp=cp15 option reads the tpidruro register. This patch extends -mtp to allow for the above three explicit tpidr names and keeps -mtp=cp15 as an alias of -mtp=tpidruro for backwards compatibility. Bootstrapped and tested on arm-none-linux-gnueabihf. gcc/ChangeLog: * config/arm/arm-opts.h (enum arm_tp_type): Remove TP_CP15. Add TP_TPIDRURW, TP_TPIDRURO, TP_TPIDRPRW values. * config/arm/arm-protos.h (arm_output_load_tpidr): Declare prototype. * config/arm/arm.cc (arm_option_reconfigure_globals): Replace TP_CP15 with TP_TPIDRURO. (arm_output_load_tpidr): Define. * config/arm/arm.h (TARGET_HARD_TP): Define in terms of TARGET_SOFT_TP. * config/arm/arm.md (load_tp_hard): Call arm_output_load_tpidr to output assembly. (reload_tp_hard): Likewise. * config/arm/arm.opt (tpidrurw, tpidruro, tpidrprw): New values for arm_tp_type. * doc/invoke.texi (Arm Options, mtp): Document new values. gcc/testsuite/ChangeLog: * gcc.target/arm/mtp.c: New test. * gcc.target/arm/mtp_1.c: New test. * gcc.target/arm/mtp_2.c: New test. * gcc.target/arm/mtp_3.c: New test. * gcc.target/arm/mtp_4.c: New test. --- gcc/config/arm/arm-opts.h | 4 +++- gcc/config/arm/arm-protos.h | 1 + gcc/config/arm/arm.cc | 32 +++++++++++++++++++++++++++- gcc/config/arm/arm.h | 2 +- gcc/config/arm/arm.md | 4 ++-- gcc/config/arm/arm.opt | 11 +++++++++- gcc/doc/invoke.texi | 15 +++++++------ gcc/testsuite/gcc.target/arm/mtp.c | 8 +++++++ gcc/testsuite/gcc.target/arm/mtp_1.c | 7 ++++++ gcc/testsuite/gcc.target/arm/mtp_2.c | 7 ++++++ gcc/testsuite/gcc.target/arm/mtp_3.c | 7 ++++++ gcc/testsuite/gcc.target/arm/mtp_4.c | 7 ++++++ 12 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/mtp.c create mode 100644 gcc/testsuite/gcc.target/arm/mtp_1.c create mode 100644 gcc/testsuite/gcc.target/arm/mtp_2.c create mode 100644 gcc/testsuite/gcc.target/arm/mtp_3.c create mode 100644 gcc/testsuite/gcc.target/arm/mtp_4.c diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h index 9964fd2dbb5..174dbc505e0 100644 --- a/gcc/config/arm/arm-opts.h +++ b/gcc/config/arm/arm-opts.h @@ -61,7 +61,9 @@ enum float_abi_type enum arm_tp_type { TP_AUTO, TP_SOFT, - TP_CP15 + TP_TPIDRURW, + TP_TPIDRURO, + TP_TPIDRPRW }; /* Which TLS scheme to use. */ diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 61fcd671437..7d73c66a15d 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -182,6 +182,7 @@ extern bool arm_is_long_call_p (tree); extern int arm_emit_vector_const (FILE *, rtx); extern void arm_emit_fp16_const (rtx c); extern const char * arm_output_load_gr (rtx *); +extern const char * arm_output_load_tpidr (rtx, bool); extern const char *vfp_output_vstmd (rtx *); extern void arm_output_multireg_pop (rtx *, bool, rtx, bool, bool); extern void arm_set_return_address (rtx, rtx); diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index c3e731b8982..38f0839de1c 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -3927,7 +3927,7 @@ arm_option_reconfigure_globals (void) if (target_thread_pointer == TP_AUTO) { if (arm_arch6k && !TARGET_THUMB1) - target_thread_pointer = TP_CP15; + target_thread_pointer = TP_TPIDRURO; else target_thread_pointer = TP_SOFT; } @@ -34648,4 +34648,34 @@ arm_get_mask_mode (machine_mode mode) return default_get_mask_mode (mode); } +/* Output assembly to read the thread pointer from the appropriate TPIDR + register into DEST. If PRED_P also emit the %? that can be used to + output the predication code. */ + +const char * +arm_output_load_tpidr (rtx dst, bool pred_p) +{ + char buf[64]; + int tpidr_coproc_num = -1; + switch (target_thread_pointer) + { + case TP_TPIDRURW: + tpidr_coproc_num = 2; + break; + case TP_TPIDRURO: + tpidr_coproc_num = 3; + break; + case TP_TPIDRPRW: + tpidr_coproc_num = 4; + break; + default: + gcc_unreachable (); + } + snprintf (buf, sizeof (buf), + "mrc%s\tp15, 0, %%0, c13, c0, %d\t@ load_tp_hard", + pred_p ? "%?" : "", tpidr_coproc_num); + output_asm_insn (buf, &dst); + return ""; +} + #include "gt-arm.h" diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 7d40b8b7e00..4f54530adcb 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -152,8 +152,8 @@ emission of floating point pcs attributes. */ #define TARGET_AAPCS_BASED \ (arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS) -#define TARGET_HARD_TP (target_thread_pointer == TP_CP15) #define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT) +#define TARGET_HARD_TP !TARGET_SOFT_TP #define TARGET_GNU2_TLS (target_tls_dialect == TLS_GNU2) /* Only 16-bit thumb code. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 2c7249f0193..2ac97232ffd 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -12275,7 +12275,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(const_int 0)] UNSPEC_TLS))] "TARGET_HARD_TP" - "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard" + "* return arm_output_load_tpidr (operands[0], true);" [(set_attr "predicable" "yes") (set_attr "type" "mrs")] ) @@ -12285,7 +12285,7 @@ [(set (match_operand:SI 0 "register_operand" "=r") (unspec_volatile:SI [(const_int 0)] VUNSPEC_MRC))] "TARGET_HARD_TP" - "mrc\\tp15, 0, %0, c13, c0, 3\\t@ reload_tp_hard" + "* return arm_output_load_tpidr (operands[0], false);" [(set_attr "type" "mrs")] ) diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt index 3a49b51ece0..88299dabc3a 100644 --- a/gcc/config/arm/arm.opt +++ b/gcc/config/arm/arm.opt @@ -230,7 +230,16 @@ EnumValue Enum(arm_tp_type) String(auto) Value(TP_AUTO) EnumValue -Enum(arm_tp_type) String(cp15) Value(TP_CP15) +Enum(arm_tp_type) String(tpidrurw) Value(TP_TPIDRURW) + +EnumValue +Enum(arm_tp_type) String(cp15) Value(TP_TPIDRURO) + +EnumValue +Enum(arm_tp_type) String(tpidruro) Value(TP_TPIDRURO) + +EnumValue +Enum(arm_tp_type) String(tpidrprw) Value(TP_TPIDRPRW) mtpcs-frame Target Mask(TPCS_FRAME) diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 54c377fd815..8fa3f9fae01 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -22645,12 +22645,15 @@ by default. @opindex mtp @item -mtp=@var{name} -Specify the access model for the thread local storage pointer. The valid -models are @samp{soft}, which generates calls to @code{__aeabi_read_tp}, -@samp{cp15}, which fetches the thread pointer from @code{cp15} directly -(supported in the arm6k architecture), and @samp{auto}, which uses the -best available method for the selected processor. The default setting is -@samp{auto}. +Specify the access model for the thread local storage pointer. The model +@samp{soft} generates calls to @code{__aeabi_read_tp}. Other accepted +models are @samp{tpidrurw}, @samp{tpidruro} and @samp{tpidrprw} which fetch +the thread pointer from the corresponding system register directly +(supported from the arm6k architecture and later). These system registers +are accessed through the CP15 co-processor interface and the argument +@samp{cp15} is also accepted as a convenience alias of @samp{tpidruro}. +The argument @samp{auto} uses the best available method for the selected +processor. The default setting is @samp{auto}. @opindex mtls-dialect @item -mtls-dialect=@var{dialect} diff --git a/gcc/testsuite/gcc.target/arm/mtp.c b/gcc/testsuite/gcc.target/arm/mtp.c new file mode 100644 index 00000000000..d994c377fd3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mtp.c @@ -0,0 +1,8 @@ +__thread int i; + +int +foo (void) +{ + return i; +} + diff --git a/gcc/testsuite/gcc.target/arm/mtp_1.c b/gcc/testsuite/gcc.target/arm/mtp_1.c new file mode 100644 index 00000000000..678d27d9234 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mtp_1.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O -mtp=cp15" } */ + +#include "mtp.c" + +/* { dg-final { scan-assembler-times {mrc\tp15, 0, r3, c13, c0, 3} 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/mtp_2.c b/gcc/testsuite/gcc.target/arm/mtp_2.c new file mode 100644 index 00000000000..bcb308f2637 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mtp_2.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O -mtp=tpidrprw" } */ + +#include "mtp.c" + +/* { dg-final { scan-assembler-times {mrc\tp15, 0, r3, c13, c0, 4} 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/mtp_3.c b/gcc/testsuite/gcc.target/arm/mtp_3.c new file mode 100644 index 00000000000..7d5cea3cab6 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mtp_3.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O -mtp=tpidruro" } */ + +#include "mtp.c" + +/* { dg-final { scan-assembler-times {mrc\tp15, 0, r3, c13, c0, 3} 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/mtp_4.c b/gcc/testsuite/gcc.target/arm/mtp_4.c new file mode 100644 index 00000000000..068078df84e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/mtp_4.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O -mtp=tpidrurw" } */ + +#include "mtp.c" + +/* { dg-final { scan-assembler-times {mrc\tp15, 0, r3, c13, c0, 2} 1 } } */