public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] RISC-V: Implement TLS Descriptors.
@ 2023-08-17 18:12 Tatsuyuki Ishi
  2023-08-29 13:40 ` Kito Cheng
                   ` (4 more replies)
  0 siblings, 5 replies; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-08-17 18:12 UTC (permalink / raw)
  To: gcc-patches; +Cc: rui314, ruiu, Tatsuyuki Ishi

This implements TLS Descriptors (TLSDESC) as specified in [1].

In TLSDESC instruction sequence, the first instruction relocates against
the target TLS variable, while subsequent instructions relocates against
the address of the first. Such usage of labels are not well-supported
within GCC. Due to this, the 4-instruction sequence is implemented as a
single RTX insn.

For now, keep defaulting to the traditional TLS model, but this can be
revisited once toolchain and libc support ships.

[1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373
---
No regression in binutils and gcc tests for rv64gc, tested alongside the
binutils and glibc implementation (posted at the same time). During
testing, the default TLS dialect was changed to TLSDESC.

This contribution is made on behalf of Blue Whale Systems, which has
copyright assignment on file with the FSF.

 gcc/config/riscv/riscv-opts.h   |  6 ++++++
 gcc/config/riscv/riscv-protos.h |  5 +++--
 gcc/config/riscv/riscv.cc       | 34 +++++++++++++++++++++++++++++----
 gcc/config/riscv/riscv.h        |  3 +++
 gcc/config/riscv/riscv.md       | 22 ++++++++++++++++++++-
 gcc/config/riscv/riscv.opt      | 14 ++++++++++++++
 6 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 378a17699cd..db03f35430a 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -319,4 +319,10 @@ enum riscv_entity
 #define TARGET_VECTOR_VLS                                                      \
   (TARGET_VECTOR && riscv_autovec_preference == RVV_SCALABLE)
 
+/* TLS types.  */
+enum riscv_tls_type {
+  TLS_TRADITIONAL,
+  TLS_DESCRIPTORS
+};
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 472c00dc439..9b7471f7591 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -33,9 +33,10 @@ enum riscv_symbol_type {
   SYMBOL_TLS,
   SYMBOL_TLS_LE,
   SYMBOL_TLS_IE,
-  SYMBOL_TLS_GD
+  SYMBOL_TLS_GD,
+  SYMBOL_TLSDESC,
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
 
 /* Classifies an address.
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 49062bef9fc..4ff0adbbb1e 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -799,6 +799,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
+    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
     default: gcc_unreachable ();
     }
@@ -1601,6 +1602,16 @@ static rtx riscv_tls_add_tp_le (rtx dest, rtx base, rtx sym)
     return gen_tls_add_tp_lesi (dest, base, tp, sym);
 }
 
+/* Instruction sequence to call the TLS Descriptor resolver.  */
+
+static rtx riscv_tlsdesc (rtx sym, rtx seqno)
+{
+  if (Pmode == DImode)
+    return gen_tlsdescdi (sym, seqno);
+  else
+    return gen_tlsdescsi (sym, seqno);
+}
+
 /* If MODE is MAX_MACHINE_MODE, ADDR appears as a move operand, otherwise
    it appears in a MEM of that mode.  Return true if ADDR is a legitimate
    constant in that context and can be split into high and low parts.
@@ -1734,7 +1745,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
 static rtx
 riscv_legitimize_tls_address (rtx loc)
 {
-  rtx dest, tp, tmp;
+  rtx dest, tp, tmp, a0;
   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
 
 #if 0
@@ -1750,9 +1761,24 @@ riscv_legitimize_tls_address (rtx loc)
       /* Rely on section anchors for the optimization that LDM TLS
 	 provides.  The anchor's address is loaded with GD TLS. */
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
+      if (TARGET_TLSDESC)
+	{
+	  static unsigned seqno;
+	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+	  dest = gen_reg_rtx (Pmode);
+
+	  emit_insn (riscv_tlsdesc (loc, GEN_INT (seqno)));
+	  emit_insn (gen_add3_insn (dest, a0, tp));
+	  seqno++;
+	}
+      else
+	{
+	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
+	  dest = gen_reg_rtx (Pmode);
+	  emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
+			      loc);
+	}
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index e18a0081297..7cf1365ec08 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -1122,4 +1122,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
 #define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_VECTOR)
 #define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE, riscv_vector::FRM_NONE}
 
+/* Check TLS Descriptors mechanism is selected.  */
+#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index b456fa6abb3..bddd92323ad 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -47,7 +47,7 @@
   UNSPEC_TLS_LE
   UNSPEC_TLS_IE
   UNSPEC_TLS_GD
-
+  UNSPEC_TLSDESC
   ;; High part of PC-relative address.
   UNSPEC_AUIPC
 
@@ -121,6 +121,14 @@
    (T1_REGNUM			6)
    (S0_REGNUM			8)
    (S1_REGNUM			9)
+   (A0_REGNUM			10)
+   (A1_REGNUM			11)
+   (A2_REGNUM			12)
+   (A3_REGNUM			13)
+   (A4_REGNUM			14)
+   (A5_REGNUM			15)
+   (A6_REGNUM			16)
+   (A7_REGNUM			17)
    (S2_REGNUM			18)
    (S3_REGNUM			19)
    (S4_REGNUM			20)
@@ -1869,6 +1877,18 @@
   [(set_attr "got" "load")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "tlsdesc<mode>"
+  [(set (reg:P A0_REGNUM)
+	    (unspec:P
+			[(match_operand:P 0 "symbolic_operand" "")
+             (match_operand:P 1 "const_int_operand")]
+			UNSPEC_TLSDESC))
+   (clobber (reg:SI T0_REGNUM))]
+  "TARGET_TLSDESC"
+  ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;jalr\tt0,t0,%%tlsdesc_call(.LT%1)"
+  [(set_attr "type" "multi")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "auipc<mode>"
   [(set (match_operand:P           0 "register_operand" "=r")
 	(unspec:P
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 6304efebfd5..40b3ebf2a99 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -311,3 +311,17 @@ Enum(riscv_autovec_lmul) String(m8) Value(RVV_M8)
 -param=riscv-autovec-lmul=
 Target RejectNegative Joined Enum(riscv_autovec_lmul) Var(riscv_autovec_lmul) Init(RVV_M1)
 -param=riscv-autovec-lmul=<string>	Set the RVV LMUL of auto-vectorization in the RISC-V port.
+
+Enum
+Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
+Specify TLS dialect.
\ No newline at end of file
-- 
2.34.1


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH] RISC-V: Implement TLS Descriptors.
  2023-08-17 18:12 [PATCH] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
@ 2023-08-29 13:40 ` Kito Cheng
  2023-09-08 10:49 ` [PATCH v2] " Tatsuyuki Ishi
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 26+ messages in thread
From: Kito Cheng @ 2023-08-29 13:40 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, rui314, ruiu

Hi Tatsuyuki:

Thanks your TLS desc implementation, it's looks already in good shape
now! just few minor comment :)


> @@ -121,6 +121,14 @@
>     (T1_REGNUM                  6)
>     (S0_REGNUM                  8)
>     (S1_REGNUM                  9)
> +   (A0_REGNUM                  10)
> +   (A1_REGNUM                  11)
> +   (A2_REGNUM                  12)
> +   (A3_REGNUM                  13)
> +   (A4_REGNUM                  14)
> +   (A5_REGNUM                  15)
> +   (A6_REGNUM                  16)
> +   (A7_REGNUM                  17)

Drop A1_REGNUM~A7_REGNUM, they seems unused.

>     (S2_REGNUM                  18)
>     (S3_REGNUM                  19)
>     (S4_REGNUM                  20)
> @@ -1869,6 +1877,18 @@
>    [(set_attr "got" "load")
>     (set_attr "mode" "<MODE>")])
>
> +(define_insn "tlsdesc<mode>"

You can add @ to the pattern name ("@tlsdesc<mode>"), then you can
simplify riscv_legitimize_tls_address like that:

@@ -1908,7 +1898,7 @@ riscv_legitimize_tls_address (rtx loc)
         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
         dest = gen_reg_rtx (Pmode);

-         emit_insn (riscv_tlsdesc (loc, GEN_INT (seqno)));
+         emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
         emit_insn (gen_add3_insn (dest, a0, tp));
         seqno++;
       }

> +  [(set (reg:P A0_REGNUM)
> +           (unspec:P
> +                       [(match_operand:P 0 "symbolic_operand" "")
> +             (match_operand:P 1 "const_int_operand")]
> +                       UNSPEC_TLSDESC))
> +   (clobber (reg:SI T0_REGNUM))]
> +  "TARGET_TLSDESC"
> +  ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;jalr\tt0,t0,%%tlsdesc_call(.LT%1)"

I would suggest using return rather than single long line, like below,
that would be easier to read :
{
 return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
        "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
        "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
        "jalr\tt0,t0,%%tlsdesc_call(.LT%1)"
}


> +  [(set_attr "type" "multi")

We need add length here, something like that: "(set_attr "length"
(const_int 16))"

> +   (set_attr "mode" "<MODE>")])
> +
>  (define_insn "auipc<mode>"
>    [(set (match_operand:P           0 "register_operand" "=r")
>         (unspec:P
> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> index 6304efebfd5..40b3ebf2a99 100644
> --- a/gcc/config/riscv/riscv.opt
> +++ b/gcc/config/riscv/riscv.opt
> @@ -311,3 +311,17 @@ Enum(riscv_autovec_lmul) String(m8) Value(RVV_M8)
>  -param=riscv-autovec-lmul=
>  Target RejectNegative Joined Enum(riscv_autovec_lmul) Var(riscv_autovec_lmul) Init(RVV_M1)
>  -param=riscv-autovec-lmul=<string>     Set the RVV LMUL of auto-vectorization in the RISC-V port.
> +
> +Enum
> +Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save

Could you add a configure option `--with-tls` to control the default
TLS dialect?

You can reference ARM:
gcc/gcc/config/arm/arm.h: grep "OPTION_DEFAULT_SPECS"
gcc/gcc/config.gcc: grep "with_tls"

> +Specify TLS dialect.
> \ No newline at end of file
> --
> 2.34.1
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-08-17 18:12 [PATCH] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
  2023-08-29 13:40 ` Kito Cheng
@ 2023-09-08 10:49 ` Tatsuyuki Ishi
  2023-10-02 14:10   ` Kito Cheng
  2023-11-16  1:07   ` Jeff Law
  2023-11-20 13:17 ` [PATCH v3] " Tatsuyuki Ishi
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-09-08 10:49 UTC (permalink / raw)
  To: ishitatsuyuki; +Cc: gcc-patches, rui314, ruiu, kito.cheng

This implements TLS Descriptors (TLSDESC) as specified in [1].

In TLSDESC instruction sequence, the first instruction relocates against
the target TLS variable, while subsequent instructions relocates against
the address of the first. Such usage of labels are not well-supported
within GCC. Due to this, the 4-instruction sequence is implemented as a
single RTX insn.

The default remains to be the traditional TLS model, but can be configured
with --with_tls={trad,desc}. The choice can be revisited once toolchain
and libc support ships.

[1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.

gcc/Changelog:
    * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
    * config.gcc: Add --with_tls configuration option to change the default
    TLS flavor.
    * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
    -mtls-dialect and with_tls defaults.
    * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the two TLS
    flavors.
    * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
    * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
    * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction sequence
    length data for TLSDESC.
    (riscv_legitimize_tls_address): Add lowering of TLSDESC.
---
No regression in gcc tests for rv64gc, tested alongside the binutils and
glibc implementation. Tested with --with_tls=desc.

v2: Add with_tls configuration option, and a few readability improvements.
    Added Changelog.
    Thanks Kito Cheng for the review.

This contribution is made on behalf of Blue Whale Systems, which has
copyright assignment on file with the FSF.

 gcc/config.gcc                  | 15 ++++++++++++++-
 gcc/config/riscv/riscv-opts.h   |  6 ++++++
 gcc/config/riscv/riscv-protos.h |  5 +++--
 gcc/config/riscv/riscv.cc       | 24 ++++++++++++++++++++----
 gcc/config/riscv/riscv.h        |  9 +++++++--
 gcc/config/riscv/riscv.md       | 21 ++++++++++++++++++++-
 gcc/config/riscv/riscv.opt      | 14 ++++++++++++++
 7 files changed, 84 insertions(+), 10 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 415e0e1ebc5..86df7b89016 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2434,6 +2434,7 @@ riscv*-*-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:-trad}
 	;;
 riscv*-*-elf* | riscv*-*-rtems*)
 	tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
@@ -2476,6 +2477,7 @@ riscv*-*-freebsd*)
 	# 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:-trad}
 	;;
 
 loongarch*-*-linux*)
@@ -4566,7 +4568,7 @@ case "${target}" in
 		;;
 
 	riscv*-*-*)
-		supported_defaults="abi arch tune riscv_attribute isa_spec"
+		supported_defaults="abi arch tune riscv_attribute isa_spec tls"
 
 		case "${target}" in
 		riscv-* | riscv32*) xlen=32 ;;
@@ -4694,6 +4696,17 @@ case "${target}" in
 				;;
 			esac
 		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
 
 		# Handle --with-multilib-list.
 		if test "x${with_multilib_list}" != xdefault; then
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 378a17699cd..db03f35430a 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -319,4 +319,10 @@ enum riscv_entity
 #define TARGET_VECTOR_VLS                                                      \
   (TARGET_VECTOR && riscv_autovec_preference == RVV_SCALABLE)
 
+/* TLS types.  */
+enum riscv_tls_type {
+  TLS_TRADITIONAL,
+  TLS_DESCRIPTORS
+};
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 472c00dc439..9b7471f7591 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -33,9 +33,10 @@ enum riscv_symbol_type {
   SYMBOL_TLS,
   SYMBOL_TLS_LE,
   SYMBOL_TLS_IE,
-  SYMBOL_TLS_GD
+  SYMBOL_TLS_GD,
+  SYMBOL_TLSDESC,
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
 
 /* Classifies an address.
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 49062bef9fc..c158e224aaa 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -799,6 +799,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
+    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
     default: gcc_unreachable ();
     }
@@ -1734,7 +1735,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
 static rtx
 riscv_legitimize_tls_address (rtx loc)
 {
-  rtx dest, tp, tmp;
+  rtx dest, tp, tmp, a0;
   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
 
 #if 0
@@ -1750,9 +1751,24 @@ riscv_legitimize_tls_address (rtx loc)
       /* Rely on section anchors for the optimization that LDM TLS
 	 provides.  The anchor's address is loaded with GD TLS. */
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
+      if (TARGET_TLSDESC)
+	{
+	  static unsigned seqno;
+	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+	  dest = gen_reg_rtx (Pmode);
+
+	  emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
+	  emit_insn (gen_add3_insn (dest, a0, tp));
+	  seqno++;
+	}
+      else
+	{
+	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
+	  dest = gen_reg_rtx (Pmode);
+	  emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
+			      loc);
+	}
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index e18a0081297..faea78f5f4c 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -59,6 +59,7 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
    --with-abi is ignored if -mabi is specified.
    --with-tune is ignored if -mtune or -mcpu is specified.
    --with-isa-spec is ignored if -misa-spec is specified.
+   --with-tls is ignored if -mtls-dialect is specified.
 
    But using default -march/-mtune value if -mcpu don't have valid option.  */
 #define OPTION_DEFAULT_SPECS \
@@ -68,8 +69,9 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
   {"arch", "%{!march=*:"						\
 	   "  %{!mcpu=*:-march=%(VALUE)}"				\
 	   "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },	\
-  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
-  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
+  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },				\
+  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },			\
+  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},         	\
 
 #ifdef IN_LIBGCC2
 #undef TARGET_64BIT
@@ -1122,4 +1124,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
 #define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_VECTOR)
 #define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE, riscv_vector::FRM_NONE}
 
+/* Check TLS Descriptors mechanism is selected.  */
+#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index b456fa6abb3..aaef9cd429b 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -47,7 +47,7 @@
   UNSPEC_TLS_LE
   UNSPEC_TLS_IE
   UNSPEC_TLS_GD
-
+  UNSPEC_TLSDESC
   ;; High part of PC-relative address.
   UNSPEC_AUIPC
 
@@ -121,6 +121,7 @@
    (T1_REGNUM			6)
    (S0_REGNUM			8)
    (S1_REGNUM			9)
+   (A0_REGNUM			10)
    (S2_REGNUM			18)
    (S3_REGNUM			19)
    (S4_REGNUM			20)
@@ -1869,6 +1870,24 @@
   [(set_attr "got" "load")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "@tlsdesc<mode>"
+  [(set (reg:P A0_REGNUM)
+	    (unspec:P
+			[(match_operand:P 0 "symbolic_operand" "")
+			 (match_operand:P 1 "const_int_operand")]
+			UNSPEC_TLSDESC))
+   (clobber (reg:SI T0_REGNUM))]
+  "TARGET_TLSDESC"
+  {
+    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
+           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
+           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
+           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
+  }
+  [(set_attr "type" "multi")
+   (set_attr "length" "16")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "auipc<mode>"
   [(set (match_operand:P           0 "register_operand" "=r")
 	(unspec:P
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 6304efebfd5..9ba690f8497 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -311,3 +311,17 @@ Enum(riscv_autovec_lmul) String(m8) Value(RVV_M8)
 -param=riscv-autovec-lmul=
 Target RejectNegative Joined Enum(riscv_autovec_lmul) Var(riscv_autovec_lmul) Init(RVV_M1)
 -param=riscv-autovec-lmul=<string>	Set the RVV LMUL of auto-vectorization in the RISC-V port.
+
+Enum
+Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
+Specify TLS dialect.
-- 
2.42.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-09-08 10:49 ` [PATCH v2] " Tatsuyuki Ishi
@ 2023-10-02 14:10   ` Kito Cheng
  2023-11-16  1:17     ` Fangrui Song
  2023-11-16  1:07   ` Jeff Law
  1 sibling, 1 reply; 26+ messages in thread
From: Kito Cheng @ 2023-10-02 14:10 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, rui314, ruiu

Just one nit and one more comment for doc:

Could you add some doc something like that? mostly I grab from other
target, so you can just included in the patch.

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 31f2234640f..39396668da2 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1174,6 +1174,9 @@ Specify the default TLS dialect, for systems
were there is a choice.
For ARM targets, possible values for @var{dialect} are @code{gnu} or
@code{gnu2}, which select between the original GNU dialect and the GNU TLS
descriptor-based dialect.
+For RISC-V targets, possible values for @var{dialect} are @code{trad} or
+@code{desc}, which select between the traditional GNU dialect and the GNU TLS
+descriptor-based dialect.

@item --enable-multiarch
Specify whether to enable or disable multiarch support.  The default is
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4085fc90907..459e266d426 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1239,7 +1239,8 @@ See RS/6000 and PowerPC Options.
-minline-atomics  -mno-inline-atomics
-minline-strlen  -mno-inline-strlen
-minline-strcmp  -mno-inline-strcmp
--minline-strncmp  -mno-inline-strncmp}
+-minline-strncmp  -mno-inline-strncmp
+-mtls-dialect=desc  -mtls-dialect=trad}

@emph{RL78 Options}
@gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
@@ -29538,6 +29539,17 @@ which register to use as base register for
reading the canary,
and from what offset from that base register. There is no default
register or offset as this is entirely for use within the Linux
kernel.
+
+@opindex mtls-dialect=desc
+@item -mtls-dialect=desc
+Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
+of TLS variables.  This is the default.
+
+@opindex mtls-dialect=trad
+@item -mtls-dialect=traditional
+Use traditional TLS as the thread-local storage mechanism for dynamic accesses
+of TLS variables.
+
@end table

@node RL78 Options




> +(define_insn "@tlsdesc<mode>"
> +  [(set (reg:P A0_REGNUM)
> +           (unspec:P
> +                       [(match_operand:P 0 "symbolic_operand" "")
> +                        (match_operand:P 1 "const_int_operand")]
> +                       UNSPEC_TLSDESC))
> +   (clobber (reg:SI T0_REGNUM))]

P rather than SI here.

> +  "TARGET_TLSDESC"
> +  {
> +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
> +  }
> +  [(set_attr "type" "multi")
> +   (set_attr "length" "16")
> +   (set_attr "mode" "<MODE>")])
> +
>  (define_insn "auipc<mode>"
>    [(set (match_operand:P           0 "register_operand" "=r")
>         (unspec:P

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-09-08 10:49 ` [PATCH v2] " Tatsuyuki Ishi
  2023-10-02 14:10   ` Kito Cheng
@ 2023-11-16  1:07   ` Jeff Law
  2023-11-16  1:51     ` Tatsuyuki Ishi
  1 sibling, 1 reply; 26+ messages in thread
From: Jeff Law @ 2023-11-16  1:07 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, rui314, ruiu, kito.cheng



On 9/8/23 04:49, Tatsuyuki Ishi via Gcc-patches wrote:
> This implements TLS Descriptors (TLSDESC) as specified in [1].
> 
> In TLSDESC instruction sequence, the first instruction relocates against
> the target TLS variable, while subsequent instructions relocates against
> the address of the first. Such usage of labels are not well-supported
> within GCC. Due to this, the 4-instruction sequence is implemented as a
> single RTX insn.
> 
> The default remains to be the traditional TLS model, but can be configured
> with --with_tls={trad,desc}. The choice can be revisited once toolchain
> and libc support ships.
> 
> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
> 
> gcc/Changelog:
>      * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
>      * config.gcc: Add --with_tls configuration option to change the default
>      TLS flavor.
>      * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
>      -mtls-dialect and with_tls defaults.
>      * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the two TLS
>      flavors.
>      * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
>      * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
>      * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction sequence
>      length data for TLSDESC.
>      (riscv_legitimize_tls_address): Add lowering of TLSDESC.
> ---

> @@ -4694,6 +4696,17 @@ case "${target}" in
>   				;;
>   			esac
>   		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
Is there a reason why this isn't formatted like the other cases?




> @@ -1869,6 +1870,24 @@
>     [(set_attr "got" "load")
>      (set_attr "mode" "<MODE>")])
>   
> +(define_insn "@tlsdesc<mode>"
> +  [(set (reg:P A0_REGNUM)
> +	    (unspec:P
> +			[(match_operand:P 0 "symbolic_operand" "")
> +			 (match_operand:P 1 "const_int_operand")]
> +			UNSPEC_TLSDESC))
> +   (clobber (reg:SI T0_REGNUM))]
> +  "TARGET_TLSDESC"
> +  {
> +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
> +  }
> +  [(set_attr "type" "multi")
> +   (set_attr "length" "16")
> +   (set_attr "mode" "<MODE>")])
Hmm, I would be a bit worried about explicitly using $a0 here.  That's 
generally frowned upon, but probably unavoidable in this case since this 
is a call under the hood.


This needs changes to invoke.texi since it introduces new options.  I 
don't think it has to be anything terribly verbose.  A one liner is 
probably sufficient and I wouldn't be surprised if other ports have 
suitable text we could copy.

So overall if Kito's OK, then I am with the trivial doc change and 
perhaps the formatting fix in config.guess.

jeff

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-10-02 14:10   ` Kito Cheng
@ 2023-11-16  1:17     ` Fangrui Song
  2023-11-16  1:39       ` Tatsuyuki Ishi
  2023-11-16  5:18       ` Jeff Law
  0 siblings, 2 replies; 26+ messages in thread
From: Fangrui Song @ 2023-11-16  1:17 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: Kito Cheng, gcc-patches, rui314, ruiu, Jeff Law

On Mon, Oct 2, 2023 at 7:10 AM Kito Cheng <kito.cheng@gmail.com> wrote:
>
> Just one nit and one more comment for doc:
>
> Could you add some doc something like that? mostly I grab from other
> target, so you can just included in the patch.
>
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index 31f2234640f..39396668da2 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -1174,6 +1174,9 @@ Specify the default TLS dialect, for systems
> were there is a choice.
> For ARM targets, possible values for @var{dialect} are @code{gnu} or
> @code{gnu2}, which select between the original GNU dialect and the GNU TLS
> descriptor-based dialect.
> +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
> +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
> +descriptor-based dialect.
>
> @item --enable-multiarch
> Specify whether to enable or disable multiarch support.  The default is
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 4085fc90907..459e266d426 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1239,7 +1239,8 @@ See RS/6000 and PowerPC Options.
> -minline-atomics  -mno-inline-atomics
> -minline-strlen  -mno-inline-strlen
> -minline-strcmp  -mno-inline-strcmp
> --minline-strncmp  -mno-inline-strncmp}
> +-minline-strncmp  -mno-inline-strncmp
> +-mtls-dialect=desc  -mtls-dialect=trad}
>
> @emph{RL78 Options}
> @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
> @@ -29538,6 +29539,17 @@ which register to use as base register for
> reading the canary,
> and from what offset from that base register. There is no default
> register or offset as this is entirely for use within the Linux
> kernel.
> +
> +@opindex mtls-dialect=desc
> +@item -mtls-dialect=desc
> +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.  This is the default.
> +
> +@opindex mtls-dialect=trad
> +@item -mtls-dialect=traditional

-mtls-dialect=trad.
aarch64-linux-gnu-gcc doesn't support -mtls-dialect=traditional

> +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.
> +
> @end table

This is the default :)

I am happy that we change the default like AArch64, but probably not
now when linker support is not widely available yet.

I cannot comment on the code side as I am not familiar with GCC internals.

> @node RL78 Options
>
>
>
>
> > +(define_insn "@tlsdesc<mode>"
> > +  [(set (reg:P A0_REGNUM)
> > +           (unspec:P
> > +                       [(match_operand:P 0 "symbolic_operand" "")
> > +                        (match_operand:P 1 "const_int_operand")]
> > +                       UNSPEC_TLSDESC))
> > +   (clobber (reg:SI T0_REGNUM))]
>
> P rather than SI here.
>
> > +  "TARGET_TLSDESC"
> > +  {
> > +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
> > +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
> > +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
> > +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
> > +  }
> > +  [(set_attr "type" "multi")
> > +   (set_attr "length" "16")
> > +   (set_attr "mode" "<MODE>")])
> > +
> >  (define_insn "auipc<mode>"
> >    [(set (match_operand:P           0 "register_operand" "=r")
> >         (unspec:P

It seems that x86-64 supports non-adjacent code sequence. Writing the
pattern this way does not allow interleaving, but I assume
interleaving doesn't enable much.
https://reviews.llvm.org/D114416


-- 
宋方睿

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  1:17     ` Fangrui Song
@ 2023-11-16  1:39       ` Tatsuyuki Ishi
  2023-11-16  5:21         ` Jeff Law
  2023-11-16  5:18       ` Jeff Law
  1 sibling, 1 reply; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-11-16  1:39 UTC (permalink / raw)
  To: Fangrui Song; +Cc: Kito Cheng, gcc-patches, Rui Ueyama, ruiu, Jeff Law

[-- Attachment #1: Type: text/plain, Size: 4116 bytes --]

> On Nov 16, 2023, at 10:17, Fangrui Song <maskray@google.com> wrote:
> 
> On Mon, Oct 2, 2023 at 7:10 AM Kito Cheng <kito.cheng@gmail.com <mailto:kito.cheng@gmail.com>> wrote:
>> 
>> Just one nit and one more comment for doc:
>> 
>> Could you add some doc something like that? mostly I grab from other
>> target, so you can just included in the patch.
>> 
>> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
>> index 31f2234640f..39396668da2 100644
>> --- a/gcc/doc/install.texi
>> +++ b/gcc/doc/install.texi
>> @@ -1174,6 +1174,9 @@ Specify the default TLS dialect, for systems
>> were there is a choice.
>> For ARM targets, possible values for @var{dialect} are @code{gnu} or
>> @code{gnu2}, which select between the original GNU dialect and the GNU TLS
>> descriptor-based dialect.
>> +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
>> +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
>> +descriptor-based dialect.
>> 
>> @item --enable-multiarch
>> Specify whether to enable or disable multiarch support.  The default is
>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>> index 4085fc90907..459e266d426 100644
>> --- a/gcc/doc/invoke.texi
>> +++ b/gcc/doc/invoke.texi
>> @@ -1239,7 +1239,8 @@ See RS/6000 and PowerPC Options.
>> -minline-atomics  -mno-inline-atomics
>> -minline-strlen  -mno-inline-strlen
>> -minline-strcmp  -mno-inline-strcmp
>> --minline-strncmp  -mno-inline-strncmp}
>> +-minline-strncmp  -mno-inline-strncmp
>> +-mtls-dialect=desc  -mtls-dialect=trad}
>> 
>> @emph{RL78 Options}
>> @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
>> @@ -29538,6 +29539,17 @@ which register to use as base register for
>> reading the canary,
>> and from what offset from that base register. There is no default
>> register or offset as this is entirely for use within the Linux
>> kernel.
>> +
>> +@opindex mtls-dialect=desc
>> +@item -mtls-dialect=desc
>> +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
>> +of TLS variables.  This is the default.
>> +
>> +@opindex mtls-dialect=trad
>> +@item -mtls-dialect=traditional
> 
> -mtls-dialect=trad.
> aarch64-linux-gnu-gcc doesn't support -mtls-dialect=traditional
> 
>> +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
>> +of TLS variables.
>> +
>> @end table
> 
> This is the default :)
> 
> I am happy that we change the default like AArch64, but probably not
> now when linker support is not widely available yet.
> 
> I cannot comment on the code side as I am not familiar with GCC internals.
> 
>> @node RL78 Options
>> 
>> 
>> 
>> 
>>> +(define_insn "@tlsdesc<mode>"
>>> +  [(set (reg:P A0_REGNUM)
>>> +           (unspec:P
>>> +                       [(match_operand:P 0 "symbolic_operand" "")
>>> +                        (match_operand:P 1 "const_int_operand")]
>>> +                       UNSPEC_TLSDESC))
>>> +   (clobber (reg:SI T0_REGNUM))]
>> 
>> P rather than SI here.
>> 
>>> +  "TARGET_TLSDESC"
>>> +  {
>>> +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
>>> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
>>> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
>>> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
>>> +  }
>>> +  [(set_attr "type" "multi")
>>> +   (set_attr "length" "16")
>>> +   (set_attr "mode" "<MODE>")])
>>> +
>>> (define_insn "auipc<mode>"
>>>   [(set (match_operand:P           0 "register_operand" "=r")
>>>        (unspec:P
> 
> It seems that x86-64 supports non-adjacent code sequence. Writing the
> pattern this way does not allow interleaving, but I assume
> interleaving doesn't enable much.
> https://reviews.llvm.org/D114416

As mentioned in the commit message, the use of relaxation-only labels does not seem well supported in current GCC. Creating a label seems to force a basic block and I’m not sure how we can avoid it.

If there’s a better way to implement this I’m happy to adopt.

Tatsuyuki.

> 
> -- 
> 宋方睿


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  1:07   ` Jeff Law
@ 2023-11-16  1:51     ` Tatsuyuki Ishi
  2023-11-16  5:23       ` Jeff Law
  0 siblings, 1 reply; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-11-16  1:51 UTC (permalink / raw)
  To: Jeff Law; +Cc: gcc-patches, Rui Ueyama, ruiu, kito.cheng

[-- Attachment #1: Type: text/plain, Size: 4332 bytes --]

> On Nov 16, 2023, at 10:07, Jeff Law <jeffreyalaw@gmail.com> wrote:
> 
> 
> 
> On 9/8/23 04:49, Tatsuyuki Ishi via Gcc-patches wrote:
>> This implements TLS Descriptors (TLSDESC) as specified in [1].
>> In TLSDESC instruction sequence, the first instruction relocates against
>> the target TLS variable, while subsequent instructions relocates against
>> the address of the first. Such usage of labels are not well-supported
>> within GCC. Due to this, the 4-instruction sequence is implemented as a
>> single RTX insn.
>> The default remains to be the traditional TLS model, but can be configured
>> with --with_tls={trad,desc}. The choice can be revisited once toolchain
>> and libc support ships.
>> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
>> gcc/Changelog:
>>     * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
>>     * config.gcc: Add --with_tls configuration option to change the default
>>     TLS flavor.
>>     * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
>>     -mtls-dialect and with_tls defaults.
>>     * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the two TLS
>>     flavors.
>>     * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
>>     * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
>>     * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction sequence
>>     length data for TLSDESC.
>>     (riscv_legitimize_tls_address): Add lowering of TLSDESC.
>> ---
> 
>> @@ -4694,6 +4696,17 @@ case "${target}" in
>>  				;;
>>  			esac
>>  		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
> Is there a reason why this isn't formatted like the other cases?

Sorry, this was an oversight. I’ll fix it in the next version.

> 
>> @@ -1869,6 +1870,24 @@
>>    [(set_attr "got" "load")
>>     (set_attr "mode" "<MODE>")])
>>  +(define_insn "@tlsdesc<mode>"
>> +  [(set (reg:P A0_REGNUM)
>> +	    (unspec:P
>> +			[(match_operand:P 0 "symbolic_operand" "")
>> +			 (match_operand:P 1 "const_int_operand")]
>> +			UNSPEC_TLSDESC))
>> +   (clobber (reg:SI T0_REGNUM))]
>> +  "TARGET_TLSDESC"
>> +  {
>> +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
>> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
>> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
>> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
>> +  }
>> +  [(set_attr "type" "multi")
>> +   (set_attr "length" "16")
>> +   (set_attr "mode" "<MODE>")])
> Hmm, I would be a bit worried about explicitly using $a0 here.  That's generally frowned upon, but probably unavoidable in this case since this is a call under the hood.

Based on what I have read in the AArch64 backend, there are two ways to do this: introduce a custom calling convention, or put in a RTX insn that covers the whole sequence. Ideally we should do the first, but then there’s the label issue and it’s quite a bit more complicated. So I’m sticking with this for now.

> This needs changes to invoke.texi since it introduces new options.  I don't think it has to be anything terribly verbose.  A one liner is probably sufficient and I wouldn't be surprised if other ports have suitable text we could copy.

Ack.

> So overall if Kito's OK, then I am with the trivial doc change and perhaps the formatting fix in config.guess.

Sorry for all the delay on this. My progress has been (and still) blocked on supporting relaxation of TLSDESC in binutils (turns out you can’t run static binaries without relaxing it first). But that doesn’t seem exactly easy to do either, because relaxation that involves GOT elimination isn’t something we have in the RISC-V backend.

I’ll try to send a new version of this patch and get this unblocked on GCC side first.
Presumably this still needs the associated gas and ld support in place, so let me know if you want to merge this soon. I will ask on binutils for whether they could accept the basic part of the implementation without relaxation first.

Thanks,
Tatsuyuki. 

> jeff


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  1:17     ` Fangrui Song
  2023-11-16  1:39       ` Tatsuyuki Ishi
@ 2023-11-16  5:18       ` Jeff Law
  1 sibling, 0 replies; 26+ messages in thread
From: Jeff Law @ 2023-11-16  5:18 UTC (permalink / raw)
  To: Fangrui Song, Tatsuyuki Ishi; +Cc: Kito Cheng, gcc-patches, rui314, ruiu



On 11/15/23 18:17, Fangrui Song wrote:

> 
> It seems that x86-64 supports non-adjacent code sequence. Writing the
> pattern this way does not allow interleaving, but I assume
> interleaving doesn't enable much.
It's of marginal benefit.  We could always split them before scheduling 
if it turned out to matter -- but given nobody's using this stuff yet, 
my inclination is to wait on that kind of micro-optimization.

jeff

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  1:39       ` Tatsuyuki Ishi
@ 2023-11-16  5:21         ` Jeff Law
  0 siblings, 0 replies; 26+ messages in thread
From: Jeff Law @ 2023-11-16  5:21 UTC (permalink / raw)
  To: Tatsuyuki Ishi, Fangrui Song; +Cc: Kito Cheng, gcc-patches, Rui Ueyama, ruiu



On 11/15/23 18:39, Tatsuyuki Ishi wrote:

> 
> As mentioned in the commit message, the use of relaxation-only labels 
> does not seem well supported in current GCC. Creating a label seems to 
> force a basic block and I’m not sure how we can avoid it.
> 
> If there’s a better way to implement this I’m happy to adopt.
In general, yes creating a label in the IL is going to create a new 
block.  But you could emit the label as part of the auipc so that it 
doesn't really show up in the IL.  Then you have to make sure the other 
insns reference the right label, which is certainly do-able.   THere's 
also linker relaxing to worry about....

jeff

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  1:51     ` Tatsuyuki Ishi
@ 2023-11-16  5:23       ` Jeff Law
  2023-11-16  5:33         ` Fangrui Song
  0 siblings, 1 reply; 26+ messages in thread
From: Jeff Law @ 2023-11-16  5:23 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, Rui Ueyama, ruiu, kito.cheng



On 11/15/23 18:51, Tatsuyuki Ishi wrote:
>> On Nov 16, 2023, at 10:07, Jeff Law <jeffreyalaw@gmail.com> wrote:

> 
> Based on what I have read in the AArch64 backend, there are two ways to 
> do this: introduce a custom calling convention, or put in a RTX insn 
> that covers the whole sequence. Ideally we should do the first, but then 
> there’s the label issue and it’s quite a bit more complicated. So I’m 
> sticking with this for now.
As I said, I think we're OK here.  We can always revamp as we get 
experience with the implementation -- I don't think any of the stuff 
we're talking about is an ABI change, they're just implementation details.

> 
> Sorry for all the delay on this. My progress has been (and still) 
> blocked on supporting relaxation of TLSDESC in binutils (turns out you 
> can’t run static binaries without relaxing it first). But that doesn’t 
> seem exactly easy to do either, because relaxation that involves GOT 
> elimination isn’t something we have in the RISC-V backend.
Note that binutils is due for another release in the next month or two. 
It'd certainly be helpful to have any issues there resolved in time for 
that release.

> 
> I’ll try to send a new version of this patch and get this unblocked on 
> GCC side first.
Sounds good.  We can always guard its use behind a feature test for GAS 
support.

Jeff

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  5:23       ` Jeff Law
@ 2023-11-16  5:33         ` Fangrui Song
  2023-11-16  5:36           ` Jeff Law
  2023-11-16  5:37           ` Tatsuyuki Ishi
  0 siblings, 2 replies; 26+ messages in thread
From: Fangrui Song @ 2023-11-16  5:33 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, Jeff Law, Rui Ueyama, ruiu, kito.cheng

On Wed, Nov 15, 2023 at 9:23 PM Jeff Law <jeffreyalaw@gmail.com> wrote:
>
>
>
> On 11/15/23 18:51, Tatsuyuki Ishi wrote:
> >> On Nov 16, 2023, at 10:07, Jeff Law <jeffreyalaw@gmail.com> wrote:
>
> >
> > Based on what I have read in the AArch64 backend, there are two ways to
> > do this: introduce a custom calling convention, or put in a RTX insn
> > that covers the whole sequence. Ideally we should do the first, but then
> > there’s the label issue and it’s quite a bit more complicated. So I’m
> > sticking with this for now.
> As I said, I think we're OK here.  We can always revamp as we get
> experience with the implementation -- I don't think any of the stuff
> we're talking about is an ABI change, they're just implementation details.
>
> >
> > Sorry for all the delay on this. My progress has been (and still)
> > blocked on supporting relaxation of TLSDESC in binutils (turns out you
> > can’t run static binaries without relaxing it first). But that doesn’t
> > seem exactly easy to do either, because relaxation that involves GOT
> > elimination isn’t something we have in the RISC-V backend.
> Note that binutils is due for another release in the next month or two.
> It'd certainly be helpful to have any issues there resolved in time for
> that release.
>
> >
> > I’ll try to send a new version of this patch and get this unblocked on
> > GCC side first.
> Sounds good.  We can always guard its use behind a feature test for GAS
> support.
>
> Jeff

Agreed.


Tatsuyuki, could you also add some tests? For example

// end of https://maskray.me/blog/2021-02-14-all-about-thread-local-storage
__thread int tls0;
extern __thread int tls1;
int foo() { return ++tls0 + ++tls1; }
static __thread int tls2, tls3;
int bar() { return ++tls2 + ++tls3; }

I have used this to check rtld and linker behavior. I think we need
some `scan-assembler`.
To make it a runnable test, some assembler feature check may be
needed. Perhaps Jeff can make some suggestion or contribute code!




-- 
宋方睿

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  5:33         ` Fangrui Song
@ 2023-11-16  5:36           ` Jeff Law
  2023-11-16  5:37           ` Tatsuyuki Ishi
  1 sibling, 0 replies; 26+ messages in thread
From: Jeff Law @ 2023-11-16  5:36 UTC (permalink / raw)
  To: Fangrui Song, Tatsuyuki Ishi; +Cc: gcc-patches, Rui Ueyama, ruiu, kito.cheng



On 11/15/23 22:33, Fangrui Song wrote:

> 
> I have used this to check rtld and linker behavior. I think we need
> some `scan-assembler`.
> To make it a runnable test, some assembler feature check may be
> needed. Perhaps Jeff can make some suggestion or contribute code!
TLS isn't really on my radar yet.  I've got about a million things to do 
on the scalar and vector optimization fronts.  The TLS stuff is just one 
of the lingering items from our Tuesday patchwork sync meetings -- 
getting it wrapped up gets it off the list of things to look at every 
week ;-)


jeff

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v2] RISC-V: Implement TLS Descriptors.
  2023-11-16  5:33         ` Fangrui Song
  2023-11-16  5:36           ` Jeff Law
@ 2023-11-16  5:37           ` Tatsuyuki Ishi
  1 sibling, 0 replies; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-11-16  5:37 UTC (permalink / raw)
  To: Fangrui Song; +Cc: gcc-patches, Jeff Law, Rui Ueyama, Rui Ueyama, Kito Cheng

> On Nov 16, 2023, at 14:33, Fangrui Song <maskray@google.com> wrote:
> 
> On Wed, Nov 15, 2023 at 9:23 PM Jeff Law <jeffreyalaw@gmail.com> wrote:
>> 
>> 
>> 
>> On 11/15/23 18:51, Tatsuyuki Ishi wrote:
>>>> On Nov 16, 2023, at 10:07, Jeff Law <jeffreyalaw@gmail.com> wrote:
>> 
>>> 
>>> Based on what I have read in the AArch64 backend, there are two ways to
>>> do this: introduce a custom calling convention, or put in a RTX insn
>>> that covers the whole sequence. Ideally we should do the first, but then
>>> there’s the label issue and it’s quite a bit more complicated. So I’m
>>> sticking with this for now.
>> As I said, I think we're OK here.  We can always revamp as we get
>> experience with the implementation -- I don't think any of the stuff
>> we're talking about is an ABI change, they're just implementation details.
>> 
>>> 
>>> Sorry for all the delay on this. My progress has been (and still)
>>> blocked on supporting relaxation of TLSDESC in binutils (turns out you
>>> can’t run static binaries without relaxing it first). But that doesn’t
>>> seem exactly easy to do either, because relaxation that involves GOT
>>> elimination isn’t something we have in the RISC-V backend.
>> Note that binutils is due for another release in the next month or two.
>> It'd certainly be helpful to have any issues there resolved in time for
>> that release.
>> 
>>> 
>>> I’ll try to send a new version of this patch and get this unblocked on
>>> GCC side first.
>> Sounds good.  We can always guard its use behind a feature test for GAS
>> support.
>> 
>> Jeff
> 
> Agreed.
> 
> 
> Tatsuyuki, could you also add some tests? For example
> 
> // end of https://maskray.me/blog/2021-02-14-all-about-thread-local-storage
> __thread int tls0;
> extern __thread int tls1;
> int foo() { return ++tls0 + ++tls1; }
> static __thread int tls2, tls3;
> int bar() { return ++tls2 + ++tls3; }
> 
> I have used this to check rtld and linker behavior. I think we need
> some `scan-assembler`.
> To make it a runnable test, some assembler feature check may be
> needed. Perhaps Jeff can make some suggestion or contribute code!
> 

I believe there’s existing platform-generic TLS coverage in gcc/testsuite/gcc.dg/torture/tls. GCC's test suite seems pretty sparse, but a lot more testing is done by glibc’s testsuite (which is also where I found the static TLS relaxation issue).

Tatsuyuki.

> 
> -- 
> 宋方睿


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v3] RISC-V: Implement TLS Descriptors.
  2023-08-17 18:12 [PATCH] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
  2023-08-29 13:40 ` Kito Cheng
  2023-09-08 10:49 ` [PATCH v2] " Tatsuyuki Ishi
@ 2023-11-20 13:17 ` Tatsuyuki Ishi
  2023-11-21  6:59   ` Fangrui Song
  2023-11-23 10:57   ` Florian Weimer
  2023-12-05  7:01 ` [PATCH v4] " Tatsuyuki Ishi
  2024-03-29  5:52 ` [PATCH v5] " Tatsuyuki Ishi
  4 siblings, 2 replies; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-11-20 13:17 UTC (permalink / raw)
  To: ishitatsuyuki; +Cc: gcc-patches, rui314, ruiu, kito.cheng, jeffreyalaw

This implements TLS Descriptors (TLSDESC) as specified in [1].

The 4-instruction sequence is implemented as a single RTX insn for
simplicity, but this can be revisited later if instruction scheduling or
more flexible RA is desired.

The default remains to be the traditional TLS model, but can be configured
with --with_tls={trad,desc}. The choice can be revisited once toolchain
and libc support ships.

[1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.

gcc/Changelog:
	* config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
	* config.gcc: Add --with_tls configuration option to change the
	default TLS flavor.
	* config/riscv/riscv.h: Add TARGET_TLSDESC determined from
	-mtls-dialect and with_tls defaults.
	* config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
	two TLS flavors.
	* config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
	* config/riscv/riscv.md: Add instruction sequence for TLSDESC.
	* config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
	sequence length data for TLSDESC.
	(riscv_legitimize_tls_address): Add lowering of TLSDESC.
	* doc/install.texi: Document --with-tls for RISC-V.
	* doc/invoke.texi: Document --mtls-dialect for RISC-V.
---
No regression in gcc tests for rv64gc, tested alongside the binutils and
glibc implementation. Tested with --with_tls=desc.

v2: Add with_tls configuration option, and a few readability improvements.
    Added Changelog.
v3: Add documentation per Kito's suggestion.
    Fix minor issues pointed out by Kito and Jeff.
    Thanks Kito Cheng and Jeff Law for review.

I've considered gating this behind a GAS feature test, but it seems
nontrivial especially for restricting the variants available at runtime.
Since TLS descriptors is not selected by default, I've decided to leave it
ungated.

In other news, I have made some progress on binutils side, and I'll try to
update the GAS / ld patch set with relaxation included, by the end of this
month.

 gcc/config.gcc                  | 15 ++++++++++++++-
 gcc/config/riscv/riscv-opts.h   |  6 ++++++
 gcc/config/riscv/riscv-protos.h |  5 +++--
 gcc/config/riscv/riscv.cc       | 24 ++++++++++++++++++++----
 gcc/config/riscv/riscv.h        |  9 +++++++--
 gcc/config/riscv/riscv.md       | 21 ++++++++++++++++++++-
 gcc/config/riscv/riscv.opt      | 14 ++++++++++++++
 gcc/doc/install.texi            |  3 +++
 gcc/doc/invoke.texi             | 13 ++++++++++++-
 9 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 415e0e1ebc5..2c1a7179b02 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2434,6 +2434,7 @@ riscv*-*-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:-trad}
 	;;
 riscv*-*-elf* | riscv*-*-rtems*)
 	tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
@@ -2476,6 +2477,7 @@ riscv*-*-freebsd*)
 	# 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:-trad}
 	;;
 
 loongarch*-*-linux*)
@@ -4566,7 +4568,7 @@ case "${target}" in
 		;;
 
 	riscv*-*-*)
-		supported_defaults="abi arch tune riscv_attribute isa_spec"
+		supported_defaults="abi arch tune riscv_attribute isa_spec tls"
 
 		case "${target}" in
 		riscv-* | riscv32*) xlen=32 ;;
@@ -4694,6 +4696,17 @@ case "${target}" in
 				;;
 			esac
 		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
 
 		# Handle --with-multilib-list.
 		if test "x${with_multilib_list}" != xdefault; then
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 378a17699cd..db03f35430a 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -319,4 +319,10 @@ enum riscv_entity
 #define TARGET_VECTOR_VLS                                                      \
   (TARGET_VECTOR && riscv_autovec_preference == RVV_SCALABLE)
 
+/* TLS types.  */
+enum riscv_tls_type {
+  TLS_TRADITIONAL,
+  TLS_DESCRIPTORS
+};
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 472c00dc439..9b7471f7591 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -33,9 +33,10 @@ enum riscv_symbol_type {
   SYMBOL_TLS,
   SYMBOL_TLS_LE,
   SYMBOL_TLS_IE,
-  SYMBOL_TLS_GD
+  SYMBOL_TLS_GD,
+  SYMBOL_TLSDESC,
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
 
 /* Classifies an address.
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 49062bef9fc..c158e224aaa 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -799,6 +799,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
+    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
     default: gcc_unreachable ();
     }
@@ -1734,7 +1735,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
 static rtx
 riscv_legitimize_tls_address (rtx loc)
 {
-  rtx dest, tp, tmp;
+  rtx dest, tp, tmp, a0;
   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
 
 #if 0
@@ -1750,9 +1751,24 @@ riscv_legitimize_tls_address (rtx loc)
       /* Rely on section anchors for the optimization that LDM TLS
 	 provides.  The anchor's address is loaded with GD TLS. */
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
+      if (TARGET_TLSDESC)
+	{
+	  static unsigned seqno;
+	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+	  dest = gen_reg_rtx (Pmode);
+
+	  emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
+	  emit_insn (gen_add3_insn (dest, a0, tp));
+	  seqno++;
+	}
+      else
+	{
+	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
+	  dest = gen_reg_rtx (Pmode);
+	  emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
+			      loc);
+	}
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index e18a0081297..faea78f5f4c 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -59,6 +59,7 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
    --with-abi is ignored if -mabi is specified.
    --with-tune is ignored if -mtune or -mcpu is specified.
    --with-isa-spec is ignored if -misa-spec is specified.
+   --with-tls is ignored if -mtls-dialect is specified.
 
    But using default -march/-mtune value if -mcpu don't have valid option.  */
 #define OPTION_DEFAULT_SPECS \
@@ -68,8 +69,9 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
   {"arch", "%{!march=*:"						\
 	   "  %{!mcpu=*:-march=%(VALUE)}"				\
 	   "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },	\
-  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
-  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
+  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },				\
+  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },			\
+  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},         	\
 
 #ifdef IN_LIBGCC2
 #undef TARGET_64BIT
@@ -1122,4 +1124,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
 #define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_VECTOR)
 #define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE, riscv_vector::FRM_NONE}
 
+/* Check TLS Descriptors mechanism is selected.  */
+#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index b456fa6abb3..7c66c64b893 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -47,7 +47,7 @@
   UNSPEC_TLS_LE
   UNSPEC_TLS_IE
   UNSPEC_TLS_GD
-
+  UNSPEC_TLSDESC
   ;; High part of PC-relative address.
   UNSPEC_AUIPC
 
@@ -121,6 +121,7 @@
    (T1_REGNUM			6)
    (S0_REGNUM			8)
    (S1_REGNUM			9)
+   (A0_REGNUM			10)
    (S2_REGNUM			18)
    (S3_REGNUM			19)
    (S4_REGNUM			20)
@@ -1869,6 +1870,24 @@
   [(set_attr "got" "load")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "@tlsdesc<mode>"
+  [(set (reg:P A0_REGNUM)
+	    (unspec:P
+			[(match_operand:P 0 "symbolic_operand" "")
+			 (match_operand:P 1 "const_int_operand")]
+			UNSPEC_TLSDESC))
+   (clobber (reg:P T0_REGNUM))]
+  "TARGET_TLSDESC"
+  {
+    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
+           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
+           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
+           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
+  }
+  [(set_attr "type" "multi")
+   (set_attr "length" "16")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "auipc<mode>"
   [(set (match_operand:P           0 "register_operand" "=r")
 	(unspec:P
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 6304efebfd5..9ba690f8497 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -311,3 +311,17 @@ Enum(riscv_autovec_lmul) String(m8) Value(RVV_M8)
 -param=riscv-autovec-lmul=
 Target RejectNegative Joined Enum(riscv_autovec_lmul) Var(riscv_autovec_lmul) Init(RVV_M1)
 -param=riscv-autovec-lmul=<string>	Set the RVV LMUL of auto-vectorization in the RISC-V port.
+
+Enum
+Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
+Specify TLS dialect.
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index e099cd0b568..6ee533c0a40 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1174,6 +1174,9 @@ Specify the default TLS dialect, for systems were there is a choice.
 For ARM targets, possible values for @var{dialect} are @code{gnu} or
 @code{gnu2}, which select between the original GNU dialect and the GNU TLS
 descriptor-based dialect.
+For RISC-V targets, possible values for @var{dialect} are @code{trad} or
+@code{desc}, which select between the traditional GNU dialect and the GNU TLS
+descriptor-based dialect.
 
 @item --enable-multiarch
 Specify whether to enable or disable multiarch support.  The default is
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index f2c1067ab7d..77b82c46311 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1234,7 +1234,8 @@ See RS/6000 and PowerPC Options.
 -mstack-protector-guard=@var{guard}  -mstack-protector-guard-reg=@var{reg}
 -mstack-protector-guard-offset=@var{offset}
 -mcsr-check -mno-csr-check
--minline-atomics  -mno-inline-atomics}
+-minline-atomics  -mno-inline-atomics
+-mtls-dialect=desc  -mtls-dialect=trad}
 
 @emph{RL78 Options}
 @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
@@ -29403,6 +29404,16 @@ which register to use as base register for reading the canary,
 and from what offset from that base register. There is no default
 register or offset as this is entirely for use within the Linux
 kernel.
+
+@opindex mtls-dialect=desc
+@item -mtls-dialect=desc
+Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
+of TLS variables.
+
+@opindex mtls-dialect=trad
+@item -mtls-dialect=trad
+Use traditional TLS as the thread-local storage mechanism for dynamic accesses
+of TLS variables.  This is the default.
 @end table
 
 @node RL78 Options
-- 
2.42.1


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v3] RISC-V: Implement TLS Descriptors.
  2023-11-20 13:17 ` [PATCH v3] " Tatsuyuki Ishi
@ 2023-11-21  6:59   ` Fangrui Song
  2023-11-21  7:07     ` Tatsuyuki Ishi
  2023-12-05 16:49     ` Tatsuyuki Ishi
  2023-11-23 10:57   ` Florian Weimer
  1 sibling, 2 replies; 26+ messages in thread
From: Fangrui Song @ 2023-11-21  6:59 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, rui314, ruiu, kito.cheng, jeffreyalaw

On Mon, Nov 20, 2023 at 6:20 AM Tatsuyuki Ishi <ishitatsuyuki@gmail.com> wrote:
>
> This implements TLS Descriptors (TLSDESC) as specified in [1].
>
> The 4-instruction sequence is implemented as a single RTX insn for
> simplicity, but this can be revisited later if instruction scheduling or
> more flexible RA is desired.
>
> The default remains to be the traditional TLS model, but can be configured
> with --with_tls={trad,desc}. The choice can be revisited once toolchain
> and libc support ships.
>
> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
>
> gcc/Changelog:
>         * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
>         * config.gcc: Add --with_tls configuration option to change the
>         default TLS flavor.
>         * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
>         -mtls-dialect and with_tls defaults.
>         * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
>         two TLS flavors.
>         * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
>         * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
>         * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
>         sequence length data for TLSDESC.
>         (riscv_legitimize_tls_address): Add lowering of TLSDESC.
>         * doc/install.texi: Document --with-tls for RISC-V.
>         * doc/invoke.texi: Document --mtls-dialect for RISC-V.

Nit: One dash for --mtls-dialect.

> ---
> No regression in gcc tests for rv64gc, tested alongside the binutils and
> glibc implementation. Tested with --with_tls=desc.
>
> v2: Add with_tls configuration option, and a few readability improvements.
>     Added Changelog.
> v3: Add documentation per Kito's suggestion.
>     Fix minor issues pointed out by Kito and Jeff.
>     Thanks Kito Cheng and Jeff Law for review.
>
> I've considered gating this behind a GAS feature test, but it seems
> nontrivial especially for restricting the variants available at runtime.
> Since TLS descriptors is not selected by default, I've decided to leave it
> ungated.
>
> In other news, I have made some progress on binutils side, and I'll try to
> update the GAS / ld patch set with relaxation included, by the end of this
> month.

Thanks for the update.  I understand the complexity adding a runtime
test when the feature also requires binutils and rtld support.
I hope that we add a test checking assembly under
gcc/testsuite/gcc.target/riscv/tls , otherwise as a non-default test,
when this breaks, it may be difficult to figure it out.
(glibc/elf/tst-* will need a runtime test, but GCC needs to have its own.)

>  gcc/config.gcc                  | 15 ++++++++++++++-
>  gcc/config/riscv/riscv-opts.h   |  6 ++++++
>  gcc/config/riscv/riscv-protos.h |  5 +++--
>  gcc/config/riscv/riscv.cc       | 24 ++++++++++++++++++++----
>  gcc/config/riscv/riscv.h        |  9 +++++++--
>  gcc/config/riscv/riscv.md       | 21 ++++++++++++++++++++-
>  gcc/config/riscv/riscv.opt      | 14 ++++++++++++++
>  gcc/doc/install.texi            |  3 +++
>  gcc/doc/invoke.texi             | 13 ++++++++++++-
>  9 files changed, 99 insertions(+), 11 deletions(-)
>
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 415e0e1ebc5..2c1a7179b02 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -2434,6 +2434,7 @@ riscv*-*-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:-trad}
>         ;;
>  riscv*-*-elf* | riscv*-*-rtems*)
>         tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
> @@ -2476,6 +2477,7 @@ riscv*-*-freebsd*)
>         # 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:-trad}
>         ;;
>
>  loongarch*-*-linux*)
> @@ -4566,7 +4568,7 @@ case "${target}" in
>                 ;;
>
>         riscv*-*-*)
> -               supported_defaults="abi arch tune riscv_attribute isa_spec"
> +               supported_defaults="abi arch tune riscv_attribute isa_spec tls"
>
>                 case "${target}" in
>                 riscv-* | riscv32*) xlen=32 ;;
> @@ -4694,6 +4696,17 @@ case "${target}" in
>                                 ;;
>                         esac
>                 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
>
>                 # Handle --with-multilib-list.
>                 if test "x${with_multilib_list}" != xdefault; then
> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> index 378a17699cd..db03f35430a 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -319,4 +319,10 @@ enum riscv_entity
>  #define TARGET_VECTOR_VLS                                                      \
>    (TARGET_VECTOR && riscv_autovec_preference == RVV_SCALABLE)
>
> +/* TLS types.  */
> +enum riscv_tls_type {
> +  TLS_TRADITIONAL,
> +  TLS_DESCRIPTORS
> +};
> +

