diff mbox series

[v5] LoongArch: Add support for TLS descriptors

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

Commit Message

mengqinggang March 19, 2024, 1:54 a.m. UTC
Add support for TLS descriptors on normal code model and extreme code model.

Normal code model instruction sequence:
  -mno-explicit-relocs:
    la.tls.desc	$r4, s
    add.d	$r12, $r4, $r2
  -mexplicit-relocs:
    pcalau12i	$r4,%desc_pc_hi20(s)
    addi.d	$r4,$r4,%desc_pc_lo12(s)
    ld.d	$r1,$r4,%desc_ld(s)
    jirl	$r1,$r1,%desc_call(s)
    add.d	$r12, $r4, $r2

Extreme code model instruction sequence:
  -mno-explicit-relocs:
    la.tls.desc	$r4, $r12, s
    add.d	$r12, $r4, $r2
  -mexplicit-relocs:
    pcalau12i	$r4,%desc_pc_hi20(s)
    addi.d	$r12,$r0,%desc_pc_lo12(s)
    lu32i.d	$r12,%desc64_pc_lo20(s)
    lu52i.d	$r12,$r12,%desc64_pc_hi12(s)
    add.d	$r4,$r4,$r12
    ld.d	$r1,$r4,%desc_ld(s)
    jirl	$r1,$r1,%desc_call(s)
    add.d	$r12, $r4, $r2

The default is still traditional TLS model, but can be configured with
--with-tls={trad,desc}. The default can change to TLS descriptors once
libc and LLVM support this.

gcc/ChangeLog:

	* config.gcc: Add --with-tls option to change TLS flavor.
	* config/loongarch/genopts/loongarch.opt.in: Add -mtls-dialect to
	configure TLS flavor.
	* config/loongarch/loongarch-def.h (struct loongarch_target): Add
	tls_dialect.
	* config/loongarch/loongarch-driver.cc (la_driver_init): Add tls
	flavor.
	* config/loongarch/loongarch-opts.cc (loongarch_init_target): Add
	tls_dialect.
	(loongarch_config_target): Ditto.
	(loongarch_update_gcc_opt_status): Ditto.
	* config/loongarch/loongarch-opts.h (loongarch_init_target):Ditto.
	(TARGET_TLS_DESC): New define.
	* config/loongarch/loongarch.cc (loongarch_symbol_insns): Add TLS DESC
	instructions sequence length.
	(loongarch_legitimize_tls_address): New TLS DESC instruction sequence.
	(loongarch_option_override_internal): Add la_opt_tls_dialect.
	(loongarch_option_restore): Add la_target.tls_dialect.
	* config/loongarch/loongarch.md (@got_load_tls_desc<mode>): Normal
	code model for TLS DESC.
	(got_load_tls_desc_off64): Extreme code model for TLS DESC.
	* config/loongarch/loongarch.opt: Regenerated.

gcc/testsuite/ChangeLog:

	* gcc.target/loongarch/cmodel-extreme-1.c: Add -mtls-dialect=trad.
	* gcc.target/loongarch/cmodel-extreme-2.c: Ditto.
	* gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c: Ditto.
	* gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c:
	Ditto.
	* gcc.target/loongarch/func-call-medium-1.c: Ditto.
	* gcc.target/loongarch/func-call-medium-2.c: Ditto.
	* gcc.target/loongarch/func-call-medium-3.c: Ditto.
	* gcc.target/loongarch/func-call-medium-4.c: Ditto.
	* gcc.target/loongarch/tls-extreme-macro.c: Ditto.
	* gcc.target/loongarch/tls-gd-noplt.c: Ditto.
	* gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c: New test.
	* gcc.target/loongarch/explicit-relocs-auto-tls-desc.c: New test.
	* gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c: New test.
	* gcc.target/loongarch/explicit-relocs-tls-desc.c: New test.

Co-authored-by: Lulu Cheng <chenglulu@loongson.cn>
Co-authored-by: Xi Ruoyao <xry111@xry111.site>
---
Changes v4 -> v5:
- Use (reg:P 4) instead of match_operand in got_load_tls_desc and
  got_load_tls_desc_off64.
- Change instruction sequence to prevent additional white spaces in the output asm
  before tabs.

Changes v3 -> v4:
- Add TLS descriptors test cases.

Changes v2 -> v3:
- Set default to traditional TLS model.
- Add support for -mexplicit-relocs and extreme code model.

Changes v1 -> v2:
- Clobber fcc0-fcc7 registers in got_load_tls_desc template.
- Support --with-tls in configure.

v4 link: https://sourceware.org/pipermail/gcc-patches/2024-March/647597.html
v3 link: https://sourceware.org/pipermail/gcc-patches/2024-March/647578.html
v2 link: https://sourceware.org/pipermail/gcc-patches/2024-February/646817.html
v1 link: https://sourceware.org/pipermail/gcc-patches/2023-December/638907.html

 gcc/config.gcc                                | 19 +++++-
 gcc/config/loongarch/genopts/loongarch.opt.in | 14 ++++
 gcc/config/loongarch/loongarch-def.h          |  7 ++
 gcc/config/loongarch/loongarch-driver.cc      |  2 +-
 gcc/config/loongarch/loongarch-opts.cc        | 12 +++-
 gcc/config/loongarch/loongarch-opts.h         |  2 +
 gcc/config/loongarch/loongarch.cc             | 47 +++++++++----
 gcc/config/loongarch/loongarch.md             | 68 +++++++++++++++++++
 gcc/config/loongarch/loongarch.opt            | 14 ++++
 .../gcc.target/loongarch/cmodel-extreme-1.c   |  2 +-
 .../gcc.target/loongarch/cmodel-extreme-2.c   |  2 +-
 .../explicit-relocs-auto-extreme-tls-desc.c   | 10 +++
 .../loongarch/explicit-relocs-auto-tls-desc.c | 10 +++
 .../explicit-relocs-auto-tls-ld-gd.c          |  2 +-
 .../explicit-relocs-extreme-tls-desc.c        | 16 +++++
 ...icit-relocs-medium-call36-auto-tls-ld-gd.c |  2 +-
 .../loongarch/explicit-relocs-tls-desc.c      | 13 ++++
 .../gcc.target/loongarch/func-call-medium-1.c |  2 +-
 .../gcc.target/loongarch/func-call-medium-2.c |  2 +-
 .../gcc.target/loongarch/func-call-medium-3.c |  2 +-
 .../gcc.target/loongarch/func-call-medium-4.c |  2 +-
 .../gcc.target/loongarch/tls-extreme-macro.c  |  2 +-
 .../gcc.target/loongarch/tls-gd-noplt.c       |  2 +-
 23 files changed, 228 insertions(+), 26 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c
 create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c
 create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c
 create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c

Comments

Xi Ruoyao April 1, 2024, 1:51 p.m. UTC | #1
Is this patch targeting GCC 14 or 15?  If 14 I guess we'd commit now...

Generally we don't add features in stage 4, but if we keep trad as the
default I think it'd be OK.  And RISC-V guys plan to push their TLS desc
implementation this week too.

