Generate la.tls.desc macro instruction for TLS descriptors model. la.tls.desc expand to pcalau12i $a0, %desc_pc_hi20(a) ld.d $a1, $a0, %desc_ld_pc_lo12(a) addi.d $a0, $a0, %desc_add_pc_lo12(a) jirl $ra, $a1, %desc_call(a)
The default is TLS descriptors, but can be configure with -mtls-dialect={desc,trad}. gcc/ChangeLog: * config.gcc: Add --with_tls to change the TLS flavor. * config/loongarch/genopts/loongarch.opt.in: Add -mtls-dialect to configure TLS flavor. * config/loongarch/loongarch-opts.h (enum loongarch_tls_type): New. * config/loongarch/loongarch-protos.h (NUM_SYMBOL_TYPES): New. * config/loongarch/loongarch.cc (loongarch_symbol_insns): Add instruction sequence length data for TLS DESC. (loongarch_legitimize_tls_address): New TLS DESC instruction sequence. * config/loongarch/loongarch.h (TARGET_TLS_DESC): New. * config/loongarch/loongarch.md (@got_load_tls_desc<mode>): New. * config/loongarch/loongarch.opt: Regenerated. --- gcc/config.gcc | 16 ++++++- gcc/config/loongarch/genopts/loongarch.opt.in | 14 ++++++ gcc/config/loongarch/loongarch-opts.h | 6 +++ gcc/config/loongarch/loongarch-protos.h | 3 +- gcc/config/loongarch/loongarch.cc | 45 +++++++++++++++---- gcc/config/loongarch/loongarch.h | 9 ++++ gcc/config/loongarch/loongarch.md | 15 +++++++ gcc/config/loongarch/loongarch.opt | 14 ++++++ 8 files changed, 111 insertions(+), 11 deletions(-) diff --git a/gcc/config.gcc b/gcc/config.gcc index 748430194f3..5b3120dff6d 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2545,6 +2545,7 @@ loongarch*-*-linux*) # Force .init_array support. The configure script cannot always # automatically detect that GAS supports it, yet we require it. gcc_cv_initfini_array=yes + with_tls=${with_tls:-desc} ;; loongarch*-*-elf*) @@ -2557,6 +2558,7 @@ loongarch*-*-elf*) # For .init_array support. The configure script cannot always # automatically detect that GAS supports it, yet we require it. gcc_cv_initfini_array=yes + with_tls=${with_tls:-desc} ;; mips*-*-netbsd*) # NetBSD/mips, either endian. @@ -4986,7 +4988,7 @@ case "${target}" in ;; loongarch*-*) - supported_defaults="abi arch tune fpu simd multilib-default strict-align-lib" + supported_defaults="abi arch tune fpu simd multilib-default strict-align-lib tls" # Local variables unset \ @@ -5244,6 +5246,18 @@ case "${target}" in with_multilib_list="${abi_base}/${abi_ext}" fi + # Handle --with-tls. + case "$with_tls" in + "" \ + | trad | desc) + # OK + ;; + *) + echo "Unknown TLS method used in --with-tls=$with_tls" 1>&2 + exit 1 + ;; + esac + # Check if the configured default ABI combination is included in # ${with_multilib_list}. loongarch_multilib_list_sane=no diff --git a/gcc/config/loongarch/genopts/loongarch.opt.in b/gcc/config/loongarch/genopts/loongarch.opt.in index 8af6cc6f532..4a2ae80f25b 100644 --- a/gcc/config/loongarch/genopts/loongarch.opt.in +++ b/gcc/config/loongarch/genopts/loongarch.opt.in @@ -254,3 +254,17 @@ default value is 4. ; CPUCFG independantly, so we use bit flags to specify them. Variable HOST_WIDE_INT isa_evolution = 0 + +Enum +Name(tls_type) Type(enum loongarch_tls_type) +The possible TLS dialects: + +EnumValue +Enum(tls_type) String(trad) Value(TLS_TRADITIONAL) + +EnumValue +Enum(tls_type) String(desc) Value(TLS_DESCRIPTORS) + +mtls-dialect= +Target RejectNegative Joined Enum(tls_type) Var(loongarch_tls_dialect) Init(TLS_DESCRIPTORS) Save +Specify TLS dialect. diff --git a/gcc/config/loongarch/loongarch-opts.h b/gcc/config/loongarch/loongarch-opts.h index fa3773223bc..28cd08712f4 100644 --- a/gcc/config/loongarch/loongarch-opts.h +++ b/gcc/config/loongarch/loongarch-opts.h @@ -115,4 +115,10 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target, #define HAVE_AS_TLS 0 #endif +/* TLS types. */ +enum loongarch_tls_type { + TLS_TRADITIONAL, + TLS_DESCRIPTORS +}; + #endif /* LOONGARCH_OPTS_H */ diff --git a/gcc/config/loongarch/loongarch-protos.h b/gcc/config/loongarch/loongarch-protos.h index cb8fc36b086..4b3f942da90 100644 --- a/gcc/config/loongarch/loongarch-protos.h +++ b/gcc/config/loongarch/loongarch-protos.h @@ -53,8 +53,9 @@ enum loongarch_symbol_type { SYMBOL_TLS_LE, SYMBOL_TLSGD, SYMBOL_TLSLDM, + SYMBOL_TLS_DESC, }; -#define NUM_SYMBOL_TYPES (SYMBOL_TLSLDM + 1) +#define NUM_SYMBOL_TYPES (SYMBOL_TLS_DESC + 1) /* Routines implemented in loongarch.cc. */ extern rtx loongarch_emit_move (rtx, rtx); diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index d3896d72bc2..c53e88dc82f 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -2004,6 +2004,9 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode) case SYMBOL_TLSLDM: return 3; + case SYMBOL_TLS_DESC: + return 4; + case SYMBOL_PCREL64: return 5; @@ -2919,24 +2922,48 @@ loongarch_call_tls_get_addr (rtx sym, enum loongarch_symbol_type type, rtx v0) static rtx loongarch_legitimize_tls_address (rtx loc) { - rtx dest, tp, tmp, tmp1, tmp2, tmp3; + rtx dest, tp, tmp, tmp1, tmp2, tmp3, a0; /* a1? */ enum tls_model model = SYMBOL_REF_TLS_MODEL (loc); rtx_insn *insn; switch (model) { case TLS_MODEL_LOCAL_DYNAMIC: - tmp = gen_rtx_REG (Pmode, GP_RETURN); - dest = gen_reg_rtx (Pmode); - insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp); - emit_libcall_block (insn, dest, tmp, loc); + if (TARGET_TLS_DESC) + { + a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); + dest = gen_reg_rtx (Pmode); + tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); + + emit_insn (gen_got_load_tls_desc (Pmode, a0, loc)); + emit_insn (gen_add3_insn (dest, a0, tp)); + } + else + { + tmp = gen_rtx_REG (Pmode, GP_RETURN); + dest = gen_reg_rtx (Pmode); + insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSLDM, tmp); + emit_libcall_block (insn, dest, tmp, loc); + } break; case TLS_MODEL_GLOBAL_DYNAMIC: - tmp = gen_rtx_REG (Pmode, GP_RETURN); - dest = gen_reg_rtx (Pmode); - insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp); - emit_libcall_block (insn, dest, tmp, loc); + if (TARGET_TLS_DESC) + { + a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); + dest = gen_reg_rtx (Pmode); + tp = gen_rtx_REG (Pmode, THREAD_POINTER_REGNUM); + + emit_insn (gen_got_load_tls_desc (Pmode, a0, loc)); + emit_insn (gen_add3_insn (dest, a0, tp)); + } + else + { + tmp = gen_rtx_REG (Pmode, GP_RETURN); + dest = gen_reg_rtx (Pmode); + insn = loongarch_call_tls_get_addr (loc, SYMBOL_TLSGD, tmp); + emit_libcall_block (insn, dest, tmp, loc); + } break; case TLS_MODEL_INITIAL_EXEC: diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h index 115222e70fd..f474cdc2857 100644 --- a/gcc/config/loongarch/loongarch.h +++ b/gcc/config/loongarch/loongarch.h @@ -25,6 +25,15 @@ along with GCC; see the file COPYING3. If not see #define TARGET_SUPPORTS_WIDE_INT 1 +/* Check TLS Descriptors mechanism is selected. */ +#define TARGET_TLS_DESC (loongarch_tls_dialect == TLS_DESCRIPTORS) + +/* --with-tls is ignored if -mtls-dialect is specified. */ +/* +#define OPTION_DEFAULT_SPECS \ + {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"}, \ +*/ + /* Macros to silence warnings about numbers being signed in traditional C and unsigned in ISO C when compiled on 32-bit hosts. */ diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index cd4ed495697..71f46c9d2fe 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -55,6 +55,7 @@ (define_c_enum "unspec" [ UNSPEC_TLS_LD UNSPEC_TLS_LE UNSPEC_TLS_IE + UNSPEC_TLS_DESC ;; Stack tie UNSPEC_TIE @@ -114,6 +115,8 @@ (define_c_enum "unspecv" [ (define_constants [(RETURN_ADDR_REGNUM 1) (TP_REGNUM 2) + (A0_REGNUM 4) + (A1_REGNUM 5) (T0_REGNUM 12) (T1_REGNUM 13) (S0_REGNUM 23) @@ -2436,6 +2439,18 @@ (define_insn "store_word<mode>" ;; Thread-Local Storage +(define_insn "@got_load_tls_desc<mode>" + [(set (match_operand:P 0 "register_operand" "=r") + (unspec:P + [(match_operand:P 1 "symbolic_operand" "")] + UNSPEC_TLS_DESC)) + (clobber (reg:SI A1_REGNUM)) + (clobber (reg:SI RETURN_ADDR_REGNUM))] + "TARGET_TLS_DESC" + "la.tls.desc\t%0,%1" + [(set_attr "got" "load") + (set_attr "mode" "<MODE>")]) + (define_insn "@got_load_tls_gd<mode>" [(set (match_operand:P 0 "register_operand" "=r") (unspec:P diff --git a/gcc/config/loongarch/loongarch.opt b/gcc/config/loongarch/loongarch.opt index 4d36e3ec4de..ad2e770e1e6 100644 --- a/gcc/config/loongarch/loongarch.opt +++ b/gcc/config/loongarch/loongarch.opt @@ -278,3 +278,17 @@ Support amcas[_db].{b/h/w/d} instructions. mld-seq-sa Target Mask(ISA_LD_SEQ_SA) Var(isa_evolution) Do not need load-load barriers (dbar 0x700). + +Enum +Name(tls_type) Type(enum loongarch_tls_type) +The possible TLS dialects: + +EnumValue +Enum(tls_type) String(trad) Value(TLS_TRADITIONAL) + +EnumValue +Enum(tls_type) String(desc) Value(TLS_DESCRIPTORS) + +mtls-dialect= +Target RejectNegative Joined Enum(tls_type) Var(loongarch_tls_dialect) Init(TLS_DESCRIPTORS) Save +Specify TLS dialect. -- 2.36.0