Generate la.tls.desc macro instruction for TLS descriptors model.

la.tls.desc expand to
  pcalau12i $a0, %desc_pc_hi20(a)
  ld.d      $a1, $a0, %desc_ld_pc_lo12(a)
  addi.d    $a0, $a0, %desc_add_pc_lo12(a)
  jirl      $ra, $a1, %desc_call(a)

The default is TLS descriptors, but can be configure with
-mtls-dialect={desc,trad}.

gcc/ChangeLog:

        * config.gcc: Add --with_tls to change the TLS flavor.
        * config/loongarch/genopts/loongarch.opt.in: Add -mtls-dialect to
        configure TLS flavor.
        * config/loongarch/loongarch-opts.h (enum loongarch_tls_type): New.
        * config/loongarch/loongarch-protos.h (NUM_SYMBOL_TYPES): New.
        * config/loongarch/loongarch.cc (loongarch_symbol_insns): Add
        instruction sequence length data for TLS DESC.
        (loongarch_legitimize_tls_address): New TLS DESC instruction sequence.
        * config/loongarch/loongarch.h (TARGET_TLS_DESC): New.
        * config/loongarch/loongarch.md (@got_load_tls_desc<mode>): New.
        * config/loongarch/loongarch.opt: Regenerated.
---
Changes v1 -> v2:
- Clobber fcc0-fcc7 registers in got_load_tls_desc template.
- Support --with-tls in configure.

 gcc/config.gcc                                | 15 ++++++-
 gcc/config/loongarch/genopts/loongarch.opt.in | 14 ++++++
 gcc/config/loongarch/loongarch-opts.h         |  6 +++
 gcc/config/loongarch/loongarch-protos.h       |  3 +-
 gcc/config/loongarch/loongarch.cc             | 45 +++++++++++++++----
 gcc/config/loongarch/loongarch.h              |  8 ++++
 gcc/config/loongarch/loongarch.md             | 36 +++++++++++++++
 gcc/config/loongarch/loongarch.opt            | 14 ++++++
 8 files changed, 130 insertions(+), 11 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index a0f9c672308..72a5e992821 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2546,6 +2546,7 @@ loongarch*-*-linux*)
        # Force .init_array support.  The configure script cannot always
        # automatically detect that GAS supports it, yet we require it.
        gcc_cv_initfini_array=yes
+       with_tls=${with_tls:-desc}
        ;;
 
 loongarch*-*-elf*)
@@ -4987,7 +4988,7 @@ case "${target}" in
                ;;
 
        loongarch*-*)
-               supported_defaults="abi arch tune fpu simd multilib-default 
strict-align-lib"
+               supported_defaults="abi arch tune fpu simd multilib-default 
strict-align-lib tls"
 
                # Local variables
                unset \
@@ -5245,6 +5246,18 @@ case "${target}" in
                        with_multilib_list="${abi_base}/${abi_ext}"
                fi
 
+               # Handle --with-tls.
+               case "$with_tls" in
+               "" \
+               | trad | desc)
+                   # OK
+                   ;;
+               *)
+                   echo "Unknown TLS method used in --with-tls=$with_tls" 1>&2
+                   exit 1
+                   ;;
+               esac
+
                # Check if the configured default ABI combination is included in
                # ${with_multilib_list}.
                loongarch_multilib_list_sane=no
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in 
b/gcc/config/loongarch/genopts/loongarch.opt.in
index 02f918053f5..2cc943ef683 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -262,3 +262,17 @@ default value is 4.
 ; CPUCFG independently, so we use bit flags to specify them.
 TargetVariable
 HOST_WIDE_INT la_isa_evolution = 0