I wonder whether `enum class` can be used instead and we can get rid
of the `TLS_` prefix.
gcc/config/ already has some uses.

>  #endif /* ! GCC_RISCV_OPTS_H */
> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> index 472c00dc439..9b7471f7591 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -33,9 +33,10 @@ enum riscv_symbol_type {
>    SYMBOL_TLS,
>    SYMBOL_TLS_LE,
>    SYMBOL_TLS_IE,
> -  SYMBOL_TLS_GD
> +  SYMBOL_TLS_GD,
> +  SYMBOL_TLSDESC,
>  };
> -#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
> +#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
>
>  /* Classifies an address.
>
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 49062bef9fc..c158e224aaa 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -799,6 +799,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
>      case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
>      case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
>      case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
> +    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
>      case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
>      default: gcc_unreachable ();
>      }
> @@ -1734,7 +1735,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
>  static rtx
>  riscv_legitimize_tls_address (rtx loc)
>  {
> -  rtx dest, tp, tmp;
> +  rtx dest, tp, tmp, a0;
>    enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
>
>  #if 0
> @@ -1750,9 +1751,24 @@ riscv_legitimize_tls_address (rtx loc)
>        /* Rely on section anchors for the optimization that LDM TLS
>          provides.  The anchor's address is loaded with GD TLS. */
>      case TLS_MODEL_GLOBAL_DYNAMIC:
> -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
> -      dest = gen_reg_rtx (Pmode);
> -      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
> +      if (TARGET_TLSDESC)
> +       {
> +         static unsigned seqno;
> +         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
> +         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
> +         dest = gen_reg_rtx (Pmode);
> +
> +         emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
> +         emit_insn (gen_add3_insn (dest, a0, tp));
> +         seqno++;
> +       }
> +      else
> +       {
> +         tmp = gen_rtx_REG (Pmode, GP_RETURN);
> +         dest = gen_reg_rtx (Pmode);
> +         emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
> +                             loc);
> +       }
>        break;
>
>      case TLS_MODEL_INITIAL_EXEC:
> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> index e18a0081297..faea78f5f4c 100644
> --- a/gcc/config/riscv/riscv.h
> +++ b/gcc/config/riscv/riscv.h
> @@ -59,6 +59,7 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>     --with-abi is ignored if -mabi is specified.
>     --with-tune is ignored if -mtune or -mcpu is specified.
>     --with-isa-spec is ignored if -misa-spec is specified.
> +   --with-tls is ignored if -mtls-dialect is specified.
>
>     But using default -march/-mtune value if -mcpu don't have valid option.  */
>  #define OPTION_DEFAULT_SPECS \
> @@ -68,8 +69,9 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>    {"arch", "%{!march=*:"                                               \
>            "  %{!mcpu=*:-march=%(VALUE)}"                               \
>            "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },  \
> -  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
> -  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
> +  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },                               \
> +  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },                        \
> +  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},                \
>
>  #ifdef IN_LIBGCC2
>  #undef TARGET_64BIT
> @@ -1122,4 +1124,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
>  #define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_VECTOR)
>  #define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE, riscv_vector::FRM_NONE}
>
> +/* Check TLS Descriptors mechanism is selected.  */
> +#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
> +
>  #endif /* ! GCC_RISCV_H */
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index b456fa6abb3..7c66c64b893 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -47,7 +47,7 @@
>    UNSPEC_TLS_LE
>    UNSPEC_TLS_IE
>    UNSPEC_TLS_GD
> -
> +  UNSPEC_TLSDESC
>    ;; High part of PC-relative address.
>    UNSPEC_AUIPC
>
> @@ -121,6 +121,7 @@
>     (T1_REGNUM                  6)
>     (S0_REGNUM                  8)
>     (S1_REGNUM                  9)
> +   (A0_REGNUM                  10)
>     (S2_REGNUM                  18)
>     (S3_REGNUM                  19)
>     (S4_REGNUM                  20)
> @@ -1869,6 +1870,24 @@
>    [(set_attr "got" "load")
>     (set_attr "mode" "<MODE>")])
>
> +(define_insn "@tlsdesc<mode>"
> +  [(set (reg:P A0_REGNUM)
> +           (unspec:P
> +                       [(match_operand:P 0 "symbolic_operand" "")
> +                        (match_operand:P 1 "const_int_operand")]
> +                       UNSPEC_TLSDESC))
> +   (clobber (reg:P T0_REGNUM))]
> +  "TARGET_TLSDESC"
> +  {
> +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
> +  }
> +  [(set_attr "type" "multi")
> +   (set_attr "length" "16")
> +   (set_attr "mode" "<MODE>")])
> +
>  (define_insn "auipc<mode>"
>    [(set (match_operand:P           0 "register_operand" "=r")
>         (unspec:P
> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> index 6304efebfd5..9ba690f8497 100644
> --- a/gcc/config/riscv/riscv.opt
> +++ b/gcc/config/riscv/riscv.opt
> @@ -311,3 +311,17 @@ Enum(riscv_autovec_lmul) String(m8) Value(RVV_M8)
>  -param=riscv-autovec-lmul=
>  Target RejectNegative Joined Enum(riscv_autovec_lmul) Var(riscv_autovec_lmul) Init(RVV_M1)
>  -param=riscv-autovec-lmul=<string>     Set the RVV LMUL of auto-vectorization in the RISC-V port.
> +
> +Enum
> +Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
> +Specify TLS dialect.
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index e099cd0b568..6ee533c0a40 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -1174,6 +1174,9 @@ Specify the default TLS dialect, for systems were there is a choice.
>  For ARM targets, possible values for @var{dialect} are @code{gnu} or
>  @code{gnu2}, which select between the original GNU dialect and the GNU TLS
>  descriptor-based dialect.
> +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
> +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
> +descriptor-based dialect.
>
>  @item --enable-multiarch
>  Specify whether to enable or disable multiarch support.  The default is
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index f2c1067ab7d..77b82c46311 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1234,7 +1234,8 @@ See RS/6000 and PowerPC Options.
>  -mstack-protector-guard=@var{guard}  -mstack-protector-guard-reg=@var{reg}
>  -mstack-protector-guard-offset=@var{offset}
>  -mcsr-check -mno-csr-check
> --minline-atomics  -mno-inline-atomics}
> +-minline-atomics  -mno-inline-atomics
> +-mtls-dialect=desc  -mtls-dialect=trad}
>
>  @emph{RL78 Options}
>  @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
> @@ -29403,6 +29404,16 @@ which register to use as base register for reading the canary,
>  and from what offset from that base register. There is no default
>  register or offset as this is entirely for use within the Linux
>  kernel.
> +
> +@opindex mtls-dialect=desc
> +@item -mtls-dialect=desc
> +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.
> +
> +@opindex mtls-dialect=trad
> +@item -mtls-dialect=trad
> +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.  This is the default.
>  @end table
>
>  @node RL78 Options
> --
> 2.42.1
>


-- 
宋方睿

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v3] RISC-V: Implement TLS Descriptors.
  2023-11-21  6:59   ` Fangrui Song
@ 2023-11-21  7:07     ` Tatsuyuki Ishi
  2023-12-05 16:49     ` Tatsuyuki Ishi
  1 sibling, 0 replies; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-11-21  7:07 UTC (permalink / raw)
  To: Fangrui Song; +Cc: gcc-patches, Rui Ueyama, Rui Ueyama, Kito Cheng, Jeff Law

[-- Attachment #1: Type: text/plain, Size: 15096 bytes --]

> On Nov 21, 2023, at 15:59, Fangrui Song <maskray@google.com> wrote:
> 
> On Mon, Nov 20, 2023 at 6:20 AM Tatsuyuki Ishi <ishitatsuyuki@gmail.com <mailto:ishitatsuyuki@gmail.com>> wrote:
>> 
>> This implements TLS Descriptors (TLSDESC) as specified in [1].
>> 
>> The 4-instruction sequence is implemented as a single RTX insn for
>> simplicity, but this can be revisited later if instruction scheduling or
>> more flexible RA is desired.
>> 
>> The default remains to be the traditional TLS model, but can be configured
>> with --with_tls={trad,desc}. The choice can be revisited once toolchain
>> and libc support ships.
>> 
>> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
>> 
>> gcc/Changelog:
>>        * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
>>        * config.gcc: Add --with_tls configuration option to change the
>>        default TLS flavor.
>>        * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
>>        -mtls-dialect and with_tls defaults.
>>        * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
>>        two TLS flavors.
>>        * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
>>        * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
>>        * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
>>        sequence length data for TLSDESC.
>>        (riscv_legitimize_tls_address): Add lowering of TLSDESC.
>>        * doc/install.texi: Document --with-tls for RISC-V.
>>        * doc/invoke.texi: Document --mtls-dialect for RISC-V.
> 
> Nit: One dash for --mtls-dialect.

Ack. Thanks.

>> ---
>> No regression in gcc tests for rv64gc, tested alongside the binutils and
>> glibc implementation. Tested with --with_tls=desc.
>> 
>> v2: Add with_tls configuration option, and a few readability improvements.
>>    Added Changelog.
>> v3: Add documentation per Kito's suggestion.
>>    Fix minor issues pointed out by Kito and Jeff.
>>    Thanks Kito Cheng and Jeff Law for review.
>> 
>> I've considered gating this behind a GAS feature test, but it seems
>> nontrivial especially for restricting the variants available at runtime.
>> Since TLS descriptors is not selected by default, I've decided to leave it
>> ungated.
>> 
>> In other news, I have made some progress on binutils side, and I'll try to
>> update the GAS / ld patch set with relaxation included, by the end of this
>> month.
> 
> Thanks for the update.  I understand the complexity adding a runtime
> test when the feature also requires binutils and rtld support.
> I hope that we add a test checking assembly under
> gcc/testsuite/gcc.target/riscv/tls , otherwise as a non-default test,
> when this breaks, it may be difficult to figure it out.
> (glibc/elf/tst-* will need a runtime test, but GCC needs to have its own.)

Checking assembly sounds reasonable.  I’ll look into it after finishing the binutils stuff.

>> gcc/config.gcc                  | 15 ++++++++++++++-
>> gcc/config/riscv/riscv-opts.h   |  6 ++++++
>> gcc/config/riscv/riscv-protos.h |  5 +++--
>> gcc/config/riscv/riscv.cc       | 24 ++++++++++++++++++++----
>> gcc/config/riscv/riscv.h        |  9 +++++++--
>> gcc/config/riscv/riscv.md       | 21 ++++++++++++++++++++-
>> gcc/config/riscv/riscv.opt      | 14 ++++++++++++++
>> gcc/doc/install.texi            |  3 +++
>> gcc/doc/invoke.texi             | 13 ++++++++++++-
>> 9 files changed, 99 insertions(+), 11 deletions(-)
>> 
>> diff --git a/gcc/config.gcc b/gcc/config.gcc
>> index 415e0e1ebc5..2c1a7179b02 100644
>> --- a/gcc/config.gcc
>> +++ b/gcc/config.gcc
>> @@ -2434,6 +2434,7 @@ riscv*-*-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:-trad}
>>        ;;
>> riscv*-*-elf* | riscv*-*-rtems*)
>>        tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
>> @@ -2476,6 +2477,7 @@ riscv*-*-freebsd*)
>>        # 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:-trad}
>>        ;;
>> 
>> loongarch*-*-linux*)
>> @@ -4566,7 +4568,7 @@ case "${target}" in
>>                ;;
>> 
>>        riscv*-*-*)
>> -               supported_defaults="abi arch tune riscv_attribute isa_spec"
>> +               supported_defaults="abi arch tune riscv_attribute isa_spec tls"
>> 
>>                case "${target}" in
>>                riscv-* | riscv32*) xlen=32 ;;
>> @@ -4694,6 +4696,17 @@ case "${target}" in
>>                                ;;
>>                        esac
>>                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
>> 
>>                # Handle --with-multilib-list.
>>                if test "x${with_multilib_list}" != xdefault; then
>> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
>> index 378a17699cd..db03f35430a 100644
>> --- a/gcc/config/riscv/riscv-opts.h
>> +++ b/gcc/config/riscv/riscv-opts.h
>> @@ -319,4 +319,10 @@ enum riscv_entity
>> #define TARGET_VECTOR_VLS                                                      \
>>   (TARGET_VECTOR && riscv_autovec_preference == RVV_SCALABLE)
>> 
>> +/* TLS types.  */
>> +enum riscv_tls_type {
>> +  TLS_TRADITIONAL,
>> +  TLS_DESCRIPTORS
>> +};
>> +
> 
> I wonder whether `enum class` can be used instead and we can get rid
> of the `TLS_` prefix.
> gcc/config/ already has some uses.

Sounds reasonable. If others have no objections I’ll put it in a revision.

>> #endif /* ! GCC_RISCV_OPTS_H */
>> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
>> index 472c00dc439..9b7471f7591 100644
>> --- a/gcc/config/riscv/riscv-protos.h
>> +++ b/gcc/config/riscv/riscv-protos.h
>> @@ -33,9 +33,10 @@ enum riscv_symbol_type {
>>   SYMBOL_TLS,
>>   SYMBOL_TLS_LE,
>>   SYMBOL_TLS_IE,
>> -  SYMBOL_TLS_GD
>> +  SYMBOL_TLS_GD,
>> +  SYMBOL_TLSDESC,
>> };
>> -#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
>> +#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
>> 
>> /* Classifies an address.
>> 
>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>> index 49062bef9fc..c158e224aaa 100644
>> --- a/gcc/config/riscv/riscv.cc
>> +++ b/gcc/config/riscv/riscv.cc
>> @@ -799,6 +799,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
>>     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
>>     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
>>     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
>> +    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
>>     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
>>     default: gcc_unreachable ();
>>     }
>> @@ -1734,7 +1735,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
>> static rtx
>> riscv_legitimize_tls_address (rtx loc)
>> {
>> -  rtx dest, tp, tmp;
>> +  rtx dest, tp, tmp, a0;
>>   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
>> 
>> #if 0
>> @@ -1750,9 +1751,24 @@ riscv_legitimize_tls_address (rtx loc)
>>       /* Rely on section anchors for the optimization that LDM TLS
>>         provides.  The anchor's address is loaded with GD TLS. */
>>     case TLS_MODEL_GLOBAL_DYNAMIC:
>> -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
>> -      dest = gen_reg_rtx (Pmode);
>> -      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
>> +      if (TARGET_TLSDESC)
>> +       {
>> +         static unsigned seqno;
>> +         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
>> +         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
>> +         dest = gen_reg_rtx (Pmode);
>> +
>> +         emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
>> +         emit_insn (gen_add3_insn (dest, a0, tp));
>> +         seqno++;
>> +       }
>> +      else
>> +       {
>> +         tmp = gen_rtx_REG (Pmode, GP_RETURN);
>> +         dest = gen_reg_rtx (Pmode);
>> +         emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
>> +                             loc);
>> +       }
>>       break;
>> 
>>     case TLS_MODEL_INITIAL_EXEC:
>> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
>> index e18a0081297..faea78f5f4c 100644
>> --- a/gcc/config/riscv/riscv.h
>> +++ b/gcc/config/riscv/riscv.h
>> @@ -59,6 +59,7 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>>    --with-abi is ignored if -mabi is specified.
>>    --with-tune is ignored if -mtune or -mcpu is specified.
>>    --with-isa-spec is ignored if -misa-spec is specified.
>> +   --with-tls is ignored if -mtls-dialect is specified.
>> 
>>    But using default -march/-mtune value if -mcpu don't have valid option.  */
>> #define OPTION_DEFAULT_SPECS \
>> @@ -68,8 +69,9 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>>   {"arch", "%{!march=*:"                                               \
>>           "  %{!mcpu=*:-march=%(VALUE)}"                               \
>>           "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },  \
>> -  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
>> -  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
>> +  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },                               \
>> +  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },                        \
>> +  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},                \
>> 
>> #ifdef IN_LIBGCC2
>> #undef TARGET_64BIT
>> @@ -1122,4 +1124,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
>> #define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_VECTOR)
>> #define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE, riscv_vector::FRM_NONE}
>> 
>> +/* Check TLS Descriptors mechanism is selected.  */
>> +#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
>> +
>> #endif /* ! GCC_RISCV_H */
>> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
>> index b456fa6abb3..7c66c64b893 100644
>> --- a/gcc/config/riscv/riscv.md
>> +++ b/gcc/config/riscv/riscv.md
>> @@ -47,7 +47,7 @@
>>   UNSPEC_TLS_LE
>>   UNSPEC_TLS_IE
>>   UNSPEC_TLS_GD
>> -
>> +  UNSPEC_TLSDESC
>>   ;; High part of PC-relative address.
>>   UNSPEC_AUIPC
>> 
>> @@ -121,6 +121,7 @@
>>    (T1_REGNUM                  6)
>>    (S0_REGNUM                  8)
>>    (S1_REGNUM                  9)
>> +   (A0_REGNUM                  10)
>>    (S2_REGNUM                  18)
>>    (S3_REGNUM                  19)
>>    (S4_REGNUM                  20)
>> @@ -1869,6 +1870,24 @@
>>   [(set_attr "got" "load")
>>    (set_attr "mode" "<MODE>")])
>> 
>> +(define_insn "@tlsdesc<mode>"
>> +  [(set (reg:P A0_REGNUM)
>> +           (unspec:P
>> +                       [(match_operand:P 0 "symbolic_operand" "")
>> +                        (match_operand:P 1 "const_int_operand")]
>> +                       UNSPEC_TLSDESC))
>> +   (clobber (reg:P T0_REGNUM))]
>> +  "TARGET_TLSDESC"
>> +  {
>> +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
>> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
>> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
>> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
>> +  }
>> +  [(set_attr "type" "multi")
>> +   (set_attr "length" "16")
>> +   (set_attr "mode" "<MODE>")])
>> +
>> (define_insn "auipc<mode>"
>>   [(set (match_operand:P           0 "register_operand" "=r")
>>        (unspec:P
>> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
>> index 6304efebfd5..9ba690f8497 100644
>> --- a/gcc/config/riscv/riscv.opt
>> +++ b/gcc/config/riscv/riscv.opt
>> @@ -311,3 +311,17 @@ Enum(riscv_autovec_lmul) String(m8) Value(RVV_M8)
>> -param=riscv-autovec-lmul=
>> Target RejectNegative Joined Enum(riscv_autovec_lmul) Var(riscv_autovec_lmul) Init(RVV_M1)
>> -param=riscv-autovec-lmul=<string>     Set the RVV LMUL of auto-vectorization in the RISC-V port.
>> +
>> +Enum
>> +Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
>> +Specify TLS dialect.
>> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
>> index e099cd0b568..6ee533c0a40 100644
>> --- a/gcc/doc/install.texi
>> +++ b/gcc/doc/install.texi
>> @@ -1174,6 +1174,9 @@ Specify the default TLS dialect, for systems were there is a choice.
>> For ARM targets, possible values for @var{dialect} are @code{gnu} or
>> @code{gnu2}, which select between the original GNU dialect and the GNU TLS
>> descriptor-based dialect.
>> +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
>> +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
>> +descriptor-based dialect.
>> 
>> @item --enable-multiarch
>> Specify whether to enable or disable multiarch support.  The default is
>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>> index f2c1067ab7d..77b82c46311 100644
>> --- a/gcc/doc/invoke.texi
>> +++ b/gcc/doc/invoke.texi
>> @@ -1234,7 +1234,8 @@ See RS/6000 and PowerPC Options.
>> -mstack-protector-guard=@var{guard}  -mstack-protector-guard-reg=@var{reg}
>> -mstack-protector-guard-offset=@var{offset}
>> -mcsr-check -mno-csr-check
>> --minline-atomics  -mno-inline-atomics}
>> +-minline-atomics  -mno-inline-atomics
>> +-mtls-dialect=desc  -mtls-dialect=trad}
>> 
>> @emph{RL78 Options}
>> @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
>> @@ -29403,6 +29404,16 @@ which register to use as base register for reading the canary,
>> and from what offset from that base register. There is no default
>> register or offset as this is entirely for use within the Linux
>> kernel.
>> +
>> +@opindex mtls-dialect=desc
>> +@item -mtls-dialect=desc
>> +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
>> +of TLS variables.
>> +
>> +@opindex mtls-dialect=trad
>> +@item -mtls-dialect=trad
>> +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
>> +of TLS variables.  This is the default.
>> @end table
>> 
>> @node RL78 Options
>> --
>> 2.42.1
>> 
> 
> 
> -- 
> 宋方睿


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v3] RISC-V: Implement TLS Descriptors.
  2023-11-20 13:17 ` [PATCH v3] " Tatsuyuki Ishi
  2023-11-21  6:59   ` Fangrui Song
@ 2023-11-23 10:57   ` Florian Weimer
  2023-11-23 11:34     ` Tatsuyuki Ishi
  1 sibling, 1 reply; 26+ messages in thread
From: Florian Weimer @ 2023-11-23 10:57 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, rui314, ruiu, kito.cheng, jeffreyalaw

* Tatsuyuki Ishi:

> I've considered gating this behind a GAS feature test, but it seems
> nontrivial especially for restricting the variants available at runtime.
> Since TLS descriptors is not selected by default, I've decided to leave it
> ungated.
>
> In other news, I have made some progress on binutils side, and I'll try to
> update the GAS / ld patch set with relaxation included, by the end of this
> month.

Is there a glibc patch with the run-time implementation already?

I'm curious how you are going to implement saving the vector register
file

Thanks,
Florian


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v3] RISC-V: Implement TLS Descriptors.
  2023-11-23 10:57   ` Florian Weimer
@ 2023-11-23 11:34     ` Tatsuyuki Ishi
  2023-11-23 11:40       ` Florian Weimer
  0 siblings, 1 reply; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-11-23 11:34 UTC (permalink / raw)
  To: Florian Weimer; +Cc: gcc-patches, Rui Ueyama, Rui Ueyama, Kito Cheng, Jeff Law

> On Nov 23, 2023, at 19:57, Florian Weimer <fweimer@redhat.com> wrote:
> 
> * Tatsuyuki Ishi:
> 
>> I've considered gating this behind a GAS feature test, but it seems
>> nontrivial especially for restricting the variants available at runtime.
>> Since TLS descriptors is not selected by default, I've decided to leave it
>> ungated.
>> 
>> In other news, I have made some progress on binutils side, and I'll try to
>> update the GAS / ld patch set with relaxation included, by the end of this
>> month.
> 
> Is there a glibc patch with the run-time implementation already?
> 
> I'm curious how you are going to implement saving the vector register
> file

There is, please see [1].  The vector register file handling is missing right
now as I’m not sure if we have agreed upon a calling convention for RVV.

In the spec, I have already specified the interaction with RVV:

> Any other registers are callee-saved. This includes any vector registers
when the vector extension is supported.

Once the calling convention is decided, I will add saving of all caller-saved
registers into the TLSDESC stub.

[1]: https://inbox.sourceware.org/libc-alpha/20230914084033.222120-1-ishitatsuyuki@gmail.com/

> Thanks,
> Florian
> 


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v3] RISC-V: Implement TLS Descriptors.
  2023-11-23 11:34     ` Tatsuyuki Ishi
@ 2023-11-23 11:40       ` Florian Weimer
  0 siblings, 0 replies; 26+ messages in thread