On Tue, 2024-03-19 at 09:54 +0800, mengqinggang wrote:
> Add support for TLS descriptors on normal code model and extreme code model.
> 
> Normal code model instruction sequence:
>   -mno-explicit-relocs:
>     la.tls.desc	$r4, s
>     add.d	$r12, $r4, $r2
>   -mexplicit-relocs:
>     pcalau12i	$r4,%desc_pc_hi20(s)
>     addi.d	$r4,$r4,%desc_pc_lo12(s)
>     ld.d	$r1,$r4,%desc_ld(s)
>     jirl	$r1,$r1,%desc_call(s)
>     add.d	$r12, $r4, $r2
> 
> Extreme code model instruction sequence:
>   -mno-explicit-relocs:
>     la.tls.desc	$r4, $r12, s
>     add.d	$r12, $r4, $r2
>   -mexplicit-relocs:
>     pcalau12i	$r4,%desc_pc_hi20(s)
>     addi.d	$r12,$r0,%desc_pc_lo12(s)
>     lu32i.d	$r12,%desc64_pc_lo20(s)
>     lu52i.d	$r12,$r12,%desc64_pc_hi12(s)
>     add.d	$r4,$r4,$r12
>     ld.d	$r1,$r4,%desc_ld(s)
>     jirl	$r1,$r1,%desc_call(s)
>     add.d	$r12, $r4, $r2
> 
> The default is still traditional TLS model, but can be configured with
> --with-tls={trad,desc}. The default can change to TLS descriptors once
> libc and LLVM support this.
> 
> gcc/ChangeLog:
> 
> 	* config.gcc: Add --with-tls option to change TLS flavor.
> 	* config/loongarch/genopts/loongarch.opt.in: Add -mtls-dialect to
> 	configure TLS flavor.
> 	* config/loongarch/loongarch-def.h (struct loongarch_target): Add
> 	tls_dialect.
> 	* config/loongarch/loongarch-driver.cc (la_driver_init): Add tls
> 	flavor.
> 	* config/loongarch/loongarch-opts.cc (loongarch_init_target): Add
> 	tls_dialect.
> 	(loongarch_config_target): Ditto.
> 	(loongarch_update_gcc_opt_status): Ditto.
> 	* config/loongarch/loongarch-opts.h (loongarch_init_target):Ditto.
> 	(TARGET_TLS_DESC): New define.
> 	* config/loongarch/loongarch.cc (loongarch_symbol_insns): Add TLS DESC
> 	instructions sequence length.
> 	(loongarch_legitimize_tls_address): New TLS DESC instruction sequence.
> 	(loongarch_option_override_internal): Add la_opt_tls_dialect.
> 	(loongarch_option_restore): Add la_target.tls_dialect.
> 	* config/loongarch/loongarch.md (@got_load_tls_desc<mode>): Normal
> 	code model for TLS DESC.
> 	(got_load_tls_desc_off64): Extreme code model for TLS DESC.
> 	* config/loongarch/loongarch.opt: Regenerated.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/loongarch/cmodel-extreme-1.c: Add -mtls-dialect=trad.
> 	* gcc.target/loongarch/cmodel-extreme-2.c: Ditto.
> 	* gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c: Ditto.
> 	* gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c:
> 	Ditto.
> 	* gcc.target/loongarch/func-call-medium-1.c: Ditto.
> 	* gcc.target/loongarch/func-call-medium-2.c: Ditto.
> 	* gcc.target/loongarch/func-call-medium-3.c: Ditto.
> 	* gcc.target/loongarch/func-call-medium-4.c: Ditto.
> 	* gcc.target/loongarch/tls-extreme-macro.c: Ditto.
> 	* gcc.target/loongarch/tls-gd-noplt.c: Ditto.
> 	* gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c: New test.
> 	* gcc.target/loongarch/explicit-relocs-auto-tls-desc.c: New test.
> 	* gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c: New test.
> 	* gcc.target/loongarch/explicit-relocs-tls-desc.c: New test.
> 
> Co-authored-by: Lulu Cheng <chenglulu@loongson.cn>
> Co-authored-by: Xi Ruoyao <xry111@xry111.site>
Lulu Cheng April 2, 2024, 1:09 a.m. UTC | #2
在 2024/4/1 下午9:51, Xi Ruoyao 写道:
> Is this patch targeting GCC 14 or 15?  If 14 I guess we'd commit now...
>
> Generally we don't add features in stage 4, but if we keep trad as the
> default I think it'd be OK.  And RISC-V guys plan to push their TLS desc
> implementation this week too.

I've rebase the code to the latest commit, and if the test is okay I'll 
bring it up right away.

Thanks!:-)

>
> On Tue, 2024-03-19 at 09:54 +0800, mengqinggang wrote:
>> Add support for TLS descriptors on normal code model and extreme code model.
>>
>> Normal code model instruction sequence:
>>    -mno-explicit-relocs:
>>      la.tls.desc	$r4, s
>>      add.d	$r12, $r4, $r2
>>    -mexplicit-relocs:
>>      pcalau12i	$r4,%desc_pc_hi20(s)
>>      addi.d	$r4,$r4,%desc_pc_lo12(s)
>>      ld.d	$r1,$r4,%desc_ld(s)
>>      jirl	$r1,$r1,%desc_call(s)
>>      add.d	$r12, $r4, $r2
>>
>> Extreme code model instruction sequence:
>>    -mno-explicit-relocs:
>>      la.tls.desc	$r4, $r12, s
>>      add.d	$r12, $r4, $r2
>>    -mexplicit-relocs:
>>      pcalau12i	$r4,%desc_pc_hi20(s)
>>      addi.d	$r12,$r0,%desc_pc_lo12(s)
>>      lu32i.d	$r12,%desc64_pc_lo20(s)
>>      lu52i.d	$r12,$r12,%desc64_pc_hi12(s)
>>      add.d	$r4,$r4,$r12
>>      ld.d	$r1,$r4,%desc_ld(s)
>>      jirl	$r1,$r1,%desc_call(s)
>>      add.d	$r12, $r4, $r2
>>
>> The default is still traditional TLS model, but can be configured with
>> --with-tls={trad,desc}. The default can change to TLS descriptors once
>> libc and LLVM support this.
>>
>> gcc/ChangeLog:
>>
>> 	* config.gcc: Add --with-tls option to change TLS flavor.
>> 	* config/loongarch/genopts/loongarch.opt.in: Add -mtls-dialect to
>> 	configure TLS flavor.
>> 	* config/loongarch/loongarch-def.h (struct loongarch_target): Add
>> 	tls_dialect.
>> 	* config/loongarch/loongarch-driver.cc (la_driver_init): Add tls
>> 	flavor.
>> 	* config/loongarch/loongarch-opts.cc (loongarch_init_target): Add
>> 	tls_dialect.
>> 	(loongarch_config_target): Ditto.
>> 	(loongarch_update_gcc_opt_status): Ditto.
>> 	* config/loongarch/loongarch-opts.h (loongarch_init_target):Ditto.
>> 	(TARGET_TLS_DESC): New define.
>> 	* config/loongarch/loongarch.cc (loongarch_symbol_insns): Add TLS DESC
>> 	instructions sequence length.
>> 	(loongarch_legitimize_tls_address): New TLS DESC instruction sequence.
>> 	(loongarch_option_override_internal): Add la_opt_tls_dialect.
>> 	(loongarch_option_restore): Add la_target.tls_dialect.
>> 	* config/loongarch/loongarch.md (@got_load_tls_desc<mode>): Normal
>> 	code model for TLS DESC.
>> 	(got_load_tls_desc_off64): Extreme code model for TLS DESC.
>> 	* config/loongarch/loongarch.opt: Regenerated.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 	* gcc.target/loongarch/cmodel-extreme-1.c: Add -mtls-dialect=trad.
>> 	* gcc.target/loongarch/cmodel-extreme-2.c: Ditto.
>> 	* gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c: Ditto.
>> 	* gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c:
>> 	Ditto.
>> 	* gcc.target/loongarch/func-call-medium-1.c: Ditto.
>> 	* gcc.target/loongarch/func-call-medium-2.c: Ditto.
>> 	* gcc.target/loongarch/func-call-medium-3.c: Ditto.
>> 	* gcc.target/loongarch/func-call-medium-4.c: Ditto.
>> 	* gcc.target/loongarch/tls-extreme-macro.c: Ditto.
>> 	* gcc.target/loongarch/tls-gd-noplt.c: Ditto.
>> 	* gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c: New test.
>> 	* gcc.target/loongarch/explicit-relocs-auto-tls-desc.c: New test.
>> 	* gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c: New test.
>> 	* gcc.target/loongarch/explicit-relocs-tls-desc.c: New test.
>>
>> Co-authored-by: Lulu Cheng <chenglulu@loongson.cn>
>> Co-authored-by: Xi Ruoyao <xry111@xry111.site>
Lulu Cheng April 2, 2024, 6:14 a.m. UTC | #3
Pushed to r14-9742.

Rebase to the latest, and modify invoke.texi to add a description of the 
TLS DESC compilation option.