+
+Enum
+Name(tls_type) Type(enum loongarch_tls_type)
+The possible TLS dialects:
+
+EnumValue
+Enum(tls_type) String(trad) Value(TLS_TRADITIONAL)
+
+EnumValue
+Enum(tls_type) String(desc) Value(TLS_DESCRIPTORS)
+
+mtls-dialect=
+Target RejectNegative Joined Enum(tls_type) Var(loongarch_tls_dialect) 
Init(TLS_DESCRIPTORS) Save
+Specify TLS dialect.
diff --git a/gcc/config/loongarch/loongarch-opts.h 
b/gcc/config/loongarch/loongarch-opts.h
index 586e67e65ee..a08ab6fac10 100644
--- a/gcc/config/loongarch/loongarch-opts.h
+++ b/gcc/config/loongarch/loongarch-opts.h
@@ -134,4 +134,10 @@ struct loongarch_flags {
 #define HAVE_AS_TLS_LE_RELAXATION 0
 #endif
 
+/* TLS types.  */
+enum loongarch_tls_type {
+  TLS_TRADITIONAL,
+  TLS_DESCRIPTORS
+};
+
 #endif /* LOONGARCH_OPTS_H */
diff --git a/gcc/config/loongarch/loongarch-protos.h 
b/gcc/config/loongarch/loongarch-protos.h
index 1fdfda9af01..6b417a3c371 100644
--- a/gcc/config/loongarch/loongarch-protos.h
+++ b/gcc/config/loongarch/loongarch-protos.h
@@ -53,8 +53,9 @@ enum loongarch_symbol_type {
   SYMBOL_TLS_LE,
   SYMBOL_TLSGD,
   SYMBOL_TLSLDM,
+  SYMBOL_TLS_DESC,
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_TLSLDM + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_TLS_DESC + 1)
 
 /* Routines implemented in loongarch.cc.  */
 extern rtx loongarch_emit_move (rtx, rtx);
diff --git a/gcc/config/loongarch/loongarch.cc 
b/gcc/config/loongarch/loongarch.cc
index 0428b6e65d5..b4e43f1d037 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -2030,6 +2030,9 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, 
machine_mode mode)
     case SYMBOL_TLSLDM:
       return 3;
 
+    case SYMBOL_TLS_DESC:
+      return 4; /* pcalau12i, addi.d, ld.d, jirl.  */
+
     case SYMBOL_PCREL64:
       return 5;
 