From: Florian Weimer @ 2023-11-23 11:40 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, Rui Ueyama, Rui Ueyama, Kito Cheng, Jeff Law

* Tatsuyuki Ishi:

> There is, please see [1].  The vector register file handling is missing right
> now as I’m not sure if we have agreed upon a calling convention for RVV.

> [1]: https://inbox.sourceware.org/libc-alpha/20230914084033.222120-1-ishitatsuyuki@gmail.com/

Thank you, I have raised my concern on the other thread.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v4] RISC-V: Implement TLS Descriptors.
  2023-08-17 18:12 [PATCH] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
                   ` (2 preceding siblings ...)
  2023-11-20 13:17 ` [PATCH v3] " Tatsuyuki Ishi
@ 2023-12-05  7:01 ` Tatsuyuki Ishi
  2024-01-27  3:24   ` Fangrui Song
  2024-03-29  5:52 ` [PATCH v5] " Tatsuyuki Ishi
  4 siblings, 1 reply; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-12-05  7:01 UTC (permalink / raw)
  To: ishitatsuyuki; +Cc: gcc-patches, rui314, ruiu, kito.cheng, jeffreyalaw

This implements TLS Descriptors (TLSDESC) as specified in [1].

The 4-instruction sequence is implemented as a single RTX insn for
simplicity, but this can be revisited later if instruction scheduling or
more flexible RA is desired.

The default remains to be the traditional TLS model, but can be configured
with --with_tls={trad,desc}. The choice can be revisited once toolchain
and libc support ships.

[1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.

gcc/Changelog:
	* config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
	* config.gcc: Add --with_tls configuration option to change the
	default TLS flavor.
	* config/riscv/riscv.h: Add TARGET_TLSDESC determined from
	-mtls-dialect and with_tls defaults.
	* config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
	two TLS flavors.
	* config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
	* config/riscv/riscv.md: Add instruction sequence for TLSDESC.
	* config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
	sequence length data for TLSDESC.
	(riscv_legitimize_tls_address): Add lowering of TLSDESC.
	* doc/install.texi: Document --with-tls for RISC-V.
	* doc/invoke.texi: Document -mtls-dialect for RISC-V.
	* testsuite/gcc.target/riscv/tls_1.x: Add TLSDESC GD test case.
	* testsuite/gcc.target/riscv/tlsdesc.c: Same as above.
---
No regression in gcc tests for rv64gc, tested alongside the binutils and
glibc implementation. Tested with --with_tls=desc.

v2: Add with_tls configuration option, and a few readability improvements.
    Added Changelog.
v3: Add documentation per Kito's suggestion.
    Fix minor issues pointed out by Kito and Jeff.
    Thanks Kito Cheng and Jeff Law for review.
v4: Add TLSDESC GD assembly test.
    Rebase on top of trunk.

 gcc/config.gcc                           | 15 ++++++++++++++-
 gcc/config/riscv/riscv-opts.h            |  6 ++++++
 gcc/config/riscv/riscv-protos.h          |  5 +++--
 gcc/config/riscv/riscv.cc                | 24 ++++++++++++++++++++----
 gcc/config/riscv/riscv.h                 |  9 +++++++--
 gcc/config/riscv/riscv.md                | 20 +++++++++++++++++++-
 gcc/config/riscv/riscv.opt               | 14 ++++++++++++++
 gcc/doc/install.texi                     |  3 +++
 gcc/doc/invoke.texi                      | 13 ++++++++++++-
 gcc/testsuite/gcc.target/riscv/tls_1.x   |  5 +++++
 gcc/testsuite/gcc.target/riscv/tlsdesc.c | 12 ++++++++++++
 11 files changed, 115 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/tls_1.x
 create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc.c

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 748430194f3..8bb22e9f590 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2490,6 +2490,7 @@ riscv*-*-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:-trad}
 	;;
 riscv*-*-elf* | riscv*-*-rtems*)
 	tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
@@ -2532,6 +2533,7 @@ riscv*-*-freebsd*)
 	# 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:-trad}
 	;;
 
 loongarch*-*-linux*)
@@ -4658,7 +4660,7 @@ case "${target}" in
 		;;
 
 	riscv*-*-*)
-		supported_defaults="abi arch tune riscv_attribute isa_spec"
+		supported_defaults="abi arch tune riscv_attribute isa_spec tls"
 
 		case "${target}" in
 		riscv-* | riscv32*) xlen=32 ;;
@@ -4788,6 +4790,17 @@ case "${target}" in
 				;;
 			esac
 		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
 
 		# Handle --with-multilib-list.
 		if test "x${with_multilib_list}" != xdefault; then
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 30efebbf07b..b2551968be0 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -138,4 +138,10 @@ enum stringop_strategy_enum {
 #define TARGET_MAX_LMUL                                                        \
   (int) (riscv_autovec_lmul == RVV_DYNAMIC ? RVV_M8 : riscv_autovec_lmul)
 
+/* TLS types.  */
+enum riscv_tls_type {
+  TLS_TRADITIONAL,
+  TLS_DESCRIPTORS
+};
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index 695ee24ad6f..f0d8f88dad7 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -33,9 +33,10 @@ enum riscv_symbol_type {
   SYMBOL_TLS,
   SYMBOL_TLS_LE,
   SYMBOL_TLS_IE,
-  SYMBOL_TLS_GD
+  SYMBOL_TLS_GD,
+  SYMBOL_TLSDESC,
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
 
 /* Classifies an address.
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 3f111fa0393..639a77922d9 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -892,6 +892,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
+    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
     default: gcc_unreachable ();
     }
@@ -1996,7 +1997,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
 static rtx
 riscv_legitimize_tls_address (rtx loc)
 {
-  rtx dest, tp, tmp;
+  rtx dest, tp, tmp, a0;
   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
 
 #if 0
@@ -2012,9 +2013,24 @@ riscv_legitimize_tls_address (rtx loc)
       /* Rely on section anchors for the optimization that LDM TLS
 	 provides.  The anchor's address is loaded with GD TLS. */
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
+      if (TARGET_TLSDESC)
+	{
+	  static unsigned seqno;
+	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+	  dest = gen_reg_rtx (Pmode);
+
+	  emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
+	  emit_insn (gen_add3_insn (dest, a0, tp));
+	  seqno++;
+	}
+      else
+	{
+	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
+	  dest = gen_reg_rtx (Pmode);
+	  emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
+			      loc);
+	}
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 6df9ec73c5e..5eb08c21cf4 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -62,6 +62,7 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
    --with-abi is ignored if -mabi is specified.
    --with-tune is ignored if -mtune or -mcpu is specified.
    --with-isa-spec is ignored if -misa-spec is specified.
+   --with-tls is ignored if -mtls-dialect is specified.
 
    But using default -march/-mtune value if -mcpu don't have valid option.  */
 #define OPTION_DEFAULT_SPECS \
@@ -71,8 +72,9 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
   {"arch", "%{!march=*:"						\
 	   "  %{!mcpu=*:-march=%(VALUE)}"				\
 	   "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },	\
-  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
-  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
+  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },				\
+  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },			\
+  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},         	\
 
 #ifdef IN_LIBGCC2
 #undef TARGET_64BIT
@@ -1215,4 +1217,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
 #define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
 #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
 
+/* Check TLS Descriptors mechanism is selected.  */
+#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index a98918dfd43..c3676d751df 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -47,7 +47,7 @@
   UNSPEC_TLS_LE
   UNSPEC_TLS_IE
   UNSPEC_TLS_GD
-
+  UNSPEC_TLSDESC
   ;; High part of PC-relative address.
   UNSPEC_AUIPC
 
@@ -2017,6 +2017,24 @@
    (set_attr "type" "load")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "@tlsdesc<mode>"
+  [(set (reg:P A0_REGNUM)
+	    (unspec:P
+			[(match_operand:P 0 "symbolic_operand" "")
+			 (match_operand:P 1 "const_int_operand")]
+			UNSPEC_TLSDESC))
+   (clobber (reg:P T0_REGNUM))]
+  "TARGET_TLSDESC"
+  {
+    return ".LT%1: auipc\ta0,%%tlsdesc_hi(%0)\;"
+           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
+           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
+           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
+  }
+  [(set_attr "type" "multi")
+   (set_attr "length" "16")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "auipc<mode>"
   [(set (match_operand:P           0 "register_operand" "=r")
 	(unspec:P
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 59ce7106ecf..8de2e8628d8 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -556,3 +556,17 @@ Enum(stringop_strategy) String(vector) Value(STRATEGY_VECTOR)
 mstringop-strategy=
 Target RejectNegative Joined Enum(stringop_strategy) Var(stringop_strategy) Init(STRATEGY_AUTO)
 Specify stringop expansion strategy.
+
+Enum
+Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
+Specify TLS dialect.
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index c1128d9274c..3b549ab62da 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1184,6 +1184,9 @@ Specify the default TLS dialect, for systems were there is a choice.
 For ARM targets, possible values for @var{dialect} are @code{gnu} or
 @code{gnu2}, which select between the original GNU dialect and the GNU TLS
 descriptor-based dialect.
+For RISC-V targets, possible values for @var{dialect} are @code{trad} or
+@code{desc}, which select between the traditional GNU dialect and the GNU TLS
+descriptor-based dialect.
 
 @item --enable-multiarch
 Specify whether to enable or disable multiarch support.  The default is
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 681e3f3f466..62c8bf9061b 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1252,7 +1252,8 @@ See RS/6000 and PowerPC Options.
 -minline-atomics  -mno-inline-atomics
 -minline-strlen  -mno-inline-strlen
 -minline-strcmp  -mno-inline-strcmp
--minline-strncmp  -mno-inline-strncmp}
+-minline-strncmp  -mno-inline-strncmp
+-mtls-dialect=desc  -mtls-dialect=trad}
 
 @emph{RL78 Options}
 @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
@@ -29988,6 +29989,16 @@ which register to use as base register for reading the canary,
 and from what offset from that base register. There is no default
 register or offset as this is entirely for use within the Linux
 kernel.
+
+@opindex mtls-dialect=desc
+@item -mtls-dialect=desc
+Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
+of TLS variables.
+
+@opindex mtls-dialect=trad
+@item -mtls-dialect=trad
+Use traditional TLS as the thread-local storage mechanism for dynamic accesses
+of TLS variables.  This is the default.
 @end table
 
 @node RL78 Options
diff --git a/gcc/testsuite/gcc.target/riscv/tls_1.x b/gcc/testsuite/gcc.target/riscv/tls_1.x
new file mode 100644
index 00000000000..cf334ef55ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/tls_1.x
@@ -0,0 +1,5 @@
+extern __thread unsigned gd;
+
+unsigned get() {
+	return gd;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc.c b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
new file mode 100644
index 00000000000..f9ac9fe0d6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
@@ -0,0 +1,12 @@
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -fpic -mtls-dialect=desc --save-temps" } */
+/* { dg-require-effective-target fpic } */
+
+#include "tls_1.x"
+
+/* { dg-final { scan-assembler-times "auipc\t\[a-x0-9\]+,%tlsdesc_hi" 1 } } */
+/* { dg-final { scan-assembler-times "lw\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "ld\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv64 } } } }*/
+/* { dg-final { scan-assembler-times "addi\ta0,\[a-x0-9\]+,%tlsdesc_add_lo" 1 } } */
+/* { dg-final { scan-assembler-times "jalr\tt0,\[a-x0-9\]+,%tlsdesc_call" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
-- 
2.43.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v3] RISC-V: Implement TLS Descriptors.
  2023-11-21  6:59   ` Fangrui Song
  2023-11-21  7:07     ` Tatsuyuki Ishi
@ 2023-12-05 16:49     ` Tatsuyuki Ishi
  1 sibling, 0 replies; 26+ messages in thread