在 2024/3/19 上午9:54, mengqinggang 写道:
> Add support for TLS descriptors on normal code model and extreme code model.
>
> Normal code model instruction sequence:
>    -mno-explicit-relocs:
>      la.tls.desc	$r4, s
>      add.d	$r12, $r4, $r2
>    -mexplicit-relocs:
>      pcalau12i	$r4,%desc_pc_hi20(s)
>      addi.d	$r4,$r4,%desc_pc_lo12(s)
>      ld.d	$r1,$r4,%desc_ld(s)
>      jirl	$r1,$r1,%desc_call(s)
>      add.d	$r12, $r4, $r2
>
> Extreme code model instruction sequence:
>    -mno-explicit-relocs:
>      la.tls.desc	$r4, $r12, s
>      add.d	$r12, $r4, $r2
>    -mexplicit-relocs:
>      pcalau12i	$r4,%desc_pc_hi20(s)
>      addi.d	$r12,$r0,%desc_pc_lo12(s)
>      lu32i.d	$r12,%desc64_pc_lo20(s)
>      lu52i.d	$r12,$r12,%desc64_pc_hi12(s)
>      add.d	$r4,$r4,$r12
>      ld.d	$r1,$r4,%desc_ld(s)
>      jirl	$r1,$r1,%desc_call(s)
>      add.d	$r12, $r4, $r2
>
> The default is still traditional TLS model, but can be configured with
> --with-tls={trad,desc}. The default can change to TLS descriptors once
> libc and LLVM support this.
>
> gcc/ChangeLog:
>
> 	* config.gcc: Add --with-tls option to change TLS flavor.
> 	* config/loongarch/genopts/loongarch.opt.in: Add -mtls-dialect to
> 	configure TLS flavor.
> 	* config/loongarch/loongarch-def.h (struct loongarch_target): Add
> 	tls_dialect.
> 	* config/loongarch/loongarch-driver.cc (la_driver_init): Add tls
> 	flavor.
> 	* config/loongarch/loongarch-opts.cc (loongarch_init_target): Add
> 	tls_dialect.
> 	(loongarch_config_target): Ditto.
> 	(loongarch_update_gcc_opt_status): Ditto.
> 	* config/loongarch/loongarch-opts.h (loongarch_init_target):Ditto.
> 	(TARGET_TLS_DESC): New define.
> 	* config/loongarch/loongarch.cc (loongarch_symbol_insns): Add TLS DESC
> 	instructions sequence length.
> 	(loongarch_legitimize_tls_address): New TLS DESC instruction sequence.
> 	(loongarch_option_override_internal): Add la_opt_tls_dialect.
> 	(loongarch_option_restore): Add la_target.tls_dialect.
> 	* config/loongarch/loongarch.md (@got_load_tls_desc<mode>): Normal
> 	code model for TLS DESC.
> 	(got_load_tls_desc_off64): Extreme code model for TLS DESC.
> 	* config/loongarch/loongarch.opt: Regenerated.
>
> gcc/testsuite/ChangeLog:
>
> 	* gcc.target/loongarch/cmodel-extreme-1.c: Add -mtls-dialect=trad.
> 	* gcc.target/loongarch/cmodel-extreme-2.c: Ditto.
> 	* gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c: Ditto.
> 	* gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c:
> 	Ditto.
> 	* gcc.target/loongarch/func-call-medium-1.c: Ditto.
> 	* gcc.target/loongarch/func-call-medium-2.c: Ditto.
> 	* gcc.target/loongarch/func-call-medium-3.c: Ditto.
> 	* gcc.target/loongarch/func-call-medium-4.c: Ditto.
> 	* gcc.target/loongarch/tls-extreme-macro.c: Ditto.
> 	* gcc.target/loongarch/tls-gd-noplt.c: Ditto.
> 	* gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c: New test.
> 	* gcc.target/loongarch/explicit-relocs-auto-tls-desc.c: New test.
> 	* gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c: New test.
> 	* gcc.target/loongarch/explicit-relocs-tls-desc.c: New test.
>
> Co-authored-by: Lulu Cheng <chenglulu@loongson.cn>
> Co-authored-by: Xi Ruoyao <xry111@xry111.site>
> ---
> Changes v4 -> v5:
> - Use (reg:P 4) instead of match_operand in got_load_tls_desc and
>    got_load_tls_desc_off64.
> - Change instruction sequence to prevent additional white spaces in the output asm
>    before tabs.
>
> Changes v3 -> v4:
> - Add TLS descriptors test cases.
>
> Changes v2 -> v3:
> - Set default to traditional TLS model.
> - Add support for -mexplicit-relocs and extreme code model.
>
> Changes v1 -> v2:
> - Clobber fcc0-fcc7 registers in got_load_tls_desc template.
> - Support --with-tls in configure.
>
> v4 link: https://sourceware.org/pipermail/gcc-patches/2024-March/647597.html
> v3 link: https://sourceware.org/pipermail/gcc-patches/2024-March/647578.html
> v2 link: https://sourceware.org/pipermail/gcc-patches/2024-February/646817.html
> v1 link: https://sourceware.org/pipermail/gcc-patches/2023-December/638907.html
>
>   gcc/config.gcc                                | 19 +++++-
>   gcc/config/loongarch/genopts/loongarch.opt.in | 14 ++++
>   gcc/config/loongarch/loongarch-def.h          |  7 ++
>   gcc/config/loongarch/loongarch-driver.cc      |  2 +-
>   gcc/config/loongarch/loongarch-opts.cc        | 12 +++-
>   gcc/config/loongarch/loongarch-opts.h         |  2 +
>   gcc/config/loongarch/loongarch.cc             | 47 +++++++++----
>   gcc/config/loongarch/loongarch.md             | 68 +++++++++++++++++++
>   gcc/config/loongarch/loongarch.opt            | 14 ++++
>   .../gcc.target/loongarch/cmodel-extreme-1.c   |  2 +-
>   .../gcc.target/loongarch/cmodel-extreme-2.c   |  2 +-
>   .../explicit-relocs-auto-extreme-tls-desc.c   | 10 +++
>   .../loongarch/explicit-relocs-auto-tls-desc.c | 10 +++
>   .../explicit-relocs-auto-tls-ld-gd.c          |  2 +-
>   .../explicit-relocs-extreme-tls-desc.c        | 16 +++++
>   ...icit-relocs-medium-call36-auto-tls-ld-gd.c |  2 +-
>   .../loongarch/explicit-relocs-tls-desc.c      | 13 ++++
>   .../gcc.target/loongarch/func-call-medium-1.c |  2 +-
>   .../gcc.target/loongarch/func-call-medium-2.c |  2 +-
>   .../gcc.target/loongarch/func-call-medium-3.c |  2 +-
>   .../gcc.target/loongarch/func-call-medium-4.c |  2 +-
>   .../gcc.target/loongarch/tls-extreme-macro.c  |  2 +-
>   .../gcc.target/loongarch/tls-gd-noplt.c       |  2 +-
>   23 files changed, 228 insertions(+), 26 deletions(-)
>   create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c
>   create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c
>   create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c
>   create mode 100644 gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c
>
> diff --git a/gcc/config.gcc b/gcc/config.gcc
> index 624e0dae191..baebafdbf5d 100644
> --- a/gcc/config.gcc
> +++ b/gcc/config.gcc
> @@ -4991,7 +4991,7 @@ case "${target}" in
>   		;;
>   
>   	loongarch*-*)
> -		supported_defaults="abi arch tune fpu simd multilib-default strict-align-lib"
> +		supported_defaults="abi arch tune fpu simd multilib-default strict-align-lib tls"
>   
>   		# Local variables
>   		unset \
> @@ -5249,6 +5249,18 @@ case "${target}" in
>   			with_multilib_list="${abi_base}/${abi_ext}"
>   		fi
>   
> +		# Handle --with-tls.
> +		case "$with_tls" in
> +		"" \
> +		| trad | desc)
> +		    # OK
> +		    ;;
> +		*)
> +		    echo "Unknown TLS method used in --with-tls=$with_tls" 1>&2
> +		    exit 1
> +		    ;;
> +		esac
> +
>   		# Check if the configured default ABI combination is included in
>   		# ${with_multilib_list}.
>   		loongarch_multilib_list_sane=no
> @@ -5914,6 +5926,11 @@ case ${target} in
>   		lasx)    tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_SIMD_LASX" ;;
>   		esac
>   
> +		case ${with_tls} in
> +		"" | trad)	tm_defines="$tm_defines DEFAULT_TLS_TYPE=TLS_TRADITIONAL" ;;
> +		desc)		tm_defines="$tm_defines DEFAULT_TLS_TYPE=TLS_DESCRIPTORS" ;;
> +		esac
> +
>   		tmake_file="loongarch/t-loongarch $tmake_file"
>   		;;
>   
> diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in
> index 02f918053f5..7de107c3e3d 100644
> --- a/gcc/config/loongarch/genopts/loongarch.opt.in
> +++ b/gcc/config/loongarch/genopts/loongarch.opt.in
> @@ -262,3 +262,17 @@ default value is 4.
>   ; CPUCFG independently, so we use bit flags to specify them.
>   TargetVariable
>   HOST_WIDE_INT la_isa_evolution = 0
> +
> +Enum
> +Name(tls_type) Type(int)
> +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(la_opt_tls_dialect) Init(M_OPT_UNSET) Save
> +Specify TLS dialect.
> diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h
> index 2dbf006d013..48d60e2b456 100644
> --- a/gcc/config/loongarch/loongarch-def.h
> +++ b/gcc/config/loongarch/loongarch-def.h
> @@ -175,6 +175,7 @@ struct loongarch_target
>     int cpu_arch;	    /* CPU_ */
>     int cpu_tune;	    /* same */
>     int cmodel;	    /* CMODEL_ */
> +  int tls_dialect;  /* TLS_ */
>   };
>   
>   /* CPU model */
> @@ -188,6 +189,12 @@ enum {
>     N_TUNE_TYPES	    = 5
>   };
>   
> +/* TLS types.  */
> +enum {
> +  TLS_TRADITIONAL = 0,
> +  TLS_DESCRIPTORS = 1
> +};
> +
>   /* CPU model properties */
>   extern loongarch_def_array<const char *, N_ARCH_TYPES>
>     loongarch_cpu_strings;
> diff --git a/gcc/config/loongarch/loongarch-driver.cc b/gcc/config/loongarch/loongarch-driver.cc
> index 62658f531ad..8c4ed34698b 100644
> --- a/gcc/config/loongarch/loongarch-driver.cc
> +++ b/gcc/config/loongarch/loongarch-driver.cc
> @@ -45,7 +45,7 @@ la_driver_init (int argc ATTRIBUTE_UNUSED, const char **argv ATTRIBUTE_UNUSED)
>     /* Initialize all fields of la_target.  */
>     loongarch_init_target (&la_target, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET,
>   			 M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET,
> -			 0, 0);
> +			 M_OPT_UNSET, 0, 0);
>     return "";
>   }
>   
> diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
> index 7eeac43ed2f..ec929aa7f29 100644
> --- a/gcc/config/loongarch/loongarch-opts.cc
> +++ b/gcc/config/loongarch/loongarch-opts.cc
> @@ -139,6 +139,7 @@ void
>   loongarch_init_target (struct loongarch_target *target,
>   		       int cpu_arch, int cpu_tune, int fpu, int simd,
>   		       int abi_base, int abi_ext, int cmodel,
> +		       int tls_dialect,
>   		       HOST_WIDE_INT isa_evolution,
>   		       HOST_WIDE_INT isa_evolution_set)
>   {
> @@ -153,6 +154,7 @@ loongarch_init_target (struct loongarch_target *target,
>     target->abi.base = abi_base;
>     target->abi.ext = abi_ext;
>     target->cmodel = cmodel;
> +  target->tls_dialect = tls_dialect;
>   }
>   
>   
> @@ -174,7 +176,8 @@ loongarch_config_target (struct loongarch_target *target,
>     obstack_init (&msg_obstack);
>   
>     struct {
> -    int arch, tune, fpu, simd, abi_base, abi_ext, cmodel, abi_flt;
> +    int arch, tune, fpu, simd, abi_base, abi_ext, cmodel,
> +	tls_dialect, abi_flt;
>     } constrained = {
>         M_OPT_ABSENT (target->cpu_arch)	  ? 0 : 1,
>         M_OPT_ABSENT (target->cpu_tune)	  ? 0 : 1,
> @@ -183,6 +186,7 @@ loongarch_config_target (struct loongarch_target *target,
>         M_OPT_ABSENT (target->abi.base)	  ? 0 : 1,
>         M_OPT_ABSENT (target->abi.ext)	  ? 0 : 1,
>         M_OPT_ABSENT (target->cmodel)	  ? 0 : 1,
> +      M_OPT_ABSENT (target->tls_dialect)  ? 0 : 1,
>         M_OPT_ABSENT (target->abi.base)	  ? 0 : 1,
>     };
>   
> @@ -551,6 +555,9 @@ fallback:
>         gcc_unreachable ();
>       }
>   
> +  t.tls_dialect = constrained.tls_dialect ? target->tls_dialect
> +	  : DEFAULT_TLS_TYPE;
> +
>     /* Cleanup and return.  */
>     obstack_free (&msg_obstack, NULL);
>     *target = t;
> @@ -786,6 +793,9 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target,
>     /* status of -mcmodel */
>     opts->x_la_opt_cmodel = target->cmodel;
>   
> +  /* status of -mtls-dialect */
> +  opts->x_la_opt_tls_dialect = target->tls_dialect;
> +
>     /* status of -mfpu */
>     opts->x_la_opt_fpu = target->isa.fpu;
>   
> diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h
> index 586e67e65ee..88e23fcee4b 100644
> --- a/gcc/config/loongarch/loongarch-opts.h
> +++ b/gcc/config/loongarch/loongarch-opts.h
> @@ -35,6 +35,7 @@ void
>   loongarch_init_target (struct loongarch_target *target,
>   		       int cpu_arch, int cpu_tune, int fpu, int simd,
>   		       int abi_base, int abi_ext, int cmodel,
> +		       int tls_dialect,
>   		       HOST_WIDE_INT isa_evolutions,
>   		       HOST_WIDE_INT isa_evolutions_set);
>   
> @@ -83,6 +84,7 @@ struct loongarch_flags {
>   #define TARGET_ABI_LP64		  (la_target.abi.base == ABI_BASE_LP64D	\
>   				   || la_target.abi.base == ABI_BASE_LP64F \
>   				   || la_target.abi.base == ABI_BASE_LP64S)
> +#define TARGET_TLS_DESC		  (la_target.tls_dialect == TLS_DESCRIPTORS)
>   
>   #define ISA_HAS_LSX \
>     (la_target.isa.simd == ISA_EXT_SIMD_LSX \
> diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
> index 70e31bb831c..1d7fa2ca3b1 100644
> --- a/gcc/config/loongarch/loongarch.cc
> +++ b/gcc/config/loongarch/loongarch.cc
> @@ -2028,7 +2028,7 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
>   
>       case SYMBOL_TLSGD:
>       case SYMBOL_TLSLDM:
> -      return 3;
> +      return TARGET_TLS_DESC ? 4 : 3;
>   
>       case SYMBOL_PCREL64:
>         return 5;
> @@ -2930,24 +2930,43 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
>   static rtx
>   loongarch_legitimize_tls_address (rtx loc)
>   {
> -  rtx dest, tp, tmp, tmp1, tmp2, tmp3;
> +  rtx dest, tp, tmp, tmp1, tmp2, tmp3, a0;
>     enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
>     rtx_insn *insn;
>   
>     switch (model)
>       {
>       case TLS_MODEL_LOCAL_DYNAMIC:
> -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
> -      dest = gen_reg_rtx (Pmode);
> -      insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
> -      emit_libcall_block (insn, dest, tmp, loc);
> -      break;
> -
> +      if (!TARGET_TLS_DESC)
> +	{
> +	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
> +	  dest = gen_reg_rtx (Pmode);
> +	  insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
> +	  emit_libcall_block (insn, dest, tmp, loc);
> +	  break;
> +	}
> +      /* Fall through.  */
>       case TLS_MODEL_GLOBAL_DYNAMIC:
> -      tmp = gen_rtx_REG (Pmode, GP_RETURN);
> -      dest = gen_reg_rtx (Pmode);
> -      insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
> -      emit_libcall_block (insn, dest, tmp, loc);
> +      if (TARGET_TLS_DESC)
> +	{
> +	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
> +	  dest = gen_reg_rtx (Pmode);
> +	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
> +
> +	  if (TARGET_CMODEL_EXTREME)
> +	    emit_insn (gen_got_load_tls_desc_off64 (loc, gen_reg_rtx (DImode)));
> +	  else
> +	    emit_insn (gen_got_load_tls_desc (Pmode, loc));
> +
> +	  emit_insn (gen_add3_insn (dest, a0, tp));
> +	}
> +      else
> +	{
> +	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
> +	  dest = gen_reg_rtx (Pmode);
> +	  insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
> +	  emit_libcall_block (insn, dest, tmp, loc);
> +	}
>         break;
>   
>       case TLS_MODEL_INITIAL_EXEC:
> @@ -7660,7 +7679,8 @@ loongarch_option_override_internal (struct gcc_options *opts,
>     loongarch_init_target (&la_target,
>   			 la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu,
>   			 la_opt_simd, la_opt_abi_base, la_opt_abi_ext,
> -			 la_opt_cmodel, opts->x_la_isa_evolution,
> +			 la_opt_cmodel, la_opt_tls_dialect,
> +			 opts->x_la_isa_evolution,
>   			 opts_set->x_la_isa_evolution);
>   
>     /* Handle target-specific options: compute defaults/conflicts etc.  */
> @@ -7873,6 +7893,7 @@ loongarch_option_restore (struct gcc_options *,
>     la_target.isa.evolution = ptr->x_la_isa_evolution;
>   
>     la_target.cmodel = ptr->x_la_opt_cmodel;
> +  la_target.tls_dialect = ptr->x_la_opt_tls_dialect;
>   }
>   
>   /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
> diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
> index 525e1e82183..f4ff6f91311 100644
> --- a/gcc/config/loongarch/loongarch.md
> +++ b/gcc/config/loongarch/loongarch.md
> @@ -52,6 +52,8 @@ (define_c_enum "unspec" [
>   
>     ;; TLS
>     UNSPEC_TLS
> +  UNSPEC_TLS_DESC
> +  UNSPEC_TLS_DESC_OFF64
>   
>     ;; Stack tie
>     UNSPEC_TIE
> @@ -127,6 +129,15 @@ (define_constants
>      (T1_REGNUM			13)
>      (S0_REGNUM			23)
>   
> +   (FCC0_REGNUM			64)
> +   (FCC1_REGNUM			65)
> +   (FCC2_REGNUM			66)
> +   (FCC3_REGNUM			67)
> +   (FCC4_REGNUM			68)
> +   (FCC5_REGNUM			69)
> +   (FCC6_REGNUM			70)
> +   (FCC7_REGNUM			71)
> +
>      ;; Return path styles
>      (NORMAL_RETURN		0)
>      (SIBCALL_RETURN		1)
> @@ -2760,6 +2771,63 @@ (define_insn "store_word<mode>"
>   
>   ;; Thread-Local Storage
>   
> +(define_insn "@got_load_tls_desc<mode>"
> +  [(set (reg:P 4)
> +	(unspec:P
> +	    [(match_operand:P 0 "symbolic_operand" "")]
> +	    UNSPEC_TLS_DESC))
> +    (clobber (reg:SI FCC0_REGNUM))
> +    (clobber (reg:SI FCC1_REGNUM))
> +    (clobber (reg:SI FCC2_REGNUM))
> +    (clobber (reg:SI FCC3_REGNUM))
> +    (clobber (reg:SI FCC4_REGNUM))
> +    (clobber (reg:SI FCC5_REGNUM))
> +    (clobber (reg:SI FCC6_REGNUM))
> +    (clobber (reg:SI FCC7_REGNUM))
> +    (clobber (reg:SI RETURN_ADDR_REGNUM))]
> +  "TARGET_TLS_DESC"
> +{
> +  return TARGET_EXPLICIT_RELOCS
> +    ? "pcalau12i\t$r4,%%desc_pc_hi20(%0)\n\t"
> +      "addi.d\t$r4,$r4,%%desc_pc_lo12(%0)\n\t"
> +      "ld.d\t$r1,$r4,%%desc_ld(%0)\n\t"
> +      "jirl\t$r1,$r1,%%desc_call(%0)"
> +    : "la.tls.desc\t$r4,%0";
> +}
> +  [(set_attr "got" "load")
> +   (set_attr "mode" "<MODE>")
> +   (set_attr "length" "16")])
> +
> +(define_insn "got_load_tls_desc_off64"
> +  [(set (reg:DI 4)
> +	(unspec:DI
> +	    [(match_operand:DI 0 "symbolic_operand" "")]
> +	    UNSPEC_TLS_DESC_OFF64))
> +    (clobber (reg:SI FCC0_REGNUM))
> +    (clobber (reg:SI FCC1_REGNUM))
> +    (clobber (reg:SI FCC2_REGNUM))
> +    (clobber (reg:SI FCC3_REGNUM))
> +    (clobber (reg:SI FCC4_REGNUM))
> +    (clobber (reg:SI FCC5_REGNUM))
> +    (clobber (reg:SI FCC6_REGNUM))
> +    (clobber (reg:SI FCC7_REGNUM))
> +    (clobber (reg:SI RETURN_ADDR_REGNUM))
> +    (clobber (match_operand:DI 1 "register_operand" "=&r"))]
> +  "TARGET_TLS_DESC && TARGET_CMODEL_EXTREME"
> +{
> +  return TARGET_EXPLICIT_RELOCS
> +    ? "pcalau12i\t$r4,%%desc_pc_hi20(%0)\n\t"
> +      "addi.d\t%1,$r0,%%desc_pc_lo12(%0)\n\t"
> +      "lu32i.d\t%1,%%desc64_pc_lo20(%0)\n\t"
> +      "lu52i.d\t%1,%1,%%desc64_pc_hi12(%0)\n\t"
> +      "add.d\t$r4,$r4,%1\n\t"
> +      "ld.d\t$r1,$r4,%%desc_ld(%0)\n\t"
> +      "jirl\t$r1,$r1,%%desc_call(%0)"
> +    : "la.tls.desc\t$r4,%1,%0";
> +}
> +  [(set_attr "got" "load")
> +   (set_attr "length" "28")])
> +
>   (define_insn "@load_tls<mode>"
>     [(set (match_operand:P 0 "register_operand" "=r")
>   	(unspec:P
> diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt
> index f10fcdd968c..1c54ab6ae43 100644
> --- a/gcc/config/loongarch/loongarch.opt
> +++ b/gcc/config/loongarch/loongarch.opt
> @@ -271,6 +271,20 @@ default value is 4.
>   TargetVariable
>   HOST_WIDE_INT la_isa_evolution = 0
>   
> +Enum
> +Name(tls_type) Type(int)
> +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(la_opt_tls_dialect) Init(M_OPT_UNSET) Save
> +Specify TLS dialect.
> +
>   mfrecipe
>   Target Mask(ISA_FRECIPE) Var(la_isa_evolution)
>   Support frecipe.{s/d} and frsqrte.{s/d} instructions.
> diff --git a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c
> index 564ee4017f7..6269607e7df 100644
> --- a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c
> +++ b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -fno-plt -mexplicit-relocs=always -fdump-rtl-final" } */
> +/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=always -fdump-rtl-final" } */
>   
>   int a;
>   extern int b;
> diff --git a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c
> index ce834805f38..35f6ee0bb30 100644
> --- a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c
> +++ b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -fno-plt -mexplicit-relocs=auto -fdump-rtl-final" } */
> +/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=auto -fdump-rtl-final" } */
>   
>   #include "cmodel-extreme-1.c"
>   
> diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c
> new file mode 100644
> index 00000000000..0fc7a1a5117
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fPIC -mcmodel=extreme -mexplicit-relocs=auto -mtls-dialect=desc" } */
> +
> +__thread int a __attribute__((visibility("hidden")));
> +extern __thread int b __attribute__((visibility("default")));
> +
> +int test() { return a + b; }
> +
> +/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\\$r12,\\.LANCHOR0" { target tls_native } } } */
> +/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\\$r12,\\.LANCHOR0" { target tls_native } } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c
> new file mode 100644
> index 00000000000..37947ecfdc8
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c
> @@ -0,0 +1,10 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=desc" } */
> +
> +__thread int a __attribute__((visibility("hidden")));
> +extern __thread int b __attribute__((visibility("default")));
> +
> +int test() { return a + b; }
> +
> +/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\.LANCHOR0" { target tls_native } } } */
> +/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\.LANCHOR0" { target tls_native } } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c
> index ca55fcfc53e..b47e37c822c 100644
> --- a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c
> +++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto" } */
> +/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=trad" } */
>   
>   __thread int a __attribute__((visibility("hidden")));
>   extern __thread int b __attribute__((visibility("default")));
> diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c
> new file mode 100644
> index 00000000000..3797556e1e6
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c
> @@ -0,0 +1,16 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fPIC -mexplicit-relocs -mtls-dialect=desc -mcmodel=extreme" } */
> +
> +__thread int a __attribute__((visibility("hidden")));
> +extern __thread int b __attribute__((visibility("default")));
> +
> +int test() { return a + b; }
> +
> +/* { dg-final { scan-assembler "pcalau12i\t\\\$r4,%desc_pc_hi20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "addi.d\t\\\$r12,\\\$r0,%desc_pc_lo12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "lu32i.d\t\\\$r12,%desc64_pc_lo20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "lu52i.d\t\\\$r12,\\\$r12,%desc64_pc_hi12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "add.d\t\\\$r4,\\\$r4,\\\$r12" { target tls_native } } } */
> +/* { dg-final { scan-assembler "ld.d\t\\\$r1,\\\$r4,%desc_ld\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "jirl\t\\\$r1,\\\$r1,%desc_call\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "add.d\t\\\$r12,\\\$r4,\\\$r2" { target tls_native } } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c
> index d1a4820834c..cfb8553236a 100644
> --- a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c
> +++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mcmodel=medium -fplt" } */
> +/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=trad -mcmodel=medium -fplt" } */
>   /* { dg-final { scan-assembler "pcaddu18i\t\\\$r1,%call36\\\(__tls_get_addr\\\)" { target { tls_native && loongarch_call36_support } } } } */
>   
>   #include "./explicit-relocs-auto-tls-ld-gd.c"
> diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c
> new file mode 100644
> index 00000000000..f6690309156
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c
> @@ -0,0 +1,13 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fPIC -mexplicit-relocs -mtls-dialect=desc" } */
> +
> +__thread int a __attribute__((visibility("hidden")));
> +extern __thread int b __attribute__((visibility("default")));
> +
> +int test() { return a + b; }
> +
> +/* { dg-final { scan-assembler "pcalau12i\t\\\$r4,%desc_pc_hi20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "addi.d\t\\\$r4,\\\$r4,%desc_pc_lo12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "ld.d\t\\\$r1,\\\$r4,%desc_ld\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "jirl\t\\\$r1,\\\$r1,%desc_call\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
> +/* { dg-final { scan-assembler "add.d\t\\\$r12,\\\$r4,\\\$r2" { target tls_native } } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
> index 6339e832fe5..5e81df55207 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mcmodel=medium" } */
> +/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
>   /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
> index a53e75e0bf9..d73df2dd8c2 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mcmodel=medium" } */
> +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
>   /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
> index 0da7bf98e3c..88a66745070 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mcmodel=medium" } */
> +/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
>   /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
> index 0219688ae80..f9dc12feaf5 100644
> --- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
> +++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mcmodel=medium" } */
> +/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
>   /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */
>   /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c b/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c
> index 4341f82129c..4adda4202fd 100644
> --- a/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c
> +++ b/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -fno-plt -mexplicit-relocs=none" } */
> +/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=none" } */
>   /* { dg-final { scan-assembler "test_le:.*la.tls.le\t\\\$r\[0-9\]+,\\\.L" { target tls_native } } } */
>   /* { dg-final { scan-assembler "test_ie:.*la.tls.ie\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,\\\.L" { target tls_native } } } */
>   /* { dg-final { scan-assembler "test_ld:.*la.tls.ld\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,\\\.L.*la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,__tls_get_addr" { target tls_native } } } */
> diff --git a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c
> index 9432c477e9d..dfa1bf53c92 100644
> --- a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c
> +++ b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c
> @@ -1,5 +1,5 @@
>   /* { dg-do compile } */
> -/* { dg-options "-O0 -fno-plt -mcmodel=normal -mexplicit-relocs" } */
> +/* { dg-options "-O0 -fno-plt -mcmodel=normal -mtls-dialect=trad -mexplicit-relocs" } */
>   /* { dg-final { scan-assembler "pcalau12i\t.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
>   
>   __attribute__ ((tls_model ("global-dynamic"))) __thread int a;
diff mbox series

Patch

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 624e0dae191..baebafdbf5d 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -4991,7 +4991,7 @@  case "${target}" in
 		;;
 
 	loongarch*-*)
-		supported_defaults="abi arch tune fpu simd multilib-default strict-align-lib"
+		supported_defaults="abi arch tune fpu simd multilib-default strict-align-lib tls"
 
 		# Local variables
 		unset \
@@ -5249,6 +5249,18 @@  case "${target}" in
 			with_multilib_list="${abi_base}/${abi_ext}"
 		fi
 
+		# Handle --with-tls.
+		case "$with_tls" in
+		"" \
+		| trad | desc)
+		    # OK
+		    ;;
+		*)
+		    echo "Unknown TLS method used in --with-tls=$with_tls" 1>&2
+		    exit 1
+		    ;;
+		esac
+
 		# Check if the configured default ABI combination is included in
 		# ${with_multilib_list}.
 		loongarch_multilib_list_sane=no
@@ -5914,6 +5926,11 @@  case ${target} in
 		lasx)    tm_defines="$tm_defines DEFAULT_ISA_EXT_SIMD=ISA_EXT_SIMD_LASX" ;;
 		esac
 
+		case ${with_tls} in
+		"" | trad)	tm_defines="$tm_defines DEFAULT_TLS_TYPE=TLS_TRADITIONAL" ;;
+		desc)		tm_defines="$tm_defines DEFAULT_TLS_TYPE=TLS_DESCRIPTORS" ;;
+		esac
+
 		tmake_file="loongarch/t-loongarch $tmake_file"
 		;;
 
diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in
index 02f918053f5..7de107c3e3d 100644
--- a/gcc/config/loongarch/genopts/loongarch.opt.in
+++ b/gcc/config/loongarch/genopts/loongarch.opt.in
@@ -262,3 +262,17 @@  default value is 4.
 ; CPUCFG independently, so we use bit flags to specify them.
 TargetVariable
 HOST_WIDE_INT la_isa_evolution = 0
+
+Enum
+Name(tls_type) Type(int)
+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(la_opt_tls_dialect) Init(M_OPT_UNSET) Save
+Specify TLS dialect.
diff --git a/gcc/config/loongarch/loongarch-def.h b/gcc/config/loongarch/loongarch-def.h
index 2dbf006d013..48d60e2b456 100644
--- a/gcc/config/loongarch/loongarch-def.h
+++ b/gcc/config/loongarch/loongarch-def.h
@@ -175,6 +175,7 @@  struct loongarch_target
   int cpu_arch;	    /* CPU_ */
   int cpu_tune;	    /* same */
   int cmodel;	    /* CMODEL_ */
+  int tls_dialect;  /* TLS_ */
 };
 
 /* CPU model */
@@ -188,6 +189,12 @@  enum {
   N_TUNE_TYPES	    = 5
 };
 
+/* TLS types.  */
+enum {
+  TLS_TRADITIONAL = 0,
+  TLS_DESCRIPTORS = 1
+};
+
 /* CPU model properties */
 extern loongarch_def_array<const char *, N_ARCH_TYPES>
   loongarch_cpu_strings;
diff --git a/gcc/config/loongarch/loongarch-driver.cc b/gcc/config/loongarch/loongarch-driver.cc
index 62658f531ad..8c4ed34698b 100644
--- a/gcc/config/loongarch/loongarch-driver.cc
+++ b/gcc/config/loongarch/loongarch-driver.cc
@@ -45,7 +45,7 @@  la_driver_init (int argc ATTRIBUTE_UNUSED, const char **argv ATTRIBUTE_UNUSED)
   /* Initialize all fields of la_target.  */
   loongarch_init_target (&la_target, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET,
 			 M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET, M_OPT_UNSET,
-			 0, 0);
+			 M_OPT_UNSET, 0, 0);
   return "";
 }
 
diff --git a/gcc/config/loongarch/loongarch-opts.cc b/gcc/config/loongarch/loongarch-opts.cc
index 7eeac43ed2f..ec929aa7f29 100644
--- a/gcc/config/loongarch/loongarch-opts.cc
+++ b/gcc/config/loongarch/loongarch-opts.cc
@@ -139,6 +139,7 @@  void
 loongarch_init_target (struct loongarch_target *target,
 		       int cpu_arch, int cpu_tune, int fpu, int simd,
 		       int abi_base, int abi_ext, int cmodel,
+		       int tls_dialect,
 		       HOST_WIDE_INT isa_evolution,
 		       HOST_WIDE_INT isa_evolution_set)
 {
@@ -153,6 +154,7 @@  loongarch_init_target (struct loongarch_target *target,
   target->abi.base = abi_base;
   target->abi.ext = abi_ext;
   target->cmodel = cmodel;
+  target->tls_dialect = tls_dialect;
 }
 
 
@@ -174,7 +176,8 @@  loongarch_config_target (struct loongarch_target *target,
   obstack_init (&msg_obstack);
 
   struct {
-    int arch, tune, fpu, simd, abi_base, abi_ext, cmodel, abi_flt;
+    int arch, tune, fpu, simd, abi_base, abi_ext, cmodel,
+	tls_dialect, abi_flt;
   } constrained = {
       M_OPT_ABSENT (target->cpu_arch)	  ? 0 : 1,
       M_OPT_ABSENT (target->cpu_tune)	  ? 0 : 1,
@@ -183,6 +186,7 @@  loongarch_config_target (struct loongarch_target *target,
       M_OPT_ABSENT (target->abi.base)	  ? 0 : 1,
       M_OPT_ABSENT (target->abi.ext)	  ? 0 : 1,
       M_OPT_ABSENT (target->cmodel)	  ? 0 : 1,
+      M_OPT_ABSENT (target->tls_dialect)  ? 0 : 1,
       M_OPT_ABSENT (target->abi.base)	  ? 0 : 1,
   };
 
@@ -551,6 +555,9 @@  fallback:
       gcc_unreachable ();
     }
 
+  t.tls_dialect = constrained.tls_dialect ? target->tls_dialect
+	  : DEFAULT_TLS_TYPE;
+
   /* Cleanup and return.  */
   obstack_free (&msg_obstack, NULL);
   *target = t;
@@ -786,6 +793,9 @@  loongarch_update_gcc_opt_status (struct loongarch_target *target,
   /* status of -mcmodel */
   opts->x_la_opt_cmodel = target->cmodel;
 
+  /* status of -mtls-dialect */
+  opts->x_la_opt_tls_dialect = target->tls_dialect;
+
   /* status of -mfpu */
   opts->x_la_opt_fpu = target->isa.fpu;
 
diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h
index 586e67e65ee..88e23fcee4b 100644
--- a/gcc/config/loongarch/loongarch-opts.h
+++ b/gcc/config/loongarch/loongarch-opts.h
@@ -35,6 +35,7 @@  void
 loongarch_init_target (struct loongarch_target *target,
 		       int cpu_arch, int cpu_tune, int fpu, int simd,
 		       int abi_base, int abi_ext, int cmodel,
+		       int tls_dialect,
 		       HOST_WIDE_INT isa_evolutions,
 		       HOST_WIDE_INT isa_evolutions_set);
 
@@ -83,6 +84,7 @@  struct loongarch_flags {
 #define TARGET_ABI_LP64		  (la_target.abi.base == ABI_BASE_LP64D	\
 				   || la_target.abi.base == ABI_BASE_LP64F \
 				   || la_target.abi.base == ABI_BASE_LP64S)
+#define TARGET_TLS_DESC		  (la_target.tls_dialect == TLS_DESCRIPTORS)
 
 #define ISA_HAS_LSX \
   (la_target.isa.simd == ISA_EXT_SIMD_LSX \
diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc
index 70e31bb831c..1d7fa2ca3b1 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -2028,7 +2028,7 @@  loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode)
 
     case SYMBOL_TLSGD:
     case SYMBOL_TLSLDM:
-      return 3;
+      return TARGET_TLS_DESC ? 4 : 3;
 
     case SYMBOL_PCREL64:
       return 5;
@@ -2930,24 +2930,43 @@  loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0)
 static rtx
 loongarch_legitimize_tls_address (rtx loc)
 {
-  rtx dest, tp, tmp, tmp1, tmp2, tmp3;
+  rtx dest, tp, tmp, tmp1, tmp2, tmp3, a0;
   enum tls_model model = SYMBOL_REF_TLS_MODEL (loc);
   rtx_insn *insn;
 
   switch (model)
     {
     case TLS_MODEL_LOCAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
-      emit_libcall_block (insn, dest, tmp, loc);
-      break;
-
+      if (!TARGET_TLS_DESC)
+	{
+	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
+	  dest = gen_reg_rtx (Pmode);
+	  insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp);
+	  emit_libcall_block (insn, dest, tmp, loc);
+	  break;
+	}
+      /* Fall through.  */
     case TLS_MODEL_GLOBAL_DYNAMIC:
-      tmp = gen_rtx_REG (Pmode, GP_RETURN);
-      dest = gen_reg_rtx (Pmode);
-      insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
-      emit_libcall_block (insn, dest, tmp, loc);
+      if (TARGET_TLS_DESC)
+	{
+	  a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+	  dest = gen_reg_rtx (Pmode);
+	  tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM);
+
+	  if (TARGET_CMODEL_EXTREME)
+	    emit_insn (gen_got_load_tls_desc_off64 (loc, gen_reg_rtx (DImode)));
+	  else
+	    emit_insn (gen_got_load_tls_desc (Pmode, loc));
+
+	  emit_insn (gen_add3_insn (dest, a0, tp));
+	}
+      else
+	{
+	  tmp = gen_rtx_REG (Pmode, GP_RETURN);
+	  dest = gen_reg_rtx (Pmode);
+	  insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp);
+	  emit_libcall_block (insn, dest, tmp, loc);
+	}
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
@@ -7660,7 +7679,8 @@  loongarch_option_override_internal (struct gcc_options *opts,
   loongarch_init_target (&la_target,
 			 la_opt_cpu_arch, la_opt_cpu_tune, la_opt_fpu,
 			 la_opt_simd, la_opt_abi_base, la_opt_abi_ext,
-			 la_opt_cmodel, opts->x_la_isa_evolution,
+			 la_opt_cmodel, la_opt_tls_dialect,
+			 opts->x_la_isa_evolution,
 			 opts_set->x_la_isa_evolution);
 
   /* Handle target-specific options: compute defaults/conflicts etc.  */
@@ -7873,6 +7893,7 @@  loongarch_option_restore (struct gcc_options *,
   la_target.isa.evolution = ptr->x_la_isa_evolution;
 
   la_target.cmodel = ptr->x_la_opt_cmodel;
+  la_target.tls_dialect = ptr->x_la_opt_tls_dialect;
 }
 
 /* Implement TARGET_CONDITIONAL_REGISTER_USAGE.  */
diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md
index 525e1e82183..f4ff6f91311 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -52,6 +52,8 @@  (define_c_enum "unspec" [
 
   ;; TLS
   UNSPEC_TLS
+  UNSPEC_TLS_DESC
+  UNSPEC_TLS_DESC_OFF64
 
   ;; Stack tie
   UNSPEC_TIE
@@ -127,6 +129,15 @@  (define_constants
    (T1_REGNUM			13)
    (S0_REGNUM			23)
 
+   (FCC0_REGNUM			64)
+   (FCC1_REGNUM			65)
+   (FCC2_REGNUM			66)
+   (FCC3_REGNUM			67)
+   (FCC4_REGNUM			68)
+   (FCC5_REGNUM			69)
+   (FCC6_REGNUM			70)
+   (FCC7_REGNUM			71)
+
    ;; Return path styles
    (NORMAL_RETURN		0)
    (SIBCALL_RETURN		1)
@@ -2760,6 +2771,63 @@  (define_insn "store_word<mode>"
 
 ;; Thread-Local Storage
 
+(define_insn "@got_load_tls_desc<mode>"
+  [(set (reg:P 4)
+	(unspec:P
+	    [(match_operand:P 0 "symbolic_operand" "")]
+	    UNSPEC_TLS_DESC))
+    (clobber (reg:SI FCC0_REGNUM))
+    (clobber (reg:SI FCC1_REGNUM))
+    (clobber (reg:SI FCC2_REGNUM))
+    (clobber (reg:SI FCC3_REGNUM))
+    (clobber (reg:SI FCC4_REGNUM))
+    (clobber (reg:SI FCC5_REGNUM))
+    (clobber (reg:SI FCC6_REGNUM))
+    (clobber (reg:SI FCC7_REGNUM))
+    (clobber (reg:SI RETURN_ADDR_REGNUM))]
+  "TARGET_TLS_DESC"
+{
+  return TARGET_EXPLICIT_RELOCS
+    ? "pcalau12i\t$r4,%%desc_pc_hi20(%0)\n\t"
+      "addi.d\t$r4,$r4,%%desc_pc_lo12(%0)\n\t"
+      "ld.d\t$r1,$r4,%%desc_ld(%0)\n\t"
+      "jirl\t$r1,$r1,%%desc_call(%0)"
+    : "la.tls.desc\t$r4,%0";
+}
+  [(set_attr "got" "load")
+   (set_attr "mode" "<MODE>")
+   (set_attr "length" "16")])
+
+(define_insn "got_load_tls_desc_off64"
+  [(set (reg:DI 4)
+	(unspec:DI
+	    [(match_operand:DI 0 "symbolic_operand" "")]
+	    UNSPEC_TLS_DESC_OFF64))
+    (clobber (reg:SI FCC0_REGNUM))
+    (clobber (reg:SI FCC1_REGNUM))
+    (clobber (reg:SI FCC2_REGNUM))
+    (clobber (reg:SI FCC3_REGNUM))
+    (clobber (reg:SI FCC4_REGNUM))
+    (clobber (reg:SI FCC5_REGNUM))
+    (clobber (reg:SI FCC6_REGNUM))
+    (clobber (reg:SI FCC7_REGNUM))
+    (clobber (reg:SI RETURN_ADDR_REGNUM))
+    (clobber (match_operand:DI 1 "register_operand" "=&r"))]
+  "TARGET_TLS_DESC && TARGET_CMODEL_EXTREME"
+{
+  return TARGET_EXPLICIT_RELOCS
+    ? "pcalau12i\t$r4,%%desc_pc_hi20(%0)\n\t"
+      "addi.d\t%1,$r0,%%desc_pc_lo12(%0)\n\t"
+      "lu32i.d\t%1,%%desc64_pc_lo20(%0)\n\t"
+      "lu52i.d\t%1,%1,%%desc64_pc_hi12(%0)\n\t"
+      "add.d\t$r4,$r4,%1\n\t"
+      "ld.d\t$r1,$r4,%%desc_ld(%0)\n\t"
+      "jirl\t$r1,$r1,%%desc_call(%0)"
+    : "la.tls.desc\t$r4,%1,%0";
+}
+  [(set_attr "got" "load")
+   (set_attr "length" "28")])
+
 (define_insn "@load_tls<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")
 	(unspec:P
diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt
index f10fcdd968c..1c54ab6ae43 100644
--- a/gcc/config/loongarch/loongarch.opt
+++ b/gcc/config/loongarch/loongarch.opt
@@ -271,6 +271,20 @@  default value is 4.
 TargetVariable
 HOST_WIDE_INT la_isa_evolution = 0
 
+Enum
+Name(tls_type) Type(int)
+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(la_opt_tls_dialect) Init(M_OPT_UNSET) Save
+Specify TLS dialect.
+
 mfrecipe
 Target Mask(ISA_FRECIPE) Var(la_isa_evolution)
 Support frecipe.{s/d} and frsqrte.{s/d} instructions.
diff --git a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c
index 564ee4017f7..6269607e7df 100644
--- a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -fno-plt -mexplicit-relocs=always -fdump-rtl-final" } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=always -fdump-rtl-final" } */
 
 int a;
 extern int b;
diff --git a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c
index ce834805f38..35f6ee0bb30 100644
--- a/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c
+++ b/gcc/testsuite/gcc.target/loongarch/cmodel-extreme-2.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -fno-plt -mexplicit-relocs=auto -fdump-rtl-final" } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=auto -fdump-rtl-final" } */
 
 #include "cmodel-extreme-1.c"
 
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c
new file mode 100644
index 00000000000..0fc7a1a5117
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-extreme-tls-desc.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mcmodel=extreme -mexplicit-relocs=auto -mtls-dialect=desc" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\\$r12,\\.LANCHOR0" { target tls_native } } } */
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\\$r12,\\.LANCHOR0" { target tls_native } } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c
new file mode 100644
index 00000000000..37947ecfdc8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-desc.c
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=desc" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\.LANCHOR0" { target tls_native } } } */
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\.LANCHOR0" { target tls_native } } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c
index ca55fcfc53e..b47e37c822c 100644
--- a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-auto-tls-ld-gd.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto" } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=trad" } */
 
 __thread int a __attribute__((visibility("hidden")));
 extern __thread int b __attribute__((visibility("default")));
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c
new file mode 100644
index 00000000000..3797556e1e6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-extreme-tls-desc.c
@@ -0,0 +1,16 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs -mtls-dialect=desc -mcmodel=extreme" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "pcalau12i\t\\\$r4,%desc_pc_hi20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "addi.d\t\\\$r12,\\\$r0,%desc_pc_lo12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "lu32i.d\t\\\$r12,%desc64_pc_lo20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "lu52i.d\t\\\$r12,\\\$r12,%desc64_pc_hi12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "add.d\t\\\$r4,\\\$r4,\\\$r12" { target tls_native } } } */
+/* { dg-final { scan-assembler "ld.d\t\\\$r1,\\\$r4,%desc_ld\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "jirl\t\\\$r1,\\\$r1,%desc_call\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "add.d\t\\\$r12,\\\$r4,\\\$r2" { target tls_native } } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c
index d1a4820834c..cfb8553236a 100644
--- a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-medium-call36-auto-tls-ld-gd.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mcmodel=medium -fplt" } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=trad -mcmodel=medium -fplt" } */
 /* { dg-final { scan-assembler "pcaddu18i\t\\\$r1,%call36\\\(__tls_get_addr\\\)" { target { tls_native && loongarch_call36_support } } } } */
 
 #include "./explicit-relocs-auto-tls-ld-gd.c"
diff --git a/gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c
new file mode 100644
index 00000000000..f6690309156
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/explicit-relocs-tls-desc.c
@@ -0,0 +1,13 @@ 
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs -mtls-dialect=desc" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "pcalau12i\t\\\$r4,%desc_pc_hi20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "addi.d\t\\\$r4,\\\$r4,%desc_pc_lo12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "ld.d\t\\\$r1,\\\$r4,%desc_ld\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "jirl\t\\\$r1,\\\$r1,%desc_call\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "add.d\t\\\$r12,\\\$r4,\\\$r2" { target tls_native } } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
index 6339e832fe5..5e81df55207 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-1.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mcmodel=medium" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
 /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
 /* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
 /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
index a53e75e0bf9..d73df2dd8c2 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-2.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mcmodel=medium" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
 /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
 /* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */
 /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
index 0da7bf98e3c..88a66745070 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-3.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mcmodel=medium" } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
 /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
 /* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
 /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
index 0219688ae80..f9dc12feaf5 100644
--- a/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
+++ b/gcc/testsuite/gcc.target/loongarch/func-call-medium-4.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mcmodel=medium" } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
 /* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
 /* { dg-final { scan-assembler "test1:.*la\.local\t.*f\n\tjirl" } } */
 /* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c b/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c
index 4341f82129c..4adda4202fd 100644
--- a/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c
+++ b/gcc/testsuite/gcc.target/loongarch/tls-extreme-macro.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -fno-plt -mexplicit-relocs=none" } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=none" } */
 /* { dg-final { scan-assembler "test_le:.*la.tls.le\t\\\$r\[0-9\]+,\\\.L" { target tls_native } } } */
 /* { dg-final { scan-assembler "test_ie:.*la.tls.ie\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,\\\.L" { target tls_native } } } */
 /* { dg-final { scan-assembler "test_ld:.*la.tls.ld\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,\\\.L.*la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,__tls_get_addr" { target tls_native } } } */
diff --git a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c
index 9432c477e9d..dfa1bf53c92 100644
--- a/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c
+++ b/gcc/testsuite/gcc.target/loongarch/tls-gd-noplt.c
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O0 -fno-plt -mcmodel=normal -mexplicit-relocs" } */
+/* { dg-options "-O0 -fno-plt -mcmodel=normal -mtls-dialect=trad -mexplicit-relocs" } */
 /* { dg-final { scan-assembler "pcalau12i\t.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
 
 __attribute__ ((tls_model ("global-dynamic"))) __thread int a;