PR target/108779 aarch64: Implement -mtp= option

A user has requested that we support the -mtp= option in aarch64 GCC for changing
the TPIDR register to read for TLS accesses. I'm not a big fan of the option name,
but we already support it in the arm port and Clang supports it for AArch64 already,
where it accepts the 'el0', 'el1', 'el2', 'el3' values.

This patch implements the same functionality in GCC.

Bootstrapped and tested on aarch64-none-linux-gnu.
Confirmed with godbolt that the sequences and options are the same as what Clang accepts/generates.

gcc/ChangeLog:

	PR target/108779
	* config/aarch64/aarch64-opts.h (enum aarch64_tp_reg): Define.
	* config/aarch64/aarch64-protos.h (aarch64_output_load_tp):
	Define prototype.
	* config/aarch64/aarch64.cc (aarch64_tpidr_register): Declare.
	(aarch64_override_options_internal): Handle the above.
	(aarch64_output_load_tp): New function.
	* config/aarch64/aarch64.md (aarch64_load_tp_hard): Call
	aarch64_output_load_tp.
	* config/aarch64/aarch64.opt (aarch64_tp_reg): Define enum.
	(mtp=): New option.
	* doc/invoke.texi (AArch64 Options): Document -mtp=.

gcc/testsuite/ChangeLog:

	PR target/108779
	* gcc.target/aarch64/mtp.c: New test.
	* gcc.target/aarch64/mtp_1.c: New test.
	* gcc.target/aarch64/mtp_2.c: New test.
	* gcc.target/aarch64/mtp_3.c: New test.
	* gcc.target/aarch64/mtp_4.c: New test.
This commit is contained in:
Kyrylo Tkachov 2023-04-21 19:00:02 +01:00
parent f824216cdb
commit 573624ec90
11 changed files with 94 additions and 1 deletions

View file

@ -75,6 +75,15 @@ enum aarch64_code_model {
AARCH64_CMODEL_LARGE
};
/* The register to use as a thread pointer for TLS accesses.
tpidr_el0 by default, but can be changed through the -mtp option. */
enum aarch64_tp_reg {
AARCH64_TPIDR_EL0 = 0,
AARCH64_TPIDR_EL1 = 1,
AARCH64_TPIDR_EL2 = 2,
AARCH64_TPIDR_EL3 = 3
};
/* SVE vector register sizes. */
enum aarch64_sve_vector_bits_enum {
SVE_SCALABLE,

View file

@ -838,6 +838,7 @@ int aarch64_movk_shift (const wide_int_ref &, const wide_int_ref &);
bool aarch64_is_mov_xn_imm (unsigned HOST_WIDE_INT);
bool aarch64_use_return_insn_p (void);
const char *aarch64_output_casesi (rtx *);
const char *aarch64_output_load_tp (rtx);
unsigned int aarch64_tlsdesc_abi_id ();
enum aarch64_symbol_type aarch64_classify_symbol (rtx, HOST_WIDE_INT);

View file

@ -281,6 +281,8 @@ private:
/* The current code model. */
enum aarch64_code_model aarch64_cmodel;
enum aarch64_tp_reg aarch64_tpidr_register;
/* The number of 64-bit elements in an SVE vector. */
poly_uint16 aarch64_sve_vg;
@ -17889,6 +17891,7 @@ aarch64_override_options_internal (struct gcc_options *opts)
initialize_aarch64_code_model (opts);
initialize_aarch64_tls_size (opts);
aarch64_tpidr_register = opts->x_aarch64_tpidr_reg;
int queue_depth = 0;
switch (aarch64_tune_params.autoprefetcher_model)
@ -27415,6 +27418,20 @@ aarch64_indirect_call_asm (rtx addr)
return "";
}
/* Emit the assembly instruction to load the thread pointer into DEST.
Select between different tpidr_elN registers depending on -mtp= setting. */
const char *
aarch64_output_load_tp (rtx dest)
{
const char *tpidrs[] = {"tpidr_el0", "tpidr_el1", "tpidr_el2", "tpidr_el3"};
char buffer[64];
snprintf (buffer, sizeof (buffer), "mrs\t%%0, %s",
tpidrs[aarch64_tpidr_register]);
output_asm_insn (buffer, &dest);
return "";
}
/* Target-specific selftests. */
#if CHECKING_P

View file

@ -7077,7 +7077,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(const_int 0)] UNSPEC_TLS))]
""
"mrs\\t%0, tpidr_el0"
"* return aarch64_output_load_tp (operands[0]);"
[(set_attr "type" "mrs")]
)

View file

@ -97,6 +97,26 @@ mcmodel=
Target RejectNegative Joined Enum(cmodel) Var(aarch64_cmodel_var) Init(AARCH64_CMODEL_SMALL) Save
Specify the code model.
Enum
Name(tp_reg) Type(enum aarch64_tp_reg)
The register used to access the thread pointer:
EnumValue
Enum(tp_reg) String(el0) Value(AARCH64_TPIDR_EL0)
EnumValue
Enum(tp_reg) String(el1) Value(AARCH64_TPIDR_EL1)
EnumValue
Enum(tp_reg) String(el2) Value(AARCH64_TPIDR_EL2)
EnumValue
Enum(tp_reg) String(el3) Value(AARCH64_TPIDR_EL3)
mtp=
Target RejectNegative Joined Enum(tp_reg) Var(aarch64_tpidr_reg) Init(AARCH64_TPIDR_EL0) Save
Specify the thread pointer register.
mstrict-align
Target Mask(STRICT_ALIGN) Save
Don't assume that unaligned accesses are handled by the system.

View file

@ -20142,6 +20142,16 @@ addresses and sizes of sections. Programs can be statically linked only. The
@option{-mcmodel=large} option is incompatible with @option{-mabi=ilp32},
@option{-fpic} and @option{-fPIC}.
@item -mtp=@var{name}
@opindex mtp
Specify the system register to use as a thread pointer. The valid values
are @samp{el0}, @samp{el1}, @samp{el2}, @samp{el3}. These correspond to
using the @samp{tpidr_el0}, @samp{tpidr_el1}, @samp{tpidr_el2},
@samp{tpidr_el3} registers accordingly. The default setting is @samp{el0}.
It is recommended to compile all code intended to interoperate with the same
value of this option to avoid accessing a different thread pointer from the
wrong exception level.
@opindex mstrict-align
@opindex mno-strict-align
@item -mstrict-align

View file

@ -0,0 +1,8 @@
__thread int i;
int
foo (void)
{
return i;
}

View file

@ -0,0 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target tls_native } */
/* { dg-options "-O -mtp=el0" } */
#include "mtp.c"
/* { dg-final { scan-assembler-times {mrs\tx[0-9]+, tpidr_el0} 1 } } */

View file

@ -0,0 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target tls_native } */
/* { dg-options "-O -mtp=el1" } */
#include "mtp.c"
/* { dg-final { scan-assembler-times {mrs\tx[0-9]+, tpidr_el1} 1 } } */

View file

@ -0,0 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target tls_native } */
/* { dg-options "-O -mtp=el2" } */
#include "mtp.c"
/* { dg-final { scan-assembler-times {mrs\tx[0-9]+, tpidr_el2} 1 } } */

View file

@ -0,0 +1,7 @@
/* { dg-do compile } */
/* { dg-require-effective-target tls_native } */
/* { dg-options "-O -mtp=el3" } */
#include "mtp.c"
/* { dg-final { scan-assembler-times {mrs\tx[0-9]+, tpidr_el3} 1 } } */