From: Tatsuyuki Ishi @ 2023-12-05 16:49 UTC (permalink / raw)
  To: Fangrui Song; +Cc: gcc-patches, Rui Ueyama, Rui Ueyama, kito.cheng, jeffreyalaw

[-- Attachment #1: Type: text/plain, Size: 15112 bytes --]

> On Nov 21, 2023, at 15:59, Fangrui Song <maskray@google.com> wrote:
> 
> On Mon, Nov 20, 2023 at 6:20 AM Tatsuyuki Ishi <ishitatsuyuki@gmail.com <mailto:ishitatsuyuki@gmail.com>> wrote:
>> 
>> This implements TLS Descriptors (TLSDESC) as specified in [1].
>> 
>> The 4-instruction sequence is implemented as a single RTX insn for
>> simplicity, but this can be revisited later if instruction scheduling or
>> more flexible RA is desired.
>> 
>> The default remains to be the traditional TLS model, but can be configured
>> with --with_tls={trad,desc}. The choice can be revisited once toolchain
>> and libc support ships.
>> 
>> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
>> 
>> gcc/Changelog:
>>        * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
>>        * config.gcc: Add --with_tls configuration option to change the
>>        default TLS flavor.
>>        * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
>>        -mtls-dialect and with_tls defaults.
>>        * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
>>        two TLS flavors.
>>        * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
>>        * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
>>        * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
>>        sequence length data for TLSDESC.
>>        (riscv_legitimize_tls_address): Add lowering of TLSDESC.
>>        * doc/install.texi: Document --with-tls for RISC-V.
>>        * doc/invoke.texi: Document --mtls-dialect for RISC-V.
> 
> Nit: One dash for --mtls-dialect.
> 
>> ---
>> No regression in gcc tests for rv64gc, tested alongside the binutils and
>> glibc implementation. Tested with --with_tls=desc.
>> 
>> v2: Add with_tls configuration option, and a few readability improvements.
>>    Added Changelog.
>> v3: Add documentation per Kito's suggestion.
>>    Fix minor issues pointed out by Kito and Jeff.
>>    Thanks Kito Cheng and Jeff Law for review.
>> 
>> I've considered gating this behind a GAS feature test, but it seems
>> nontrivial especially for restricting the variants available at runtime.
>> Since TLS descriptors is not selected by default, I've decided to leave it
>> ungated.
>> 
>> In other news, I have made some progress on binutils side, and I'll try to
>> update the GAS / ld patch set with relaxation included, by the end of this
>> month.
> 
> Thanks for the update.  I understand the complexity adding a runtime
> test when the feature also requires binutils and rtld support.
> I hope that we add a test checking assembly under
> gcc/testsuite/gcc.target/riscv/tls , otherwise as a non-default test,
> when this breaks, it may be difficult to figure it out.
> (glibc/elf/tst-* will need a runtime test, but GCC needs to have its own.)
> 
>> gcc/config.gcc                  | 15 ++++++++++++++-
>> gcc/config/riscv/riscv-opts.h   |  6 ++++++
>> gcc/config/riscv/riscv-protos.h |  5 +++--
>> gcc/config/riscv/riscv.cc       | 24 ++++++++++++++++++++----
>> gcc/config/riscv/riscv.h        |  9 +++++++--
>> gcc/config/riscv/riscv.md       | 21 ++++++++++++++++++++-
>> gcc/config/riscv/riscv.opt      | 14 ++++++++++++++
>> gcc/doc/install.texi            |  3 +++
>> gcc/doc/invoke.texi             | 13 ++++++++++++-
>> 9 files changed, 99 insertions(+), 11 deletions(-)
>> 
>> diff --git a/gcc/config.gcc b/gcc/config.gcc
>> index 415e0e1ebc5..2c1a7179b02 100644
>> --- a/gcc/config.gcc
>> +++ b/gcc/config.gcc
>> @@ -2434,6 +2434,7 @@ riscv*-*-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:-trad}
>>        ;;
>> riscv*-*-elf* | riscv*-*-rtems*)
>>        tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
>> @@ -2476,6 +2477,7 @@ riscv*-*-freebsd*)
>>        # 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:-trad}
>>        ;;
>> 
>> loongarch*-*-linux*)
>> @@ -4566,7 +4568,7 @@ case "${target}" in
>>                ;;
>> 
>>        riscv*-*-*)
>> -               supported_defaults="abi arch tune riscv_attribute isa_spec"
>> +               supported_defaults="abi arch tune riscv_attribute isa_spec tls"
>> 
>>                case "${target}" in
>>                riscv-* | riscv32*) xlen=32 ;;
>> @@ -4694,6 +4696,17 @@ case "${target}" in
>>                                ;;
>>                        esac
>>                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
>> 
>>                # Handle --with-multilib-list.
>>                if test "x${with_multilib_list}" != xdefault; then
>> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
>> index 378a17699cd..db03f35430a 100644
>> --- a/gcc/config/riscv/riscv-opts.h
>> +++ b/gcc/config/riscv/riscv-opts.h
>> @@ -319,4 +319,10 @@ enum riscv_entity
>> #define TARGET_VECTOR_VLS                                                      \
>>   (TARGET_VECTOR && riscv_autovec_preference == RVV_SCALABLE)
>> 
>> +/* TLS types.  */
>> +enum riscv_tls_type {
>> +  TLS_TRADITIONAL,
>> +  TLS_DESCRIPTORS
>> +};
>> +
> 
> I wonder whether `enum class` can be used instead and we can get rid
> of the `TLS_` prefix.
> gcc/config/ already has some uses.

