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. --- Changes v1 -> v2: - Clobber fcc0-fcc7 registers in got_load_tls_desc template. - Support --with-tls in configure. gcc/config.gcc | 15 ++++++- 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 | 8 ++++ gcc/config/loongarch/loongarch.md | 36 +++++++++++++++ gcc/config/loongarch/loongarch.opt | 14 ++++++ 8 files changed, 130 insertions(+), 11 deletions(-) diff --git a/gcc/config.gcc b/gcc/config.gcc index a0f9c672308..72a5e992821 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -2546,6 +2546,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*) @@ -4987,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 \ @@ -5245,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 02f918053f5..2cc943ef683 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(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 586e67e65ee..a08ab6fac10 100644 --- a/gcc/config/loongarch/loongarch-opts.h +++ b/gcc/config/loongarch/loongarch-opts.h @@ -134,4 +134,10 @@ struct loongarch_flags { #define HAVE_AS_TLS_LE_RELAXATION 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 1fdfda9af01..6b417a3c371 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 0428b6e65d5..b4e43f1d037 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -2030,6 +2030,9 @@ loongarch_symbol_insns (enum loongarch_symbol_type type, machine_mode mode) case SYMBOL_TLSLDM: return 3; + case SYMBOL_TLS_DESC: + return 4; /* pcalau12i, addi.d, ld.d, jirl. */ + case SYMBOL_PCREL64: return 5; @@ -2930,24 +2933,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 8b453ab3140..262d3488120 100644 --- a/gcc/config/loongarch/loongarch.h +++ b/gcc/config/loongarch/loongarch.h @@ -25,6 +25,14 @@ along with GCC; see the file COPYING3. If not see #define TARGET_SUPPORTS_WIDE_INT 1 +/* Support for configure-time default option. The rules are: + --with-tls is ignored if -mtls-dialect is specified. */ +#define OPTION_DEFAULT_SPECS \ + {"tls", "%{!mtls-dialect=*:-mtls-dialect=%(VALUE)}"}, \ + +/* Check TLS Descriptors mechanism is selected. */ +#define TARGET_TLS_DESC (loongarch_tls_dialect == TLS_DESCRIPTORS) + /* 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 dffa41b0bf5..f525c45a398 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -52,6 +52,11 @@ (define_c_enum "unspec" [ ;; TLS UNSPEC_TLS + UNSPEC_TLS_GD + UNSPEC_TLS_LD + UNSPEC_TLS_LE + UNSPEC_TLS_IE + UNSPEC_TLS_DESC ;; Stack tie UNSPEC_TIE @@ -123,10 +128,21 @@ (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) + (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 +2776,26 @@ (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 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 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 "@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..04846ae86c0 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(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. + mfrecipe Target Mask(ISA_FRECIPE) Var(la_isa_evolution) Support frecipe.{s/d} and frsqrte.{s/d} instructions. -- 2.36.0