On Sun, Sep 27, 2026 at 4:23 PM Andrea Pinski <[email protected]> wrote: > > On Sun, Sep 27, 2026 at 4:16 PM mironu <[email protected]> wrote: > > > > The MIPS backend currently uses rdhwr to access the thread pointer. > > This instruction is unavailable on older MIPS processors such as the > > R3900. > > > > Add -mtp=soft to allow the MIPS backend to obtain the thread pointer > > through the __mips_read_tp runtime helper instead of using rdhwr. > > The default -mtp=rdhwr behavior is unchanged. > > > > Tests cover the software thread-pointer path for normal MIPS, MIPS16, > > and MIPS16 with abicalls, as well as the default rdhwr path. > > So at Cavium, we had patches to allow us to use a GRP instead of > rdhwr. This was for Octeon 1 which was just a normal MIPS64r1 (not r2 > which added rdhwr); we removed that hack once Octeon 2 came around > which had native rdhwr support (Octeon 3 supported it too). > This was only done for speed reasons because the Linux kernel would do > a trap and handle the rdhwr anyways. > Can you expand on why you want to allow not to use rdhwr? And the > effects on the ABI here; is __mips_read_tp documented as part of some > ABI documentation? Or did you make this up?
Another point: do you have a copyright on file with the FSF; otherwise you will need to not submit anonymously. Please read https://gcc.gnu.org/contribute.html#legal and the legal requirements there. Thanks, Andrea > > > > > gcc/ChangeLog: > > > > * config/mips/mips-opts.h (enum mips_thread_pointer_setting): > > Add MIPS_TP_SOFT. > > * config/mips/mips.cc (mips_expand_thread_pointer): > > Generate a call to __mips_read_tp when -mtp=soft is used. > > * config/mips/mips.opt: Add -mtp option with rdhwr and soft > > thread-pointer access methods. > > * config/mips/mips.opt.urls: Add URL for -mtp. > > * doc/invoke.texi: Document -mtp. > > > > gcc/testsuite/ChangeLog: > > > > * gcc.target/mips/tls-hard-tp.c: New test. > > * gcc.target/mips/tls-soft-tp-mips16-abicalls.c: New test. > > * gcc.target/mips/tls-soft-tp-mips16.c: New test. > > * gcc.target/mips/tls-soft-tp.c: New test. > > * gcc.target/mips/mips.exp: Add tp to mips_option_groups. > > --- > > gcc/config/mips/mips-opts.h | 6 ++++++ > > gcc/config/mips/mips.cc | 17 +++++++++++++++-- > > gcc/config/mips/mips.opt | 14 ++++++++++++++ > > gcc/config/mips/mips.opt.urls | 3 +++ > > gcc/doc/invoke.texi | 7 +++++++ > > gcc/testsuite/gcc.target/mips/mips.exp | 1 + > > gcc/testsuite/gcc.target/mips/tls-hard-tp.c | 13 +++++++++++++ > > .../mips/tls-soft-tp-mips16-abicalls.c | 14 ++++++++++++++ > > .../gcc.target/mips/tls-soft-tp-mips16.c | 14 ++++++++++++++ > > gcc/testsuite/gcc.target/mips/tls-soft-tp.c | 13 +++++++++++++ > > 10 files changed, 100 insertions(+), 2 deletions(-) > > create mode 100644 gcc/testsuite/gcc.target/mips/tls-hard-tp.c > > create mode 100644 > > gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16-abicalls.c > > create mode 100644 gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16.c > > create mode 100644 gcc/testsuite/gcc.target/mips/tls-soft-tp.c > > > > diff --git a/gcc/config/mips/mips-opts.h b/gcc/config/mips/mips-opts.h > > index d8b1b4c632c..c53fdbe4b5c 100644 > > --- a/gcc/config/mips/mips-opts.h > > +++ b/gcc/config/mips/mips-opts.h > > @@ -41,6 +41,12 @@ enum mips_r10k_cache_barrier_setting { > > R10K_CACHE_BARRIER_LOAD_STORE > > }; > > > > +/* Enumerates the setting of the -mtp option. */ > > +enum mips_thread_pointer_setting { > > + MIPS_TP_RDHWR, > > + MIPS_TP_SOFT > > +}; > > + > > /* No enumeration is defined to index the -march= values (entries in > > mips_cpu_info_table), with the type int being used instead, but we > > need to distinguish the special "from-abi" and "native" values. */ > > diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc > > index e54a310b2b4..1930ea6d5c6 100644 > > --- a/gcc/config/mips/mips.cc > > +++ b/gcc/config/mips/mips.cc > > @@ -3610,6 +3610,9 @@ mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT > > offset) > > /* The __tls_get_attr symbol. */ > > static GTY(()) rtx mips_tls_symbol; > > > > +/* The helper used to read the thread pointer in soft mode. */ > > +static GTY(()) rtx mips_read_tp_symbol; > > + > > /* Return an instruction sequence that calls __tls_get_addr. SYM is > > the TLS symbol we are referencing and TYPE is the symbol type to use > > (either global dynamic or local dynamic). V0 is an RTX for the > > @@ -3646,9 +3649,19 @@ mips_call_tls_get_addr (rtx sym, enum > > mips_symbol_type type, rtx v0) > > rtx > > mips_expand_thread_pointer (rtx tp) > > { > > - rtx fn; > > + rtx fn, v0; > > > > - if (TARGET_MIPS16) > > + if (mips_thread_pointer == MIPS_TP_SOFT) > > + { > > + if (!mips_read_tp_symbol) > > + mips_read_tp_symbol = init_one_libfunc ("__mips_read_tp"); > > + > > + v0 = gen_rtx_REG (Pmode, GP_RETURN); > > + mips_expand_call (MIPS_CALL_NORMAL, v0, mips_read_tp_symbol, > > + const0_rtx, NULL_RTX, false); > > + emit_move_insn (tp, v0); > > + } > > + else if (TARGET_MIPS16) > > { > > if (!mips16_rdhwr_stub) > > mips16_rdhwr_stub = new mips16_rdhwr_one_only_stub (); > > diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt > > index eb14761ea27..e0fadb4e43a 100644 > > --- a/gcc/config/mips/mips.opt > > +++ b/gcc/config/mips/mips.opt > > @@ -425,6 +425,20 @@ mtune= > > Target RejectNegative Joined Var(mips_tune_option) ToLower > > Enum(mips_arch_opt_value) > > -mtune=PROCESSOR Optimize the output for PROCESSOR. > > > > +mtp= > > +Target RejectNegative Joined Enum(mips_thread_pointer_setting) > > Var(mips_thread_pointer) Init(MIPS_TP_RDHWR) > > +-mtp=METHOD Specify how to access the thread pointer. > > + > > +Enum > > +Name(mips_thread_pointer_setting) Type(enum mips_thread_pointer_setting) > > +Valid arguments to -mtp=: > > + > > +EnumValue > > +Enum(mips_thread_pointer_setting) String(rdhwr) Value(MIPS_TP_RDHWR) > > + > > +EnumValue > > +Enum(mips_thread_pointer_setting) String(soft) Value(MIPS_TP_SOFT) > > + > > mstrict-align > > Target Var(TARGET_STRICT_ALIGN) Init(0) > > Don't generate code with unaligned load store, only valid for MIPS R6. > > diff --git a/gcc/config/mips/mips.opt.urls b/gcc/config/mips/mips.opt.urls > > index 6287d9f1c70..1f1bbef5dc9 100644 > > --- a/gcc/config/mips/mips.opt.urls > > +++ b/gcc/config/mips/mips.opt.urls > > @@ -243,6 +243,9 @@ UrlSuffix(gcc/MIPS-Options.html#index-mmadd4) > > mtune= > > UrlSuffix(gcc/MIPS-Options.html#index-mtune-9) > > > > +mtp= > > +UrlSuffix(gcc/MIPS-Options.html#index-mtp) > > + > > mstrict-align > > UrlSuffix(gcc/MIPS-Options.html#index-mstrict-align-3) > > > > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi > > index c5d17c059fd..1bbb90e43f9 100644 > > --- a/gcc/doc/invoke.texi > > +++ b/gcc/doc/invoke.texi > > @@ -29125,6 +29125,13 @@ particular member of that family. > > @code{_MIPS_TUNE_@var{foo}}, which work in the same way as the > > @option{-march} ones described above. > > > > +@opindex mtp > > +@item -mtp=@var{method} > > +Specify how to access the thread pointer. The default, @samp{rdhwr}, > > +uses the @code{rdhwr $3,$29} instruction. @samp{soft} generates a call > > +to @code{__mips_read_tp} instead. The helper must return the current > > +thread pointer in the normal MIPS function return register. > > + > > @opindex mips1 > > @item -mips1 > > Equivalent to @option{-march=mips1}. > > diff --git a/gcc/testsuite/gcc.target/mips/mips.exp > > b/gcc/testsuite/gcc.target/mips/mips.exp > > index 9492b1dcaf8..8ded794b761 100644 > > --- a/gcc/testsuite/gcc.target/mips/mips.exp > > +++ b/gcc/testsuite/gcc.target/mips/mips.exp > > @@ -314,6 +314,7 @@ foreach option { > > code-readable > > nan > > r10k-cache-barrier > > + tp > > tune > > } { > > lappend mips_option_groups $option "-m$option=.*" > > diff --git a/gcc/testsuite/gcc.target/mips/tls-hard-tp.c > > b/gcc/testsuite/gcc.target/mips/tls-hard-tp.c > > new file mode 100644 > > index 00000000000..4b23d561b02 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/mips/tls-hard-tp.c > > @@ -0,0 +1,13 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-march=mips32r2 -mgp32 -mno-abicalls" } */ > > + > > +extern __thread int x __attribute__ ((tls_model ("initial-exec"))); > > + > > +int > > +foo (void) > > +{ > > + return x; > > +} > > + > > +/* { dg-final { scan-assembler "rdhwr" } } */ > > +/* { dg-final { scan-assembler-not "__mips_read_tp" } } */ > > diff --git a/gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16-abicalls.c > > b/gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16-abicalls.c > > new file mode 100644 > > index 00000000000..11f73026592 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16-abicalls.c > > @@ -0,0 +1,14 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-march=r3900 -mips16 -mtp=soft -mgp32 -mabicalls > > -mno-shared" } */ > > + > > +extern __thread int x __attribute__ ((tls_model ("initial-exec"))); > > + > > +int > > +foo (void) > > +{ > > + return x; > > +} > > + > > +/* { dg-final { scan-assembler "__mips_read_tp" } } */ > > +/* { dg-final { scan-assembler-not "rdhwr" } } */ > > +/* { dg-final { scan-assembler-not "__mips16_rdhwr" } } */ > > diff --git a/gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16.c > > b/gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16.c > > new file mode 100644 > > index 00000000000..0efa8b37cb3 > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/mips/tls-soft-tp-mips16.c > > @@ -0,0 +1,14 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-march=r3900 -mips16 -mtp=soft -mgp32 -mno-abicalls" } */ > > + > > +extern __thread int x __attribute__ ((tls_model ("initial-exec"))); > > + > > +int > > +foo (void) > > +{ > > + return x; > > +} > > + > > +/* { dg-final { scan-assembler "__mips_read_tp" } } */ > > +/* { dg-final { scan-assembler-not "rdhwr" } } */ > > +/* { dg-final { scan-assembler-not "__mips16_rdhwr" } } */ > > diff --git a/gcc/testsuite/gcc.target/mips/tls-soft-tp.c > > b/gcc/testsuite/gcc.target/mips/tls-soft-tp.c > > new file mode 100644 > > index 00000000000..a771d431dec > > --- /dev/null > > +++ b/gcc/testsuite/gcc.target/mips/tls-soft-tp.c > > @@ -0,0 +1,13 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-march=r3900 -mtp=soft -mgp32 -mno-abicalls" } */ > > + > > +extern __thread int x __attribute__ ((tls_model ("initial-exec"))); > > + > > +int > > +foo (void) > > +{ > > + return x; > > +} > > + > > +/* { dg-final { scan-assembler "__mips_read_tp" } } */ > > +/* { dg-final { scan-assembler-not "rdhwr" } } */ > > -- > > 2.43.0 > >