Sorry, once thing I forgot to mention about this when I posted v4.
This enum is used in the context of an .opt file, so I’ve kept it as-is in
v4 to avoid contradicting the code style.

Tatsuyuki.

>> #endif /* ! GCC_RISCV_OPTS_H */
>> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
>> index 472c00dc439..9b7471f7591 100644
>> --- a/gcc/config/riscv/riscv-protos.h
>> +++ b/gcc/config/riscv/riscv-protos.h
>> @@ -33,9 +33,10 @@ enum riscv_symbol_type {
>>   SYMBOL_TLS,
>>   SYMBOL_TLS_LE,
>>   SYMBOL_TLS_IE,
>> -  SYMBOL_TLS_GD
>> +  SYMBOL_TLS_GD,
>> +  SYMBOL_TLSDESC,
>> };
>> -#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
>> +#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
>> 
>> /* Classifies an address.
>> 
>> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
>> index 49062bef9fc..c158e224aaa 100644
>> --- a/gcc/config/riscv/riscv.cc
>> +++ b/gcc/config/riscv/riscv.cc
>> @@ -799,6 +799,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
>>     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
>>     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
>>     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
>> +    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
>>     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
>>     default: gcc_unreachable ();
>>     }
>> @@ -1734,7 +1735,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
>> static rtx
>> riscv_legitimize_tls_address (rtx loc)
>> {
>> -  rtx dest, tp, tmp;
>> +  rtx dest, tp, tmp, a0;
>>   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
>> 
>> #if 0
>> @@ -1750,9 +1751,24 @@ riscv_legitimize_tls_address (rtx loc)
>>       /* Rely on section anchors for the optimization that LDM TLS
>>         provides.  The anchor's address is loaded with GD TLS. */
>>     case TLS_MODEL_GLOBAL_DYNAMIC:
>> -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
>> -      dest = gen_reg_rtx (Pmode);
>> -      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
>> +      if (TARGET_TLSDESC)
>> +       {
>> +         static unsigned seqno;
>> +         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
>> +         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
>> +         dest = gen_reg_rtx (Pmode);
>> +
>> +         emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
>> +         emit_insn (gen_add3_insn (dest, a0, tp));
>> +         seqno++;
>> +       }
>> +      else
>> +       {
>> +         tmp = gen_rtx_REG (Pmode, GP_RETURN);
>> +         dest = gen_reg_rtx (Pmode);
>> +         emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
>> +                             loc);
>> +       }
>>       break;
>> 
>>     case TLS_MODEL_INITIAL_EXEC:
>> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
>> index e18a0081297..faea78f5f4c 100644
>> --- a/gcc/config/riscv/riscv.h
>> +++ b/gcc/config/riscv/riscv.h
>> @@ -59,6 +59,7 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>>    --with-abi is ignored if -mabi is specified.
>>    --with-tune is ignored if -mtune or -mcpu is specified.
>>    --with-isa-spec is ignored if -misa-spec is specified.
>> +   --with-tls is ignored if -mtls-dialect is specified.
>> 
>>    But using default -march/-mtune value if -mcpu don't have valid option.  */
>> #define OPTION_DEFAULT_SPECS \
>> @@ -68,8 +69,9 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>>   {"arch", "%{!march=*:"                                               \
>>           "  %{!mcpu=*:-march=%(VALUE)}"                               \
>>           "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },  \
>> -  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
>> -  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
>> +  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },                               \
>> +  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },                        \
>> +  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},                \
>> 
>> #ifdef IN_LIBGCC2
>> #undef TARGET_64BIT
>> @@ -1122,4 +1124,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
>> #define OPTIMIZE_MODE_SWITCHING(ENTITY) (TARGET_VECTOR)
>> #define NUM_MODES_FOR_MODE_SWITCHING {VXRM_MODE_NONE, riscv_vector::FRM_NONE}
>> 
>> +/* Check TLS Descriptors mechanism is selected.  */
>> +#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
>> +
>> #endif /* ! GCC_RISCV_H */
>> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
>> index b456fa6abb3..7c66c64b893 100644
>> --- a/gcc/config/riscv/riscv.md
>> +++ b/gcc/config/riscv/riscv.md
>> @@ -47,7 +47,7 @@
>>   UNSPEC_TLS_LE
>>   UNSPEC_TLS_IE
>>   UNSPEC_TLS_GD
>> -
>> +  UNSPEC_TLSDESC
>>   ;; High part of PC-relative address.
>>   UNSPEC_AUIPC
>> 
>> @@ -121,6 +121,7 @@
>>    (T1_REGNUM                  6)
>>    (S0_REGNUM                  8)
>>    (S1_REGNUM                  9)
>> +   (A0_REGNUM                  10)
>>    (S2_REGNUM                  18)
>>    (S3_REGNUM                  19)
>>    (S4_REGNUM                  20)
>> @@ -1869,6 +1870,24 @@
>>   [(set_attr "got" "load")
>>    (set_attr "mode" "<MODE>")])
>> 
>> +(define_insn "@tlsdesc<mode>"
>> +  [(set (reg:P A0_REGNUM)
>> +           (unspec:P
>> +                       [(match_operand:P 0 "symbolic_operand" "")
>> +                        (match_operand:P 1 "const_int_operand")]
>> +                       UNSPEC_TLSDESC))
>> +   (clobber (reg:P T0_REGNUM))]
>> +  "TARGET_TLSDESC"
>> +  {
>> +    return ".LT%1: auipc\ta0, %%tlsdesc_hi(%0)\;"
>> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
>> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
>> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
>> +  }
>> +  [(set_attr "type" "multi")
>> +   (set_attr "length" "16")
>> +   (set_attr "mode" "<MODE>")])
>> +
>> (define_insn "auipc<mode>"
>>   [(set (match_operand:P           0 "register_operand" "=r")
>>        (unspec:P
>> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
>> index 6304efebfd5..9ba690f8497 100644
>> --- a/gcc/config/riscv/riscv.opt
>> +++ b/gcc/config/riscv/riscv.opt
>> @@ -311,3 +311,17 @@ Enum(riscv_autovec_lmul) String(m8) Value(RVV_M8)
>> -param=riscv-autovec-lmul=
>> Target RejectNegative Joined Enum(riscv_autovec_lmul) Var(riscv_autovec_lmul) Init(RVV_M1)
>> -param=riscv-autovec-lmul=<string>     Set the RVV LMUL of auto-vectorization in the RISC-V port.
>> +
>> +Enum
>> +Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
>> +Specify TLS dialect.
>> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
>> index e099cd0b568..6ee533c0a40 100644
>> --- a/gcc/doc/install.texi
>> +++ b/gcc/doc/install.texi
>> @@ -1174,6 +1174,9 @@ Specify the default TLS dialect, for systems were there is a choice.
>> For ARM targets, possible values for @var{dialect} are @code{gnu} or
>> @code{gnu2}, which select between the original GNU dialect and the GNU TLS
>> descriptor-based dialect.
>> +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
>> +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
>> +descriptor-based dialect.
>> 
>> @item --enable-multiarch
>> Specify whether to enable or disable multiarch support.  The default is
>> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>> index f2c1067ab7d..77b82c46311 100644
>> --- a/gcc/doc/invoke.texi
>> +++ b/gcc/doc/invoke.texi
>> @@ -1234,7 +1234,8 @@ See RS/6000 and PowerPC Options.
>> -mstack-protector-guard=@var{guard}  -mstack-protector-guard-reg=@var{reg}
>> -mstack-protector-guard-offset=@var{offset}
>> -mcsr-check -mno-csr-check
>> --minline-atomics  -mno-inline-atomics}
>> +-minline-atomics  -mno-inline-atomics
>> +-mtls-dialect=desc  -mtls-dialect=trad}
>> 
>> @emph{RL78 Options}
>> @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
>> @@ -29403,6 +29404,16 @@ which register to use as base register for reading the canary,
>> and from what offset from that base register. There is no default
>> register or offset as this is entirely for use within the Linux
>> kernel.
>> +
>> +@opindex mtls-dialect=desc
>> +@item -mtls-dialect=desc
>> +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
>> +of TLS variables.
>> +
>> +@opindex mtls-dialect=trad
>> +@item -mtls-dialect=trad
>> +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
>> +of TLS variables.  This is the default.
>> @end table
>> 
>> @node RL78 Options
>> --
>> 2.42.1
>> 
> 
> 
> -- 
> 宋方睿


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v4] RISC-V: Implement TLS Descriptors.
  2023-12-05  7:01 ` [PATCH v4] " Tatsuyuki Ishi
@ 2024-01-27  3:24   ` Fangrui Song
  0 siblings, 0 replies; 26+ messages in thread
From: Fangrui Song @ 2024-01-27  3:24 UTC (permalink / raw)
  To: Tatsuyuki Ishi; +Cc: gcc-patches, rui314, ruiu, kito.cheng, jeffreyalaw

On Mon, Dec 4, 2023 at 11:02 PM Tatsuyuki Ishi <ishitatsuyuki@gmail.com> wrote:
>
> This implements TLS Descriptors (TLSDESC) as specified in [1].
>
> The 4-instruction sequence is implemented as a single RTX insn for
> simplicity, but this can be revisited later if instruction scheduling or
> more flexible RA is desired.
>
> The default remains to be the traditional TLS model, but can be configured
> with --with_tls={trad,desc}. The choice can be revisited once toolchain
> and libc support ships.

typo: --with-tls={trad,desc}.

The patch looks good to me, but I am not an approver:) I only have
some nitpicky comments.

