LoongArch: Added TLS Le Relax support.

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.
This commit is contained in:
Lulu Cheng 2023-12-12 16:32:31 +08:00
parent d3d6a96d45
commit 3c20e6263a
8 changed files with 125 additions and 3 deletions

View file

@ -793,6 +793,12 @@
#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

View 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 */

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

View 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
@ -2503,6 +2504,17 @@
"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")

31
gcc/configure vendored
View file

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

View 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],

View file

@ -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;
}

View 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 } {