]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: Added TLS Le Relax support.
authorLulu Cheng <chenglulu@loongson.cn>
Tue, 12 Dec 2023 08:32:31 +0000 (16:32 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Tue, 2 Jan 2024 01:33:27 +0000 (09:33 +0800)
Check whether the assembler supports tls le relax. If it supports it, the assembly
instruction sequence of tls le relax will be generated by default.

The original way to obtain the tls le symbol address:
    lu12i.w $rd, %le_hi20(sym)
    ori $rd, $rd, %le_lo12(sym)
    add.{w/d} $rd, $rd, $tp

If the assembler supports tls le relax, the following sequence is generated:

    lu12i.w $rd, %le_hi20_r(sym)
    add.{w/d} $rd,$rd,$tp,%le_add_r(sym)
    addi.{w/d} $rd,$rd,%le_lo12_r(sym)

gcc/ChangeLog:

* config.in: Regenerate.
* config/loongarch/loongarch-opts.h (HAVE_AS_TLS_LE_RELAXATION): Define.
* config/loongarch/loongarch.cc (loongarch_legitimize_tls_address):
Added TLS Le Relax support.
(loongarch_print_operand_reloc): Add the output string of TLS Le Relax.
* config/loongarch/loongarch.md (@add_tls_le_relax<mode>): New template.
* configure: Regenerate.
* configure.ac: Check if binutils supports TLS le relax.

gcc/testsuite/ChangeLog:

* lib/target-supports.exp: Add a function to check whether binutil supports
TLS Le Relax.
* gcc.target/loongarch/tls-le-relax.c: New test.

gcc/config.in
gcc/config/loongarch/loongarch-opts.h
gcc/config/loongarch/loongarch.cc
gcc/config/loongarch/loongarch.md
gcc/configure
gcc/configure.ac
gcc/testsuite/gcc.target/loongarch/tls-le-relax.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp

index fa40825d6d0f9fe237d4485923c626e7935889cd..b499bbfdda7522ac349c1b15e6e5d20d45147dca 100644 (file)
 #endif
 
 
+/* Define if your assembler supports tls le relocation. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_TLS_LE_RELAXATION
+#endif
+
+
 /* Define if your assembler supports vl/vst/vlm/vstm with an optional
    alignment hint argument. */
 #ifndef USED_FOR_TARGET
index d091359300a09dd6309e2da7348f2c49e349fadb..e46f79af3907d019df08c3c16af8c0ef05850cae 100644 (file)
@@ -114,4 +114,8 @@ struct loongarch_flags {
 #define HAVE_AS_TLS 0
 #endif
 
+#ifndef HAVE_AS_TLS_LE_RELAXATION
+#define HAVE_AS_TLS_LE_RELAXATION 0
+#endif
+
 #endif /* LOONGARCH_OPTS_H */
index 9f2b3e98bf0ed54c0dcdd52dcba17a8c0bef08e1..db83232884f38788b10ae58a57b3c67c8b0c924a 100644 (file)
@@ -2997,7 +2997,29 @@ loongarch_legitimize_tls_address (rtx loc)
 
     case TLS_MODEL_LOCAL_EXEC:
        {
-         /* la.tls.le; tp-relative add.  */
+         /* la.tls.le; tp-relative add.
+
+            normal:
+             lu12i.w $rd, %le_hi20(sym)
+             ori $rd, $rd, %le_lo12(sym)
+             add.{w/d} $rd, $rd, $tp
+             (st.{w/d}/ld.{w/d} $rs, $rd, 0)
+
+            tls le relax:
+             lu12i.w $rd, %le_hi20_r(sym)
+             add.{w/d} $rd,$rd,$tp
+             addi.{w/d} $rd,$rd,%le_lo12_r(sym)
+             (st.{w/d}/ld.{w/d} $rs, $rd, 0)
+
+            extreme (When the code model is set to extreme, the TLS le Relax
+            instruction sequence is not generated):
+             lu12i.w $rd, %le_hi20(sym)
+             ori $rd, $rd, %le_lo12(sym)
+             lu32i.d $rd, %le64_lo20(sym)
+             lu52i.d $rd, $rd, %le64_hi12(sym)
+             add.d $rd, $rd, $tp
+             (st.{w/d}/ld.{w/d} $rs, $rd, 0)  */
+
          tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
          tmp1 = gen_reg_rtx (Pmode);
          dest = gen_reg_rtx (Pmode);
@@ -3008,7 +3030,20 @@ loongarch_legitimize_tls_address (rtx loc)
              tmp3 = gen_reg_rtx (Pmode);
              rtx high = gen_rtx_HIGH (Pmode, copy_rtx (tmp2));
              high = loongarch_force_temporary (tmp3, high);
-             emit_insn (gen_ori_l_lo12 (Pmode, tmp1, high, tmp2));
+
+             /* The assembler does not implement tls le relax support when the
+                code model is extreme, so when the code model is extreme, the
+                old symbol address acquisition method is still used.  */
+             if (HAVE_AS_TLS_LE_RELAXATION && !TARGET_CMODEL_EXTREME)
+               {
+                 emit_insn (gen_add_tls_le_relax (Pmode, dest, high,
+                                                  tp, loc));
+                 loongarch_emit_move (dest,
+                                      gen_rtx_LO_SUM (Pmode, dest, tmp2));
+                 return dest;
+               }
+             else
+               emit_insn (gen_ori_l_lo12 (Pmode, tmp1, high, tmp2));
 
              if (TARGET_CMODEL_EXTREME)
                {
@@ -5940,7 +5975,12 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part,
            gcc_unreachable ();
        }
       else
-       reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
+       {
+         if (HAVE_AS_TLS_LE_RELAXATION && !TARGET_CMODEL_EXTREME)
+           reloc = hi_reloc ? "%le_hi20_r" : "%le_lo12_r";
+         else
+           reloc = hi_reloc ? "%le_hi20" : "%le_lo12";
+       }
       break;
 
     case SYMBOL_TLSGD:
index 47c1c5603c1c5f9d0100581ae9c7ea10d546e5ca..4dd578bc5e455a085d893b786ce6ce7583886241 100644 (file)
@@ -73,6 +73,7 @@
   UNSPEC_LOAD_FROM_GOT
   UNSPEC_PCALAU12I
   UNSPEC_PCALAU12I_GR
+  UNSPEC_ADD_TLS_LE_RELAX
   UNSPEC_ORI_L_LO12
   UNSPEC_LUI_L_HI20
   UNSPEC_LUI_H_LO20
   "pcalau12i\t%0,%%pc_hi20(%1)"
   [(set_attr "type" "move")])
 
+(define_insn "@add_tls_le_relax<mode>"
+  [(set (match_operand:P 0 "register_operand" "=r")
+       (unspec:P [(match_operand:P 1 "register_operand" "r")
+                  (match_operand:P 2 "register_operand" "r")
+                  (match_operand:P 3 "symbolic_operand")]
+         UNSPEC_ADD_TLS_LE_RELAX))]
+  "HAVE_AS_TLS_LE_RELAXATION"
+  "add.<d>\t%0,%1,%2,%%le_add_r(%3)"
+  [(set_attr "type" "move")]
+)
+
 (define_insn "@ori_l_lo12<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
        (unspec:P [(match_operand:P 1 "register_operand" "r")
index de72cb1e1fe5e8f0f7627396b550f9ab19f4493c..996046f51982c396e03e138a4191ce6a25f995c6 100755 (executable)
@@ -31050,6 +31050,37 @@ if test $gcc_cv_as_loongarch_cond_branch_relax = yes; then
 
 $as_echo "#define HAVE_AS_COND_BRANCH_RELAXATION 1" >>confdefs.h
 
+fi
+
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for tls le relaxation support" >&5
+$as_echo_n "checking assembler for tls le relaxation support... " >&6; }
+if ${gcc_cv_as_loongarch_tls_le_relaxation_support+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  gcc_cv_as_loongarch_tls_le_relaxation_support=no
+  if test x$gcc_cv_as != x; then
+    $as_echo 'lu12i.w $t0,%le_hi20_r(a)' > conftest.s
+    if { ac_try='$gcc_cv_as $gcc_cv_as_flags  -o conftest.o conftest.s >&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+    then
+       gcc_cv_as_loongarch_tls_le_relaxation_support=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_loongarch_tls_le_relaxation_support" >&5
+$as_echo "$gcc_cv_as_loongarch_tls_le_relaxation_support" >&6; }
+if test $gcc_cv_as_loongarch_tls_le_relaxation_support = yes; then
+
+$as_echo "#define HAVE_AS_TLS_LE_RELAXATION 1" >>confdefs.h
+
 fi
 
     ;;
index 21ba631482f0eb6ee1c32153ab9fe0a964c616de..784be5bed5969d8ec91ed3850a3a47960bf221c8 100644 (file)
@@ -5447,6 +5447,11 @@ x:
        beq $a0,$a1,a],,
       [AC_DEFINE(HAVE_AS_COND_BRANCH_RELAXATION, 1,
                [Define if your assembler supports conditional branch relaxation.])])
+    gcc_GAS_CHECK_FEATURE([tls le relaxation support],
+      gcc_cv_as_loongarch_tls_le_relaxation_support,,
+      [lu12i.w $t0,%le_hi20_r(a)],,
+      [AC_DEFINE(HAVE_AS_TLS_LE_RELAXATION, 1,
+         [Define if your assembler supports tls le relocation.])])
     ;;
     s390*-*-*)
     gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
diff --git a/gcc/testsuite/gcc.target/loongarch/tls-le-relax.c b/gcc/testsuite/gcc.target/loongarch/tls-le-relax.c
new file mode 100644 (file)
index 0000000..a9a404f
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=normal -mexplicit-relocs" } */
+/* { dg-final { scan-assembler "%le_add_r" { target tls_le_relax } } } */
+
+__attribute__ ((tls_model ("local-exec"))) __thread int a;
+
+void
+test (void)
+{
+  a = 10;
+}
+
index 167e630f5a5fbe07407a26468da5c33ecaeeff4b..3aa761d3e09054b23f560107b3606b49117db1dd 100644 (file)
@@ -13249,6 +13249,18 @@ proc check_effective_target_loongarch_call36_support { } {
   } ""]
 }
 
+# Returns 1 if binutils supports TLS le Relax, 0 otherwise.
+proc check_effective_target_tls_le_relax { } {
+  if [check_effective_target_tls_native] {
+    return [check_no_compiler_messages loongarch_tls_le_relax object {
+        /* Assembly code */
+       lu12i.w $r12, %le_hi20_r(a)
+    }]
+  }
+
+  return 0;
+}
+
 # Appends necessary Python flags to extra-tool-flags if Python.h is supported.
 # Otherwise, modifies dg-do-what.
 proc dg-require-python-h { args } {