Reviewed-by: Fangrui Song <maskray@google.com>

I know that the binutils patch needs some work, but I think it doesn't
have to block this patch.
BTW, Clang got -mtls-dialect=desc today, so one can test GCC by  gcc
-S -fpic -mtls-dialect + clang -c + ld.lld + musl
https://maskray.me/blog/2024-01-23-riscv-tlsdesc-works

I actually tested my ld.lld patch by compiling with GCC and manually
replacing TLS GD code sequence with TLSDESC :)

> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
>
> gcc/Changelog:
>         * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
>         * config.gcc: Add --with_tls configuration option to change the
>         default TLS flavor.
>         * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
>         -mtls-dialect and with_tls defaults.
>         * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
>         two TLS flavors.
>         * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
>         * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
>         * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
>         sequence length data for TLSDESC.
>         (riscv_legitimize_tls_address): Add lowering of TLSDESC.
>         * doc/install.texi: Document --with-tls for RISC-V.
>         * doc/invoke.texi: Document -mtls-dialect for RISC-V.
>         * testsuite/gcc.target/riscv/tls_1.x: Add TLSDESC GD test case.
>         * testsuite/gcc.target/riscv/tlsdesc.c: Same as above.
> ---
> No regression in gcc tests for rv64gc, tested alongside the binutils and
> glibc implementation. Tested with --with_tls=desc.
>
> v2: Add with_tls configuration option, and a few readability improvements.
>     Added Changelog.
> v3: Add documentation per Kito's suggestion.
>     Fix minor issues pointed out by Kito and Jeff.
>     Thanks Kito Cheng and Jeff Law for review.
> v4: Add TLSDESC GD assembly test.
>     Rebase on top of trunk.
>
>  gcc/config.gcc                           | 15 ++++++++++++++-
>  gcc/config/riscv/riscv-opts.h            |  6 ++++++
>  gcc/config/riscv/riscv-protos.h          |  5 +++--
>  gcc/config/riscv/riscv.cc                | 24 ++++++++++++++++++++----
>  gcc/config/riscv/riscv.h                 |  9 +++++++--
>  gcc/config/riscv/riscv.md                | 20 +++++++++++++++++++-
>  gcc/config/riscv/riscv.opt               | 14 ++++++++++++++
>  gcc/doc/install.texi                     |  3 +++
>  gcc/doc/invoke.texi                      | 13 ++++++++++++-
>  gcc/testsuite/gcc.target/riscv/tls_1.x   |  5 +++++
>  gcc/testsuite/gcc.target/riscv/tlsdesc.c | 12 ++++++++++++
>  11 files changed, 115 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/tls_1.x
>  create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc.c
>
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 748430194f3..8bb22e9f590 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -2490,6 +2490,7 @@ riscv*-*-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:-trad}
>         ;;
>  riscv*-*-elf* | riscv*-*-rtems*)
>         tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
> @@ -2532,6 +2533,7 @@ riscv*-*-freebsd*)
>         # 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:-trad}
>         ;;
>
>  loongarch*-*-linux*)
> @@ -4658,7 +4660,7 @@ case "${target}" in
>                 ;;
>
>         riscv*-*-*)
> -               supported_defaults="abi arch tune riscv_attribute isa_spec"
> +               supported_defaults="abi arch tune riscv_attribute isa_spec tls"
>
>                 case "${target}" in
>                 riscv-* | riscv32*) xlen=32 ;;
> @@ -4788,6 +4790,17 @@ case "${target}" in
>                                 ;;
>                         esac
>                 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
>
>                 # Handle --with-multilib-list.
>                 if test "x${with_multilib_list}" != xdefault; then
> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> index 30efebbf07b..b2551968be0 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -138,4 +138,10 @@ enum stringop_strategy_enum {
>  #define TARGET_MAX_LMUL                                                        \
>    (int) (riscv_autovec_lmul == RVV_DYNAMIC ? RVV_M8 : riscv_autovec_lmul)
>
> +/* TLS types.  */
> +enum riscv_tls_type {
> +  TLS_TRADITIONAL,
> +  TLS_DESCRIPTORS
> +};
> +
>  #endif /* ! GCC_RISCV_OPTS_H */
> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> index 695ee24ad6f..f0d8f88dad7 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -33,9 +33,10 @@ enum riscv_symbol_type {
>    SYMBOL_TLS,
>    SYMBOL_TLS_LE,
>    SYMBOL_TLS_IE,
> -  SYMBOL_TLS_GD
> +  SYMBOL_TLS_GD,
> +  SYMBOL_TLSDESC,
>  };
> -#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
> +#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
>
>  /* Classifies an address.
>
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index 3f111fa0393..639a77922d9 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -892,6 +892,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
>      case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
>      case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
>      case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
> +    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
>      case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
>      default: gcc_unreachable ();
>      }
> @@ -1996,7 +1997,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
>  static rtx
>  riscv_legitimize_tls_address (rtx loc)
>  {
> -  rtx dest, tp, tmp;
> +  rtx dest, tp, tmp, a0;
>    enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
>
>  #if 0
> @@ -2012,9 +2013,24 @@ riscv_legitimize_tls_address (rtx loc)
>        /* Rely on section anchors for the optimization that LDM TLS
>          provides.  The anchor's address is loaded with GD TLS. */
>      case TLS_MODEL_GLOBAL_DYNAMIC:
> -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
> -      dest = gen_reg_rtx (Pmode);
> -      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
> +      if (TARGET_TLSDESC)
> +       {
> +         static unsigned seqno;
> +         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
> +         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
> +         dest = gen_reg_rtx (Pmode);
> +
> +         emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
> +         emit_insn (gen_add3_insn (dest, a0, tp));
> +         seqno++;
> +       }
> +      else
> +       {
> +         tmp = gen_rtx_REG (Pmode, GP_RETURN);
> +         dest = gen_reg_rtx (Pmode);
> +         emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
> +                             loc);
> +       }
>        break;
>
>      case TLS_MODEL_INITIAL_EXEC:
> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> index 6df9ec73c5e..5eb08c21cf4 100644
> --- a/gcc/config/riscv/riscv.h
> +++ b/gcc/config/riscv/riscv.h
> @@ -62,6 +62,7 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>     --with-abi is ignored if -mabi is specified.
>     --with-tune is ignored if -mtune or -mcpu is specified.
>     --with-isa-spec is ignored if -misa-spec is specified.
> +   --with-tls is ignored if -mtls-dialect is specified.
>
>     But using default -march/-mtune value if -mcpu don't have valid option.  */
>  #define OPTION_DEFAULT_SPECS \
> @@ -71,8 +72,9 @@ extern const char *riscv_multi_lib_check (int argc, const char **argv);
>    {"arch", "%{!march=*:"                                               \
>            "  %{!mcpu=*:-march=%(VALUE)}"                               \
>            "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },  \
> -  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
> -  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
> +  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },                               \
> +  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },                        \
> +  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},                \
>
>  #ifdef IN_LIBGCC2
>  #undef TARGET_64BIT
> @@ -1215,4 +1217,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
>  #define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
>  #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
>
> +/* Check TLS Descriptors mechanism is selected.  */
> +#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
> +
>  #endif /* ! GCC_RISCV_H */
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index a98918dfd43..c3676d751df 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -47,7 +47,7 @@
>    UNSPEC_TLS_LE
>    UNSPEC_TLS_IE
>    UNSPEC_TLS_GD
> -
> +  UNSPEC_TLSDESC
>    ;; High part of PC-relative address.
>    UNSPEC_AUIPC
>
> @@ -2017,6 +2017,24 @@
>     (set_attr "type" "load")
>     (set_attr "mode" "<MODE>")])
>
> +(define_insn "@tlsdesc<mode>"
> +  [(set (reg:P A0_REGNUM)
> +           (unspec:P
> +                       [(match_operand:P 0 "symbolic_operand" "")
> +                        (match_operand:P 1 "const_int_operand")]
> +                       UNSPEC_TLSDESC))
> +   (clobber (reg:P T0_REGNUM))]
> +  "TARGET_TLSDESC"
> +  {
> +    return ".LT%1: auipc\ta0,%%tlsdesc_hi(%0)\;"
> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
> +  }
> +  [(set_attr "type" "multi")
> +   (set_attr "length" "16")
> +   (set_attr "mode" "<MODE>")])
> +
>  (define_insn "auipc<mode>"
>    [(set (match_operand:P           0 "register_operand" "=r")
>         (unspec:P
> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> index 59ce7106ecf..8de2e8628d8 100644
> --- a/gcc/config/riscv/riscv.opt
> +++ b/gcc/config/riscv/riscv.opt
> @@ -556,3 +556,17 @@ Enum(stringop_strategy) String(vector) Value(STRATEGY_VECTOR)
>  mstringop-strategy=
>  Target RejectNegative Joined Enum(stringop_strategy) Var(stringop_strategy) Init(STRATEGY_AUTO)
>  Specify stringop expansion strategy.
> +
> +Enum
> +Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
> +Specify TLS dialect.
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index c1128d9274c..3b549ab62da 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -1184,6 +1184,9 @@ Specify the default TLS dialect, for systems were there is a choice.
>  For ARM targets, possible values for @var{dialect} are @code{gnu} or
>  @code{gnu2}, which select between the original GNU dialect and the GNU TLS
>  descriptor-based dialect.
> +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
> +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
> +descriptor-based dialect.
>
>  @item --enable-multiarch
>  Specify whether to enable or disable multiarch support.  The default is
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index 681e3f3f466..62c8bf9061b 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1252,7 +1252,8 @@ See RS/6000 and PowerPC Options.
>  -minline-atomics  -mno-inline-atomics
>  -minline-strlen  -mno-inline-strlen
>  -minline-strcmp  -mno-inline-strcmp
> --minline-strncmp  -mno-inline-strncmp}
> +-minline-strncmp  -mno-inline-strncmp
> +-mtls-dialect=desc  -mtls-dialect=trad}
>
>  @emph{RL78 Options}
>  @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
> @@ -29988,6 +29989,16 @@ which register to use as base register for reading the canary,
>  and from what offset from that base register. There is no default
>  register or offset as this is entirely for use within the Linux
>  kernel.
> +
> +@opindex mtls-dialect=desc
> +@item -mtls-dialect=desc
> +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.
> +

This can be simplified to:

"Use TLS descriptors for dynamic accesses of TLS variables."

I know aarch64 uses the term "mechanism" but "dialect" seems preferred?
I think in several places, "mechanism" can be changed to "dialect".

> +@opindex mtls-dialect=trad
> +@item -mtls-dialect=trad
> +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.  This is the default.
>  @end table

Use the traditional general-dynamic TLS model for dynamic accesses of
TLS variables.

It's a pity that aarch64 doesn't have a -mtls-dialect=trad test that
actually checks assembly:(

>  @node RL78 Options
> diff --git a/gcc/testsuite/gcc.target/riscv/tls_1.x b/gcc/testsuite/gcc.target/riscv/tls_1.x
> new file mode 100644
> index 00000000000..cf334ef55ed
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/tls_1.x
> @@ -0,0 +1,5 @@
> +extern __thread unsigned gd;
> +
> +unsigned get() {
> +       return gd;
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc.c b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
> new file mode 100644
> index 00000000000..f9ac9fe0d6d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
> @@ -0,0 +1,12 @@
> +/* { dg-require-effective-target tls_native } */
> +/* { dg-options "-O2 -fpic -mtls-dialect=desc --save-temps" } */
> +/* { dg-require-effective-target fpic } */
> +
> +#include "tls_1.x"
> +
> +/* { dg-final { scan-assembler-times "auipc\t\[a-x0-9\]+,%tlsdesc_hi" 1 } } */
> +/* { dg-final { scan-assembler-times "lw\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv32 } } } } */
> +/* { dg-final { scan-assembler-times "ld\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv64 } } } }*/
> +/* { dg-final { scan-assembler-times "addi\ta0,\[a-x0-9\]+,%tlsdesc_add_lo" 1 } } */
> +/* { dg-final { scan-assembler-times "jalr\tt0,\[a-x0-9\]+,%tlsdesc_call" 1 } } */
> +/* { dg-final { cleanup-saved-temps } } */
> --
> 2.43.0

Thanks for the test.


-- 
宋方睿

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH v5] RISC-V: Implement TLS Descriptors.
  2023-08-17 18:12 [PATCH] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
                   ` (3 preceding siblings ...)
  2023-12-05  7:01 ` [PATCH v4] " Tatsuyuki Ishi
@ 2024-03-29  5:52 ` Tatsuyuki Ishi
  2024-03-29  6:32   ` Kito Cheng
  4 siblings, 1 reply; 26+ messages in thread
From: Tatsuyuki Ishi @ 2024-03-29  5:52 UTC (permalink / raw)
  To: ishitatsuyuki; +Cc: gcc-patches, rui314, ruiu, kito.cheng, jeffreyalaw

This implements TLS Descriptors (TLSDESC) as specified in [1].

The 4-instruction sequence is implemented as a single RTX insn for
simplicity, but this can be revisited later if instruction scheduling or
more flexible RA is desired.

The default remains to be the traditional TLS model, but can be configured
with --with-tls={trad,desc}. The choice can be revisited once toolchain
and libc support ships.

[1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.

gcc/Changelog:
	* config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
	* config.gcc: Add --with-tls configuration option to change the
	default TLS flavor.
	* config/riscv/riscv.h: Add TARGET_TLSDESC determined from
	-mtls-dialect and with_tls defaults.
	* config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
	two TLS flavors.
	* config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
	* config/riscv/riscv.md: Add instruction sequence for TLSDESC.
	* config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
	sequence length data for TLSDESC.
	(riscv_legitimize_tls_address): Add lowering of TLSDESC.
	* doc/install.texi: Document --with-tls for RISC-V.
	* doc/invoke.texi: Document -mtls-dialect for RISC-V.
	* testsuite/gcc.target/riscv/tls_1.x: Add TLSDESC GD test case.
	* testsuite/gcc.target/riscv/tlsdesc.c: Same as above.
---
No regression in gcc tests for rv32gcv and rv64gcv, tested alongside
the binutils and glibc implementation. Tested with --with-tls=desc.

v2: Add with_tls configuration option, and a few readability improvements.
    Added Changelog.
v3: Add documentation per Kito's suggestion.
    Fix minor issues pointed out by Kito and Jeff.
    Thanks Kito Cheng and Jeff Law for review.
v4: Add TLSDESC GD assembly test.
    Rebase on top of trunk.
v5: Trivial rebase on top of trunk.

I have recently addressed relaxation concerns on binutils and RVV
register save/restore on glibc, so I'm sending out a trivial rebase
with the hope that the full set can be merged soon.

 gcc/config.gcc                           | 15 ++++++++++++++-
 gcc/config/riscv/riscv-opts.h            |  6 ++++++
 gcc/config/riscv/riscv-protos.h          |  5 +++--
 gcc/config/riscv/riscv.cc                | 24 ++++++++++++++++++++----
 gcc/config/riscv/riscv.h                 |  9 +++++++--
 gcc/config/riscv/riscv.md                | 20 +++++++++++++++++++-
 gcc/config/riscv/riscv.opt               | 14 ++++++++++++++
 gcc/doc/install.texi                     |  3 +++
 gcc/doc/invoke.texi                      | 13 ++++++++++++-
 gcc/testsuite/gcc.target/riscv/tls_1.x   |  5 +++++
 gcc/testsuite/gcc.target/riscv/tlsdesc.c | 12 ++++++++++++
 11 files changed, 115 insertions(+), 11 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/riscv/tls_1.x
 create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc.c

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 17873ac2103..1a5870672d2 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -2492,6 +2492,7 @@ riscv*-*-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:-trad}
 	;;
 riscv*-*-elf* | riscv*-*-rtems*)
 	tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
@@ -2534,6 +2535,7 @@ riscv*-*-freebsd*)
 	# 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:-trad}
 	;;
 
 loongarch*-*-linux*)
@@ -4671,7 +4673,7 @@ case "${target}" in
 		;;
 
 	riscv*-*-*)
