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
> >

Reply via email to