@@ -2930,24 +2933,48 @@ loongarch_call_tls_get_addr (rtx sym, enum 
loongarch_symbol_type type, rtx v0)
 static rtx
 loongarch_legitimize_tls_address (rtx loc)
 {
-  rtx dest, tp, tmp, tmp1, tmp2, tmp3;
+  rtx dest, tp, tmp, tmp1, tmp2, tmp3, a0; /* a1? */
   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
   rtx_insn *insn;
 
   switch (model)
     {
     case TLS_MODEL_LOCAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
-      emit_libcall_block (insn, dest, tmp, loc);
+      if (TARGET_TLS_DESC)
+       {
+         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+         dest = gen_reg_rtx (Pmode);
+         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+
+         emit_insn (gen_got_load_tls_desc (Pmode, a0, loc));
+         emit_insn (gen_add3_insn (dest, a0, tp));
+       }
+      else
+       {
+         tmp = gen_rtx_REG (Pmode, GP_RETURN);
+         dest = gen_reg_rtx (Pmode);
+         insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
+         emit_libcall_block (insn, dest, tmp, loc);
+       }
       break;
 
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
-      emit_libcall_block (insn, dest, tmp, loc);
+      if (TARGET_TLS_DESC)
+       {
+         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+         dest = gen_reg_rtx (Pmode);
+         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+
+         emit_insn (gen_got_load_tls_desc (Pmode, a0, loc));
+         emit_insn (gen_add3_insn (dest, a0, tp));
+       }
+      else
+       {
+         tmp = gen_rtx_REG (Pmode, GP_RETURN);
+         dest = gen_reg_rtx (Pmode);
+         insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
+         emit_libcall_block (insn, dest, tmp, loc);
+       }
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index 8b453ab3140..262d3488120 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -25,6 +25,14 @@ along with GCC; see the file COPYING3.  If not see
 
 #define TARGET_SUPPORTS_WIDE_INT 1
 
+/* Support for configure-time default option. The rules are:
+   --with-tls is ignored if -mtls-dialect is specified.  */
+#define OPTION_DEFAULT_SPECS \
+  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"}, \
+
+/* Check TLS Descriptors mechanism is selected.  */
+#define TARGET_TLS_DESC (loongarch_tls_dialect == TLS_DESCRIPTORS)
+
 /* Macros to silence warnings about numbers being signed in traditional
    C and unsigned in ISO C when compiled on 32-bit hosts.  */
 
diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index dffa41b0bf5..f525c45a398 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -52,6 +52,11 @@ (define_c_enum "unspec" [
 
   ;; TLS
   UNSPEC_TLS
+  UNSPEC_TLS_GD
+  UNSPEC_TLS_LD
+  UNSPEC_TLS_LE
+  UNSPEC_TLS_IE
+  UNSPEC_TLS_DESC
 
   ;; Stack tie
   UNSPEC_TIE
@@ -123,10 +128,21 @@ (define_c_enum "unspecv" [
 (define_constants
   [(RETURN_ADDR_REGNUM         1)
    (TP_REGNUM                  2)
+   (A0_REGNUM                  4)
+   (A1_REGNUM                  5)
    (T0_REGNUM                  12)
    (T1_REGNUM                  13)
    (S0_REGNUM                  23)
 
+   (FCC0_REGNUM                        64)
+   (FCC1_REGNUM                        65)
+   (FCC2_REGNUM                        66)
+   (FCC3_REGNUM                        67)
+   (FCC4_REGNUM                        68)
+   (FCC5_REGNUM                        69)
+   (FCC6_REGNUM                        70)
+   (FCC7_REGNUM                        71)
+
    ;; Return path styles
    (NORMAL_RETURN              0)
    (SIBCALL_RETURN             1)
@@ -2760,6 +2776,26 @@ (define_insn "store_word<mode>"
 
 ;; Thread-Local Storage
 
+(define_insn "@got_load_tls_desc<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (unspec:P
+           [(match_operand:P 1 "symbolic_operand" "")]
+           UNSPEC_TLS_DESC))
+    (clobber (reg:SI FCC0_REGNUM))
+    (clobber (reg:SI FCC1_REGNUM))
+    (clobber (reg:SI FCC2_REGNUM))
+    (clobber (reg:SI FCC3_REGNUM))
+    (clobber (reg:SI FCC4_REGNUM))
+    (clobber (reg:SI FCC5_REGNUM))
+    (clobber (reg:SI FCC6_REGNUM))
+    (clobber (reg:SI FCC7_REGNUM))
+    (clobber (reg:SI A1_REGNUM))
+    (clobber (reg:SI RETURN_ADDR_REGNUM))]
+  "TARGET_TLS_DESC"
+  "la.tls.desc\t%0,%1"
+  [(set_attr "got" "load")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "@load_tls<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (unspec:P
diff --git a/gcc/config/loongarch/loongarch.opt 
b/gcc/config/loongarch/loongarch.opt
index f10fcdd968c..04846ae86c0 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -271,6 +271,20 @@ default value is 4.
 TargetVariable
 HOST_WIDE_INT la_isa_evolution = 0
 
+Enum
+Name(tls_type) Type(enum loongarch_tls_type)
+The possible TLS dialects:
+
+EnumValue
+Enum(tls_type) String(trad) Value(TLS_TRADITIONAL)
+
+EnumValue
+Enum(tls_type) String(desc) Value(TLS_DESCRIPTORS)
+
+mtls-dialect=
+Target RejectNegative Joined Enum(tls_type) Var(loongarch_tls_dialect) 
Init(TLS_DESCRIPTORS) Save
+Specify TLS dialect.
+
 mfrecipe
 Target Mask(ISA_FRECIPE) Var(la_isa_evolution)
 Support frecipe.{s/d} and frsqrte.{s/d} instructions.
-- 
2.36.0

Reply via email to