-		supported_defaults="abi arch tune riscv_attribute isa_spec"
+		supported_defaults="abi arch tune riscv_attribute isa_spec tls"
 
 		case "${target}" in
 		riscv-* | riscv32*) xlen=32 ;;
@@ -4801,6 +4803,17 @@ case "${target}" in
 				;;
 			esac
 		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
 
 		# Handle --with-multilib-list.
 		if test "x${with_multilib_list}" != xdefault; then
diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
index 392b9169240..1b2dd5757a8 100644
--- a/gcc/config/riscv/riscv-opts.h
+++ b/gcc/config/riscv/riscv-opts.h
@@ -154,4 +154,10 @@ enum rvv_vector_bits_enum {
 #define TARGET_MAX_LMUL                                                        \
   (int) (rvv_max_lmul == RVV_DYNAMIC ? RVV_M8 : rvv_max_lmul)
 
+/* TLS types.  */
+enum riscv_tls_type {
+  TLS_TRADITIONAL,
+  TLS_DESCRIPTORS
+};
+
 #endif /* ! GCC_RISCV_OPTS_H */
diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
index b8735593805..066a5a5a7cc 100644
--- a/gcc/config/riscv/riscv-protos.h
+++ b/gcc/config/riscv/riscv-protos.h
@@ -34,9 +34,10 @@ enum riscv_symbol_type {
   SYMBOL_TLS,
   SYMBOL_TLS_LE,
   SYMBOL_TLS_IE,
-  SYMBOL_TLS_GD
+  SYMBOL_TLS_GD,
+  SYMBOL_TLSDESC,
 };
-#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
+#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
 
 /* Classifies an address.
 
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index fe9976bfffe..deac3e4e9e3 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -1072,6 +1072,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
     case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
     case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
     case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
+    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
     case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
     case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference.  */
     default: gcc_unreachable ();
@@ -2220,7 +2221,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
 static rtx
 riscv_legitimize_tls_address (rtx loc)
 {
-  rtx dest, tp, tmp;
+  rtx dest, tp, tmp, a0;
   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
 
 #if 0
@@ -2236,9 +2237,24 @@ riscv_legitimize_tls_address (rtx loc)
       /* Rely on section anchors for the optimization that LDM TLS
 	 provides.  The anchor's address is loaded with GD TLS. */
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
+      if (TARGET_TLSDESC)
+	{
+	  static unsigned seqno;
+	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+	  dest = gen_reg_rtx (Pmode);
+
+	  emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
+	  emit_insn (gen_add3_insn (dest, a0, tp));
+	  seqno++;
+	}
+      else
+	{
+	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
+	  dest = gen_reg_rtx (Pmode);
+	  emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
+			      loc);
+	}
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index da089a03e9d..10ad4aedd70 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -64,6 +64,7 @@ extern const char *riscv_arch_help (int argc, const char **argv);
    --with-abi is ignored if -mabi is specified.
    --with-tune is ignored if -mtune or -mcpu is specified.
    --with-isa-spec is ignored if -misa-spec is specified.
+   --with-tls is ignored if -mtls-dialect is specified.
 
    But using default -march/-mtune value if -mcpu don't have valid option.  */
 #define OPTION_DEFAULT_SPECS \
@@ -73,8 +74,9 @@ extern const char *riscv_arch_help (int argc, const char **argv);
   {"arch", "%{!march=*:"						\
 	   "  %{!mcpu=*:-march=%(VALUE)}"				\
 	   "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },	\
-  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
-  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
+  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },				\
+  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },			\
+  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},         	\
 
 #ifdef IN_LIBGCC2
 #undef TARGET_64BIT
@@ -1228,4 +1230,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
 #define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
 #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
 
+/* Check TLS Descriptors mechanism is selected.  */
+#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
+
 #endif /* ! GCC_RISCV_H */
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 0346cc3859d..c2b4323c53a 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -48,7 +48,7 @@
   UNSPEC_TLS_LE
   UNSPEC_TLS_IE
   UNSPEC_TLS_GD
-
+  UNSPEC_TLSDESC
   ;; High part of PC-relative address.
   UNSPEC_AUIPC
 
@@ -2089,6 +2089,24 @@
    (set_attr "type" "load")
    (set_attr "mode" "<MODE>")])
 
