diff mbox series

LoongArch: Add support for TLS descriptors

Message ID 20231201095524.1896396-1-mengqinggang@loongson.cn
State New
Headers show
Series LoongArch: Add support for TLS descriptors | expand

Commit Message

mengqinggang Dec. 1, 2023, 9:55 a.m. UTC
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.
---
 gcc/config.gcc                                | 16 ++++++-
 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              |  9 ++++
 gcc/config/loongarch/loongarch.md             | 15 +++++++
 gcc/config/loongarch/loongarch.opt            | 14 ++++++
 8 files changed, 111 insertions(+), 11 deletions(-)

Comments

Xi Ruoyao Dec. 1, 2023, 10:01 a.m. UTC | #1
On Fri, 2023-12-01 at 17:55 +0800, mengqinggang wrote:
> 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}.

No, the default should be trad to be compatible with old Glibc and
Binutils.

Or you can check the value of --with-glibc-version=M.N and the GAS
feature when GCC is configured to decide the default.
Xi Ruoyao Dec. 1, 2023, 10:03 a.m. UTC | #2
On Fri, 2023-12-01 at 18:01 +0800, Xi Ruoyao wrote:
> On Fri, 2023-12-01 at 17:55 +0800, mengqinggang wrote:
> > 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}.
> 
> No, the default should be trad to be compatible with old Glibc and
> Binutils.
> 
> Or you can check the value of --with-glibc-version=M.N and the GAS
> feature when GCC is configured to decide the default.

And GCC is in stage 3 now.  To me this change is significant enough to
be deferred into GCC 15 stage 1.
mengqinggang Dec. 1, 2023, 10:13 a.m. UTC | #3
This is mainly for the convenience of testing, and we will consider the 
issues you mentioned.


在 2023/12/1 下午6:01, Xi Ruoyao 写道:
> On Fri, 2023-12-01 at 17:55 +0800, mengqinggang wrote:
>> 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}.
> No, the default should be trad to be compatible with old Glibc and
> Binutils.
>
> Or you can check the value of --with-glibc-version=M.N and the GAS
> feature when GCC is configured to decide the default.
>
Xi Ruoyao Dec. 1, 2023, 10:24 a.m. UTC | #4
On Fri, 2023-12-01 at 18:13 +0800, mengqinggang wrote:
> This is mainly for the convenience of testing

Actually when I build my system on x86_64 I always set -mtls-
dialect=gnu2 in my CFLAGS.  And I think maybe generally (i.e. on
different architectures) we should make TLS descriptor the default if
it's supported by the assembler and --with-glibc-version= setting is
high enough...

Currently the only architecture (AFAIK) having TLS desc as the default
is AArch64 because it supports TLS desc since the birthday.
diff mbox series

Patch

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 748430194f3..5b3120dff6d 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2545,6 +2545,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*)
@@ -2557,6 +2558,7 @@  loongarch*-*-elf*)
 	# For .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}
 	;;
 
 mips*-*-netbsd*)			# NetBSD/mips, either endian.
@@ -4986,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 \
@@ -5244,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 8af6cc6f532..4a2ae80f25b 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -254,3 +254,17 @@  default value is 4.
 ; CPUCFG independantly, so we use bit flags to specify them.
 Variable
 HOST_WIDE_INT 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 fa3773223bc..28cd08712f4 100644
--- a/gcc/config/loongarch/loongarch-opts.h
+++ b/gcc/config/loongarch/loongarch-opts.h
@@ -115,4 +115,10 @@  loongarch_update_gcc_opt_status (struct loongarch_target *target,
 #define HAVE_AS_TLS 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 cb8fc36b086..4b3f942da90 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 d3896d72bc2..c53e88dc82f 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -2004,6 +2004,9 @@  loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
     case SYMBOL_TLSLDM:
       return 3;
 
+    case SYMBOL_TLS_DESC:
+      return 4;
+
     case SYMBOL_PCREL64:
       return 5;
 
@@ -2919,24 +2922,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 115222e70fd..f474cdc2857 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -25,6 +25,15 @@  along with GCC; see the file COPYING3.  If not see
 
 #define TARGET_SUPPORTS_WIDE_INT 1
 
+/* Check TLS Descriptors mechanism is selected.  */
+#define TARGET_TLS_DESC (loongarch_tls_dialect == TLS_DESCRIPTORS)
+
+/* --with-tls is ignored if -mtls-dialect is specified.  */
+/*
+#define OPTION_DEFAULT_SPECS \
+  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"}, \
+*/
+
 /* 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 cd4ed495697..71f46c9d2fe 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -55,6 +55,7 @@  (define_c_enum "unspec" [
   UNSPEC_TLS_LD
   UNSPEC_TLS_LE
   UNSPEC_TLS_IE
+  UNSPEC_TLS_DESC
 
   ;; Stack tie
   UNSPEC_TIE
@@ -114,6 +115,8 @@  (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)
@@ -2436,6 +2439,18 @@  (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 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 "@got_load_tls_gd<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 4d36e3ec4de..ad2e770e1e6 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -278,3 +278,17 @@  Support amcas[_db].{b/h/w/d} instructions.
 mld-seq-sa
 Target Mask(ISA_LD_SEQ_SA) Var(isa_evolution)
 Do not need load-load barriers (dbar 0x700).
+
+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.