+(define_insn "@tlsdesc<mode>"
+  [(set (reg:P A0_REGNUM)
+	    (unspec:P
+			[(match_operand:P 0 "symbolic_operand" "")
+			 (match_operand:P 1 "const_int_operand")]
+			UNSPEC_TLSDESC))
+   (clobber (reg:P T0_REGNUM))]
+  "TARGET_TLSDESC"
+  {
+    return ".LT%1: auipc\ta0,%%tlsdesc_hi(%0)\;"
+           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
+           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
+           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
+  }
+  [(set_attr "type" "multi")
+   (set_attr "length" "16")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn "auipc<mode>"
   [(set (match_operand:P           0 "register_operand" "=r")
 	(unspec:P
diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
index 7d625af02d5..8da0764eb4b 100644
--- a/gcc/config/riscv/riscv.opt
+++ b/gcc/config/riscv/riscv.opt
@@ -606,3 +606,17 @@ Enum(rvv_vector_bits) String(zvl) Value(RVV_VECTOR_BITS_ZVL)
 mrvv-vector-bits=
 Target RejectNegative Joined Enum(rvv_vector_bits) Var(rvv_vector_bits) Init(RVV_VECTOR_BITS_SCALABLE)
 -mrvv-vector-bits=<string>	Set the kind of bits for an RVV vector register.
+
+Enum
+Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
+Specify TLS dialect.
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 269fe7ec870..120bb045f4d 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1187,6 +1187,9 @@ Specify the default TLS dialect, for systems were there is a choice.
 For ARM targets, possible values for @var{dialect} are @code{gnu} or
 @code{gnu2}, which select between the original GNU dialect and the GNU TLS
 descriptor-based dialect.
+For RISC-V targets, possible values for @var{dialect} are @code{trad} or
+@code{desc}, which select between the traditional GNU dialect and the GNU TLS
+descriptor-based dialect.
 
 @item --enable-multiarch
 Specify whether to enable or disable multiarch support.  The default is
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index d09074e13de..e4112bbe61e 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -1262,7 +1262,8 @@ See RS/6000 and PowerPC Options.
 -minline-atomics  -mno-inline-atomics
 -minline-strlen  -mno-inline-strlen
 -minline-strcmp  -mno-inline-strcmp
--minline-strncmp  -mno-inline-strncmp}
+-minline-strncmp  -mno-inline-strncmp
+-mtls-dialect=desc  -mtls-dialect=trad}
 
 @emph{RL78 Options}
 @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
@@ -30975,6 +30976,16 @@ which register to use as base register for reading the canary,
 and from what offset from that base register. There is no default
 register or offset as this is entirely for use within the Linux
 kernel.
+
+@opindex mtls-dialect=desc
+@item -mtls-dialect=desc
+Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
+of TLS variables.
+
+@opindex mtls-dialect=trad
+@item -mtls-dialect=trad
+Use traditional TLS as the thread-local storage mechanism for dynamic accesses
+of TLS variables.  This is the default.
 @end table
 
 @node RL78 Options
diff --git a/gcc/testsuite/gcc.target/riscv/tls_1.x b/gcc/testsuite/gcc.target/riscv/tls_1.x
new file mode 100644
index 00000000000..cf334ef55ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/tls_1.x
@@ -0,0 +1,5 @@
+extern __thread unsigned gd;
+
+unsigned get() {
+	return gd;
+}
diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc.c b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
new file mode 100644
index 00000000000..f9ac9fe0d6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
@@ -0,0 +1,12 @@
+/* { dg-require-effective-target tls_native } */
+/* { dg-options "-O2 -fpic -mtls-dialect=desc --save-temps" } */
+/* { dg-require-effective-target fpic } */
+
+#include "tls_1.x"
+
+/* { dg-final { scan-assembler-times "auipc\t\[a-x0-9\]+,%tlsdesc_hi" 1 } } */
+/* { dg-final { scan-assembler-times "lw\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv32 } } } } */
+/* { dg-final { scan-assembler-times "ld\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv64 } } } }*/
+/* { dg-final { scan-assembler-times "addi\ta0,\[a-x0-9\]+,%tlsdesc_add_lo" 1 } } */
+/* { dg-final { scan-assembler-times "jalr\tt0,\[a-x0-9\]+,%tlsdesc_call" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
-- 
2.44.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5] RISC-V: Implement TLS Descriptors.
  2024-03-29  5:52 ` [PATCH v5] " Tatsuyuki Ishi
@ 2024-03-29  6:32   ` Kito Cheng
  2024-04-08 14:31     ` Kito Cheng
  0 siblings, 1 reply; 26+ messages in thread
From: Kito Cheng @ 2024-03-29  6:32 UTC (permalink / raw)
  To: Tatsuyuki Ishi
  Cc: gcc-patches, rui314, ruiu, jeffreyalaw, Palmer Dabbelt, Fangrui Song

Hi Tatsuyuki:

Thanks for your hard work and keep updating, the patch set is LGTM, I
plan to commit this next week if no further comments :)

Hi MaskRay:

Thanks for your review on the patchset! just put you into the cc list
in case you have few more comments :)


On Fri, Mar 29, 2024 at 1:53 PM Tatsuyuki Ishi <ishitatsuyuki@gmail.com> wrote:
>
> This implements TLS Descriptors (TLSDESC) as specified in [1].
>
> The 4-instruction sequence is implemented as a single RTX insn for
> simplicity, but this can be revisited later if instruction scheduling or
> more flexible RA is desired.
>
> The default remains to be the traditional TLS model, but can be configured
> with --with-tls={trad,desc}. The choice can be revisited once toolchain
> and libc support ships.
>
> [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
>
> gcc/Changelog:
>         * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
>         * config.gcc: Add --with-tls configuration option to change the
>         default TLS flavor.
>         * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
>         -mtls-dialect and with_tls defaults.
>         * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
>         two TLS flavors.
>         * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
>         * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
>         * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
>         sequence length data for TLSDESC.
>         (riscv_legitimize_tls_address): Add lowering of TLSDESC.
>         * doc/install.texi: Document --with-tls for RISC-V.
>         * doc/invoke.texi: Document -mtls-dialect for RISC-V.
>         * testsuite/gcc.target/riscv/tls_1.x: Add TLSDESC GD test case.
>         * testsuite/gcc.target/riscv/tlsdesc.c: Same as above.
> ---
> No regression in gcc tests for rv32gcv and rv64gcv, tested alongside
> the binutils and glibc implementation. Tested with --with-tls=desc.
>
> v2: Add with_tls configuration option, and a few readability improvements.
>     Added Changelog.
> v3: Add documentation per Kito's suggestion.
>     Fix minor issues pointed out by Kito and Jeff.
>     Thanks Kito Cheng and Jeff Law for review.
> v4: Add TLSDESC GD assembly test.
>     Rebase on top of trunk.
> v5: Trivial rebase on top of trunk.
>
> I have recently addressed relaxation concerns on binutils and RVV
> register save/restore on glibc, so I'm sending out a trivial rebase
> with the hope that the full set can be merged soon.
>
>  gcc/config.gcc                           | 15 ++++++++++++++-
>  gcc/config/riscv/riscv-opts.h            |  6 ++++++
>  gcc/config/riscv/riscv-protos.h          |  5 +++--
>  gcc/config/riscv/riscv.cc                | 24 ++++++++++++++++++++----
>  gcc/config/riscv/riscv.h                 |  9 +++++++--
>  gcc/config/riscv/riscv.md                | 20 +++++++++++++++++++-
>  gcc/config/riscv/riscv.opt               | 14 ++++++++++++++
>  gcc/doc/install.texi                     |  3 +++
>  gcc/doc/invoke.texi                      | 13 ++++++++++++-
>  gcc/testsuite/gcc.target/riscv/tls_1.x   |  5 +++++
>  gcc/testsuite/gcc.target/riscv/tlsdesc.c | 12 ++++++++++++
>  11 files changed, 115 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/tls_1.x
>  create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc.c
>
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 17873ac2103..1a5870672d2 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -2492,6 +2492,7 @@ riscv*-*-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:-trad}
>         ;;
>  riscv*-*-elf* | riscv*-*-rtems*)
>         tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
> @@ -2534,6 +2535,7 @@ riscv*-*-freebsd*)
>         # 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:-trad}
>         ;;
>
>  loongarch*-*-linux*)
> @@ -4671,7 +4673,7 @@ case "${target}" in
>                 ;;
>
>         riscv*-*-*)
> -               supported_defaults="abi arch tune riscv_attribute isa_spec"
> +               supported_defaults="abi arch tune riscv_attribute isa_spec tls"
>
>                 case "${target}" in
>                 riscv-* | riscv32*) xlen=32 ;;
> @@ -4801,6 +4803,17 @@ case "${target}" in
>                                 ;;
>                         esac
>                 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
>
>                 # Handle --with-multilib-list.
>                 if test "x${with_multilib_list}" != xdefault; then
> diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> index 392b9169240..1b2dd5757a8 100644
> --- a/gcc/config/riscv/riscv-opts.h
> +++ b/gcc/config/riscv/riscv-opts.h
> @@ -154,4 +154,10 @@ enum rvv_vector_bits_enum {
>  #define TARGET_MAX_LMUL                                                        \
>    (int) (rvv_max_lmul == RVV_DYNAMIC ? RVV_M8 : rvv_max_lmul)
>
> +/* TLS types.  */
> +enum riscv_tls_type {
> +  TLS_TRADITIONAL,
> +  TLS_DESCRIPTORS
> +};
> +
>  #endif /* ! GCC_RISCV_OPTS_H */
> diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> index b8735593805..066a5a5a7cc 100644
> --- a/gcc/config/riscv/riscv-protos.h
> +++ b/gcc/config/riscv/riscv-protos.h
> @@ -34,9 +34,10 @@ enum riscv_symbol_type {
>    SYMBOL_TLS,
>    SYMBOL_TLS_LE,
>    SYMBOL_TLS_IE,
> -  SYMBOL_TLS_GD
> +  SYMBOL_TLS_GD,
> +  SYMBOL_TLSDESC,
>  };
> -#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
> +#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
>
>  /* Classifies an address.
>
> diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> index fe9976bfffe..deac3e4e9e3 100644
> --- a/gcc/config/riscv/riscv.cc
> +++ b/gcc/config/riscv/riscv.cc
> @@ -1072,6 +1072,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
>      case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
>      case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
>      case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
> +    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
>      case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
>      case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference.  */
>      default: gcc_unreachable ();
> @@ -2220,7 +2221,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
>  static rtx
>  riscv_legitimize_tls_address (rtx loc)
>  {
> -  rtx dest, tp, tmp;
> +  rtx dest, tp, tmp, a0;
>    enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
>
>  #if 0
> @@ -2236,9 +2237,24 @@ riscv_legitimize_tls_address (rtx loc)
>        /* Rely on section anchors for the optimization that LDM TLS
>          provides.  The anchor's address is loaded with GD TLS. */
>      case TLS_MODEL_GLOBAL_DYNAMIC:
> -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
> -      dest = gen_reg_rtx (Pmode);
> -      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
> +      if (TARGET_TLSDESC)
> +       {
> +         static unsigned seqno;
> +         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
> +         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
> +         dest = gen_reg_rtx (Pmode);
> +
> +         emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
> +         emit_insn (gen_add3_insn (dest, a0, tp));
> +         seqno++;
> +       }
> +      else
> +       {
> +         tmp = gen_rtx_REG (Pmode, GP_RETURN);
> +         dest = gen_reg_rtx (Pmode);
> +         emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
> +                             loc);
> +       }
>        break;
>
>      case TLS_MODEL_INITIAL_EXEC:
> diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> index da089a03e9d..10ad4aedd70 100644
> --- a/gcc/config/riscv/riscv.h
> +++ b/gcc/config/riscv/riscv.h
> @@ -64,6 +64,7 @@ extern const char *riscv_arch_help (int argc, const char **argv);
>     --with-abi is ignored if -mabi is specified.
>     --with-tune is ignored if -mtune or -mcpu is specified.
>     --with-isa-spec is ignored if -misa-spec is specified.
> +   --with-tls is ignored if -mtls-dialect is specified.
>
>     But using default -march/-mtune value if -mcpu don't have valid option.  */
>  #define OPTION_DEFAULT_SPECS \
> @@ -73,8 +74,9 @@ extern const char *riscv_arch_help (int argc, const char **argv);
>    {"arch", "%{!march=*:"                                               \
>            "  %{!mcpu=*:-march=%(VALUE)}"                               \
>            "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },  \
> -  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
> -  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
> +  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },                               \
> +  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },                        \
> +  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},                \
>
>  #ifdef IN_LIBGCC2
>  #undef TARGET_64BIT
> @@ -1228,4 +1230,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
>  #define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
>  #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
>
> +/* Check TLS Descriptors mechanism is selected.  */
> +#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
> +
>  #endif /* ! GCC_RISCV_H */
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index 0346cc3859d..c2b4323c53a 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -48,7 +48,7 @@
>    UNSPEC_TLS_LE
>    UNSPEC_TLS_IE
>    UNSPEC_TLS_GD
> -
> +  UNSPEC_TLSDESC
>    ;; High part of PC-relative address.
>    UNSPEC_AUIPC
>
> @@ -2089,6 +2089,24 @@
>     (set_attr "type" "load")
>     (set_attr "mode" "<MODE>")])
>
> +(define_insn "@tlsdesc<mode>"
> +  [(set (reg:P A0_REGNUM)
> +           (unspec:P
> +                       [(match_operand:P 0 "symbolic_operand" "")
> +                        (match_operand:P 1 "const_int_operand")]
> +                       UNSPEC_TLSDESC))
> +   (clobber (reg:P T0_REGNUM))]
> +  "TARGET_TLSDESC"
> +  {
> +    return ".LT%1: auipc\ta0,%%tlsdesc_hi(%0)\;"
> +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
> +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
> +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
> +  }
> +  [(set_attr "type" "multi")
> +   (set_attr "length" "16")
> +   (set_attr "mode" "<MODE>")])
> +
>  (define_insn "auipc<mode>"
>    [(set (match_operand:P           0 "register_operand" "=r")
>         (unspec:P
> diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> index 7d625af02d5..8da0764eb4b 100644
> --- a/gcc/config/riscv/riscv.opt
> +++ b/gcc/config/riscv/riscv.opt
> @@ -606,3 +606,17 @@ Enum(rvv_vector_bits) String(zvl) Value(RVV_VECTOR_BITS_ZVL)
>  mrvv-vector-bits=
>  Target RejectNegative Joined Enum(rvv_vector_bits) Var(rvv_vector_bits) Init(RVV_VECTOR_BITS_SCALABLE)
>  -mrvv-vector-bits=<string>     Set the kind of bits for an RVV vector register.
> +
> +Enum
> +Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
> +Specify TLS dialect.
> diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> index 269fe7ec870..120bb045f4d 100644
> --- a/gcc/doc/install.texi
> +++ b/gcc/doc/install.texi
> @@ -1187,6 +1187,9 @@ Specify the default TLS dialect, for systems were there is a choice.
>  For ARM targets, possible values for @var{dialect} are @code{gnu} or
>  @code{gnu2}, which select between the original GNU dialect and the GNU TLS
>  descriptor-based dialect.
> +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
> +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
> +descriptor-based dialect.
>
>  @item --enable-multiarch
>  Specify whether to enable or disable multiarch support.  The default is
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index d09074e13de..e4112bbe61e 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -1262,7 +1262,8 @@ See RS/6000 and PowerPC Options.
>  -minline-atomics  -mno-inline-atomics
>  -minline-strlen  -mno-inline-strlen
>  -minline-strcmp  -mno-inline-strcmp
> --minline-strncmp  -mno-inline-strncmp}
> +-minline-strncmp  -mno-inline-strncmp
> +-mtls-dialect=desc  -mtls-dialect=trad}
>
>  @emph{RL78 Options}
>  @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
> @@ -30975,6 +30976,16 @@ which register to use as base register for reading the canary,
>  and from what offset from that base register. There is no default
>  register or offset as this is entirely for use within the Linux
>  kernel.
> +
> +@opindex mtls-dialect=desc
> +@item -mtls-dialect=desc
> +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.
> +
> +@opindex mtls-dialect=trad
> +@item -mtls-dialect=trad
> +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
> +of TLS variables.  This is the default.
>  @end table
>
>  @node RL78 Options
> diff --git a/gcc/testsuite/gcc.target/riscv/tls_1.x b/gcc/testsuite/gcc.target/riscv/tls_1.x
> new file mode 100644
> index 00000000000..cf334ef55ed
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/tls_1.x
> @@ -0,0 +1,5 @@
> +extern __thread unsigned gd;
> +
> +unsigned get() {
> +       return gd;
> +}
> diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc.c b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
> new file mode 100644
> index 00000000000..f9ac9fe0d6d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
> @@ -0,0 +1,12 @@
> +/* { dg-require-effective-target tls_native } */
> +/* { dg-options "-O2 -fpic -mtls-dialect=desc --save-temps" } */
> +/* { dg-require-effective-target fpic } */
> +
> +#include "tls_1.x"
> +
> +/* { dg-final { scan-assembler-times "auipc\t\[a-x0-9\]+,%tlsdesc_hi" 1 } } */
> +/* { dg-final { scan-assembler-times "lw\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv32 } } } } */
> +/* { dg-final { scan-assembler-times "ld\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv64 } } } }*/
> +/* { dg-final { scan-assembler-times "addi\ta0,\[a-x0-9\]+,%tlsdesc_add_lo" 1 } } */
> +/* { dg-final { scan-assembler-times "jalr\tt0,\[a-x0-9\]+,%tlsdesc_call" 1 } } */
> +/* { dg-final { cleanup-saved-temps } } */
> --
> 2.44.0
>

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH v5] RISC-V: Implement TLS Descriptors.
  2024-03-29  6:32   ` Kito Cheng
@ 2024-04-08 14:31     ` Kito Cheng
  0 siblings, 0 replies; 26+ messages in thread
From: Kito Cheng @ 2024-04-08 14:31 UTC (permalink / raw)
  To: Tatsuyuki Ishi
  Cc: gcc-patches, rui314, ruiu, jeffreyalaw, Palmer Dabbelt, Fangrui Song

Committed to trunk, thanks Tatsuyuki!

On Fri, Mar 29, 2024 at 2:32 PM Kito Cheng <kito.cheng@gmail.com> wrote:
>
> Hi Tatsuyuki:
>
> Thanks for your hard work and keep updating, the patch set is LGTM, I
> plan to commit this next week if no further comments :)
>
> Hi MaskRay:
>
> Thanks for your review on the patchset! just put you into the cc list
> in case you have few more comments :)
>
>
> On Fri, Mar 29, 2024 at 1:53 PM Tatsuyuki Ishi <ishitatsuyuki@gmail.com> wrote:
> >
> > This implements TLS Descriptors (TLSDESC) as specified in [1].
> >
> > The 4-instruction sequence is implemented as a single RTX insn for
> > simplicity, but this can be revisited later if instruction scheduling or
> > more flexible RA is desired.
> >
> > The default remains to be the traditional TLS model, but can be configured
> > with --with-tls={trad,desc}. The choice can be revisited once toolchain
> > and libc support ships.
> >
> > [1]: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/pull/373.
> >
> > gcc/Changelog:
> >         * config/riscv/riscv.opt: Add -mtls-dialect to configure TLS flavor.
> >         * config.gcc: Add --with-tls configuration option to change the
> >         default TLS flavor.
> >         * config/riscv/riscv.h: Add TARGET_TLSDESC determined from
> >         -mtls-dialect and with_tls defaults.
> >         * config/riscv/riscv-opts.h: Define enum riscv_tls_type for the
> >         two TLS flavors.
> >         * config/riscv/riscv-protos.h: Define SYMBOL_TLSDESC symbol type.
> >         * config/riscv/riscv.md: Add instruction sequence for TLSDESC.
> >         * config/riscv/riscv.cc (riscv_symbol_insns): Add instruction
> >         sequence length data for TLSDESC.
> >         (riscv_legitimize_tls_address): Add lowering of TLSDESC.
> >         * doc/install.texi: Document --with-tls for RISC-V.
> >         * doc/invoke.texi: Document -mtls-dialect for RISC-V.
> >         * testsuite/gcc.target/riscv/tls_1.x: Add TLSDESC GD test case.
> >         * testsuite/gcc.target/riscv/tlsdesc.c: Same as above.
> > ---
> > No regression in gcc tests for rv32gcv and rv64gcv, tested alongside
> > the binutils and glibc implementation. Tested with --with-tls=desc.
> >
> > v2: Add with_tls configuration option, and a few readability improvements.
> >     Added Changelog.
> > v3: Add documentation per Kito's suggestion.
> >     Fix minor issues pointed out by Kito and Jeff.
> >     Thanks Kito Cheng and Jeff Law for review.
> > v4: Add TLSDESC GD assembly test.
> >     Rebase on top of trunk.
> > v5: Trivial rebase on top of trunk.
> >
> > I have recently addressed relaxation concerns on binutils and RVV
> > register save/restore on glibc, so I'm sending out a trivial rebase
> > with the hope that the full set can be merged soon.
> >
> >  gcc/config.gcc                           | 15 ++++++++++++++-
> >  gcc/config/riscv/riscv-opts.h            |  6 ++++++
> >  gcc/config/riscv/riscv-protos.h          |  5 +++--
> >  gcc/config/riscv/riscv.cc                | 24 ++++++++++++++++++++----
> >  gcc/config/riscv/riscv.h                 |  9 +++++++--
> >  gcc/config/riscv/riscv.md                | 20 +++++++++++++++++++-
> >  gcc/config/riscv/riscv.opt               | 14 ++++++++++++++
> >  gcc/doc/install.texi                     |  3 +++
> >  gcc/doc/invoke.texi                      | 13 ++++++++++++-
> >  gcc/testsuite/gcc.target/riscv/tls_1.x   |  5 +++++
> >  gcc/testsuite/gcc.target/riscv/tlsdesc.c | 12 ++++++++++++
> >  11 files changed, 115 insertions(+), 11 deletions(-)
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/tls_1.x
> >  create mode 100644 gcc/testsuite/gcc.target/riscv/tlsdesc.c
> >
> > diff --git a/gcc/config.gcc b/gcc/config.gcc
> > index 17873ac2103..1a5870672d2 100644
> > --- a/gcc/config.gcc
> > +++ b/gcc/config.gcc
> > @@ -2492,6 +2492,7 @@ riscv*-*-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:-trad}
> >         ;;
> >  riscv*-*-elf* | riscv*-*-rtems*)
> >         tm_file="elfos.h newlib-stdint.h ${tm_file} riscv/elf.h"
> > @@ -2534,6 +2535,7 @@ riscv*-*-freebsd*)
> >         # 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:-trad}
> >         ;;
> >
> >  loongarch*-*-linux*)
> > @@ -4671,7 +4673,7 @@ case "${target}" in
> >                 ;;
> >
> >         riscv*-*-*)
> > -               supported_defaults="abi arch tune riscv_attribute isa_spec"
> > +               supported_defaults="abi arch tune riscv_attribute isa_spec tls"
> >
> >                 case "${target}" in
> >                 riscv-* | riscv32*) xlen=32 ;;
> > @@ -4801,6 +4803,17 @@ case "${target}" in
> >                                 ;;
> >                         esac
> >                 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
> >
> >                 # Handle --with-multilib-list.
> >                 if test "x${with_multilib_list}" != xdefault; then
> > diff --git a/gcc/config/riscv/riscv-opts.h b/gcc/config/riscv/riscv-opts.h
> > index 392b9169240..1b2dd5757a8 100644
> > --- a/gcc/config/riscv/riscv-opts.h
> > +++ b/gcc/config/riscv/riscv-opts.h
> > @@ -154,4 +154,10 @@ enum rvv_vector_bits_enum {
> >  #define TARGET_MAX_LMUL                                                        \
> >    (int) (rvv_max_lmul == RVV_DYNAMIC ? RVV_M8 : rvv_max_lmul)
> >
> > +/* TLS types.  */
> > +enum riscv_tls_type {
> > +  TLS_TRADITIONAL,
> > +  TLS_DESCRIPTORS
> > +};
> > +
> >  #endif /* ! GCC_RISCV_OPTS_H */
> > diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h
> > index b8735593805..066a5a5a7cc 100644
> > --- a/gcc/config/riscv/riscv-protos.h
> > +++ b/gcc/config/riscv/riscv-protos.h
> > @@ -34,9 +34,10 @@ enum riscv_symbol_type {
> >    SYMBOL_TLS,
> >    SYMBOL_TLS_LE,
> >    SYMBOL_TLS_IE,
> > -  SYMBOL_TLS_GD
> > +  SYMBOL_TLS_GD,
> > +  SYMBOL_TLSDESC,
> >  };
> > -#define NUM_SYMBOL_TYPES (SYMBOL_TLS_GD + 1)
> > +#define NUM_SYMBOL_TYPES (SYMBOL_TLSDESC + 1)
> >
> >  /* Classifies an address.
> >
> > diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
> > index fe9976bfffe..deac3e4e9e3 100644
> > --- a/gcc/config/riscv/riscv.cc
> > +++ b/gcc/config/riscv/riscv.cc
> > @@ -1072,6 +1072,7 @@ static int riscv_symbol_insns (enum riscv_symbol_type type)
> >      case SYMBOL_ABSOLUTE: return 2; /* LUI + the reference.  */
> >      case SYMBOL_PCREL: return 2; /* AUIPC + the reference.  */
> >      case SYMBOL_TLS_LE: return 3; /* LUI + ADD TP + the reference.  */
> > +    case SYMBOL_TLSDESC: return 6; /* 4-instruction call + ADD TP + the reference.  */
> >      case SYMBOL_GOT_DISP: return 3; /* AUIPC + LD GOT + the reference.  */
> >      case SYMBOL_FORCE_TO_MEM: return 3; /* AUIPC + LD + the reference.  */
> >      default: gcc_unreachable ();
> > @@ -2220,7 +2221,7 @@ riscv_call_tls_get_addr (rtx sym, rtx result)
> >  static rtx
> >  riscv_legitimize_tls_address (rtx loc)
> >  {
> > -  rtx dest, tp, tmp;
> > +  rtx dest, tp, tmp, a0;
> >    enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
> >
> >  #if 0
> > @@ -2236,9 +2237,24 @@ riscv_legitimize_tls_address (rtx loc)
> >        /* Rely on section anchors for the optimization that LDM TLS
> >          provides.  The anchor's address is loaded with GD TLS. */
> >      case TLS_MODEL_GLOBAL_DYNAMIC:
> > -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
> > -      dest = gen_reg_rtx (Pmode);
> > -      emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp, loc);
> > +      if (TARGET_TLSDESC)
> > +       {
> > +         static unsigned seqno;
> > +         tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
> > +         a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
> > +         dest = gen_reg_rtx (Pmode);
> > +
> > +         emit_insn (gen_tlsdesc (Pmode, loc, GEN_INT (seqno)));
> > +         emit_insn (gen_add3_insn (dest, a0, tp));
> > +         seqno++;
> > +       }
> > +      else
> > +       {
> > +         tmp = gen_rtx_REG (Pmode, GP_RETURN);
> > +         dest = gen_reg_rtx (Pmode);
> > +         emit_libcall_block (riscv_call_tls_get_addr (loc, tmp), dest, tmp,
> > +                             loc);
> > +       }
> >        break;
> >
> >      case TLS_MODEL_INITIAL_EXEC:
> > diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
> > index da089a03e9d..10ad4aedd70 100644
> > --- a/gcc/config/riscv/riscv.h
> > +++ b/gcc/config/riscv/riscv.h
> > @@ -64,6 +64,7 @@ extern const char *riscv_arch_help (int argc, const char **argv);
> >     --with-abi is ignored if -mabi is specified.
> >     --with-tune is ignored if -mtune or -mcpu is specified.
> >     --with-isa-spec is ignored if -misa-spec is specified.
> > +   --with-tls is ignored if -mtls-dialect is specified.
> >
> >     But using default -march/-mtune value if -mcpu don't have valid option.  */
> >  #define OPTION_DEFAULT_SPECS \
> > @@ -73,8 +74,9 @@ extern const char *riscv_arch_help (int argc, const char **argv);
> >    {"arch", "%{!march=*:"                                               \
> >            "  %{!mcpu=*:-march=%(VALUE)}"                               \
> >            "  %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" },  \
> > -  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
> > -  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" }, \
> > +  {"abi", "%{!mabi=*:-mabi=%(VALUE)}" },                               \
> > +  {"isa_spec", "%{!misa-spec=*:-misa-spec=%(VALUE)}" },                        \
> > +  {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"},                \
> >
> >  #ifdef IN_LIBGCC2
> >  #undef TARGET_64BIT
> > @@ -1228,4 +1230,7 @@ extern void riscv_remove_unneeded_save_restore_calls (void);
> >  #define HAVE_POST_MODIFY_DISP TARGET_XTHEADMEMIDX
> >  #define HAVE_PRE_MODIFY_DISP  TARGET_XTHEADMEMIDX
> >
> > +/* Check TLS Descriptors mechanism is selected.  */
> > +#define TARGET_TLSDESC (riscv_tls_dialect == TLS_DESCRIPTORS)
> > +
> >  #endif /* ! GCC_RISCV_H */
> > diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> > index 0346cc3859d..c2b4323c53a 100644
> > --- a/gcc/config/riscv/riscv.md
> > +++ b/gcc/config/riscv/riscv.md
> > @@ -48,7 +48,7 @@
> >    UNSPEC_TLS_LE
> >    UNSPEC_TLS_IE
> >    UNSPEC_TLS_GD
> > -
> > +  UNSPEC_TLSDESC
> >    ;; High part of PC-relative address.
> >    UNSPEC_AUIPC
> >
> > @@ -2089,6 +2089,24 @@
> >     (set_attr "type" "load")
> >     (set_attr "mode" "<MODE>")])
> >
> > +(define_insn "@tlsdesc<mode>"
> > +  [(set (reg:P A0_REGNUM)
> > +           (unspec:P
> > +                       [(match_operand:P 0 "symbolic_operand" "")
> > +                        (match_operand:P 1 "const_int_operand")]
> > +                       UNSPEC_TLSDESC))
> > +   (clobber (reg:P T0_REGNUM))]
> > +  "TARGET_TLSDESC"
> > +  {
> > +    return ".LT%1: auipc\ta0,%%tlsdesc_hi(%0)\;"
> > +           "<load>\tt0,%%tlsdesc_load_lo(.LT%1)(a0)\;"
> > +           "addi\ta0,a0,%%tlsdesc_add_lo(.LT%1)\;"
> > +           "jalr\tt0,t0,%%tlsdesc_call(.LT%1)";
> > +  }
> > +  [(set_attr "type" "multi")
> > +   (set_attr "length" "16")
> > +   (set_attr "mode" "<MODE>")])
> > +
> >  (define_insn "auipc<mode>"
> >    [(set (match_operand:P           0 "register_operand" "=r")
> >         (unspec:P
> > diff --git a/gcc/config/riscv/riscv.opt b/gcc/config/riscv/riscv.opt
> > index 7d625af02d5..8da0764eb4b 100644
> > --- a/gcc/config/riscv/riscv.opt
> > +++ b/gcc/config/riscv/riscv.opt
> > @@ -606,3 +606,17 @@ Enum(rvv_vector_bits) String(zvl) Value(RVV_VECTOR_BITS_ZVL)
> >  mrvv-vector-bits=
> >  Target RejectNegative Joined Enum(rvv_vector_bits) Var(rvv_vector_bits) Init(RVV_VECTOR_BITS_SCALABLE)
> >  -mrvv-vector-bits=<string>     Set the kind of bits for an RVV vector register.
> > +
> > +Enum
> > +Name(tls_type) Type(enum riscv_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(riscv_tls_dialect) Init(TLS_TRADITIONAL) Save
> > +Specify TLS dialect.
> > diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
> > index 269fe7ec870..120bb045f4d 100644
> > --- a/gcc/doc/install.texi
> > +++ b/gcc/doc/install.texi
> > @@ -1187,6 +1187,9 @@ Specify the default TLS dialect, for systems were there is a choice.
> >  For ARM targets, possible values for @var{dialect} are @code{gnu} or
> >  @code{gnu2}, which select between the original GNU dialect and the GNU TLS
> >  descriptor-based dialect.
> > +For RISC-V targets, possible values for @var{dialect} are @code{trad} or
> > +@code{desc}, which select between the traditional GNU dialect and the GNU TLS
> > +descriptor-based dialect.
> >
> >  @item --enable-multiarch
> >  Specify whether to enable or disable multiarch support.  The default is
> > diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> > index d09074e13de..e4112bbe61e 100644
> > --- a/gcc/doc/invoke.texi
> > +++ b/gcc/doc/invoke.texi
> > @@ -1262,7 +1262,8 @@ See RS/6000 and PowerPC Options.
> >  -minline-atomics  -mno-inline-atomics
> >  -minline-strlen  -mno-inline-strlen
> >  -minline-strcmp  -mno-inline-strcmp
> > --minline-strncmp  -mno-inline-strncmp}
> > +-minline-strncmp  -mno-inline-strncmp
> > +-mtls-dialect=desc  -mtls-dialect=trad}
> >
> >  @emph{RL78 Options}
> >  @gccoptlist{-msim  -mmul=none  -mmul=g13  -mmul=g14  -mallregs
> > @@ -30975,6 +30976,16 @@ which register to use as base register for reading the canary,
> >  and from what offset from that base register. There is no default
> >  register or offset as this is entirely for use within the Linux
> >  kernel.
> > +
> > +@opindex mtls-dialect=desc
> > +@item -mtls-dialect=desc
> > +Use TLS descriptors as the thread-local storage mechanism for dynamic accesses
> > +of TLS variables.
> > +
> > +@opindex mtls-dialect=trad
> > +@item -mtls-dialect=trad
> > +Use traditional TLS as the thread-local storage mechanism for dynamic accesses
> > +of TLS variables.  This is the default.
> >  @end table
> >
> >  @node RL78 Options
> > diff --git a/gcc/testsuite/gcc.target/riscv/tls_1.x b/gcc/testsuite/gcc.target/riscv/tls_1.x
> > new file mode 100644
> > index 00000000000..cf334ef55ed
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/riscv/tls_1.x
> > @@ -0,0 +1,5 @@
> > +extern __thread unsigned gd;
> > +
> > +unsigned get() {
> > +       return gd;
> > +}
> > diff --git a/gcc/testsuite/gcc.target/riscv/tlsdesc.c b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
> > new file mode 100644
> > index 00000000000..f9ac9fe0d6d
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.target/riscv/tlsdesc.c
> > @@ -0,0 +1,12 @@
> > +/* { dg-require-effective-target tls_native } */
> > +/* { dg-options "-O2 -fpic -mtls-dialect=desc --save-temps" } */
> > +/* { dg-require-effective-target fpic } */
> > +
> > +#include "tls_1.x"
> > +
> > +/* { dg-final { scan-assembler-times "auipc\t\[a-x0-9\]+,%tlsdesc_hi" 1 } } */
> > +/* { dg-final { scan-assembler-times "lw\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv32 } } } } */
> > +/* { dg-final { scan-assembler-times "ld\t\[a-x0-9\]+,%tlsdesc_load_lo" 1 { target { rv64 } } } }*/
> > +/* { dg-final { scan-assembler-times "addi\ta0,\[a-x0-9\]+,%tlsdesc_add_lo" 1 } } */
> > +/* { dg-final { scan-assembler-times "jalr\tt0,\[a-x0-9\]+,%tlsdesc_call" 1 } } */
> > +/* { dg-final { cleanup-saved-temps } } */
> > --
> > 2.44.0
> >

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2024-04-08 14:32 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-17 18:12 [PATCH] RISC-V: Implement TLS Descriptors Tatsuyuki Ishi
2023-08-29 13:40 ` Kito Cheng
2023-09-08 10:49 ` [PATCH v2] " Tatsuyuki Ishi
2023-10-02 14:10   ` Kito Cheng
2023-11-16  1:17     ` Fangrui Song
2023-11-16  1:39       ` Tatsuyuki Ishi
2023-11-16  5:21         ` Jeff Law
2023-11-16  5:18       ` Jeff Law
2023-11-16  1:07   ` Jeff Law
2023-11-16  1:51     ` Tatsuyuki Ishi
2023-11-16  5:23       ` Jeff Law
2023-11-16  5:33         ` Fangrui Song
2023-11-16  5:36           ` Jeff Law
2023-11-16  5:37           ` Tatsuyuki Ishi
2023-11-20 13:17 ` [PATCH v3] " Tatsuyuki Ishi
2023-11-21  6:59   ` Fangrui Song
2023-11-21  7:07     ` Tatsuyuki Ishi
2023-12-05 16:49     ` Tatsuyuki Ishi
2023-11-23 10:57   ` Florian Weimer
2023-11-23 11:34     ` Tatsuyuki Ishi
2023-11-23 11:40       ` Florian Weimer
2023-12-05  7:01 ` [PATCH v4] " Tatsuyuki Ishi
2024-01-27  3:24   ` Fangrui Song
2024-03-29  5:52 ` [PATCH v5] " Tatsuyuki Ishi
2024-03-29  6:32   ` Kito Cheng
2024-04-08 14:31     ` Kito Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).