From ccdc216414a902642b358b80f9aaa14bb7ce192b Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Wed, 22 Jun 2011 09:57:02 +0000 Subject: [PATCH] invoke.texi (ARM Options): Document -mtls-dialect option. * doc/invoke.texi (ARM Options): Document -mtls-dialect option. * doc/install.texi (Configuration): Document --with-tls. * config.gcc (arm*-*-linux*): Default to gnu tls. (arm*-*-*): Add --with-tls option. (all_defaults): Add 'tls'. * config/arm/arm.c (enum tls_reloc): Add TLS_DESCSEQ. (arm_call_tls_get_addr): Clean up. Assert not tls descriptor. (arm_tls_descseq_addr): New. (legitimize_tls_address): Add tlsdesc support. (arm_cannot_copy_insn_p): Check for tlscall. (arm_emit_tls_decoration): Likewise. * config/arm/arm.h (TARGET_GNU2_TLS): New. (OPTION_DEFAULT_SPECS): Add with-tls support. * config/arm/arm.md (R1_REGNUM): Define. (tlscall): New. * config/arm/arm.opt (tls_type): New enumeration type and values. (mtls-dialect): New switch. * config/arm/arm-opts.h (enum tls_type): New. testsuite/ * gcc.target/arm/tlscall.c: New. From-SVN: r175287 --- gcc/ChangeLog | 21 +++++ gcc/config/arm/arm-opts.h | 5 ++ gcc/config/arm/arm.c | 107 +++++++++++++++++++------ gcc/config/arm/arm.h | 7 +- gcc/config/arm/arm.md | 22 +++++ gcc/config/arm/arm.opt | 14 ++++ gcc/doc/install.texi | 6 ++ gcc/doc/invoke.texi | 14 +++- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gcc.target/arm/tlscall.c | 31 +++++++ 10 files changed, 204 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/tlscall.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa89cdda46e..83c9b1021be 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2011-06-22 Nathan Sidwell + + * doc/invoke.texi (ARM Options): Document -mtls-dialect option. + * doc/install.texi (Configuration): Document --with-tls. + * config.gcc (arm*-*-linux*): Default to gnu tls. + (arm*-*-*): Add --with-tls option. + (all_defaults): Add 'tls'. + * config/arm/arm.c (enum tls_reloc): Add TLS_DESCSEQ. + (arm_call_tls_get_addr): Clean up. Assert not tls descriptor. + (arm_tls_descseq_addr): New. + (legitimize_tls_address): Add tlsdesc support. + (arm_cannot_copy_insn_p): Check for tlscall. + (arm_emit_tls_decoration): Likewise. + * config/arm/arm.h (TARGET_GNU2_TLS): New. + (OPTION_DEFAULT_SPECS): Add with-tls support. + * config/arm/arm.md (R1_REGNUM): Define. + (tlscall): New. + * config/arm/arm.opt (tls_type): New enumeration type and values. + (mtls-dialect): New switch. + * config/arm/arm-opts.h (enum tls_type): New. + 2011-06-21 Nicola Pero * attribs.c (register_attribute): Added assert to check that all diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h index c35224eaf5c..6e604db3f45 100644 --- a/gcc/config/arm/arm-opts.h +++ b/gcc/config/arm/arm-opts.h @@ -68,4 +68,9 @@ enum arm_tp_type { TP_CP15 }; +/* Which TLS scheme to use. */ +enum arm_tls_type { + TLS_GNU, + TLS_GNU2 +}; #endif diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 547acc8f926..88e3b623562 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1009,7 +1009,8 @@ enum tls_reloc { TLS_LDM32, TLS_LDO32, TLS_IE32, - TLS_LE32 + TLS_LE32, + TLS_DESCSEQ /* GNU scheme */ }; /* The maximum number of insns to be used when loading a constant. */ @@ -5881,6 +5882,7 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc) { rtx insns, label, labelno, sum; + gcc_assert (reloc != TLS_DESCSEQ); start_sequence (); labelno = GEN_INT (pic_labelno++); @@ -5895,20 +5897,42 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc) if (TARGET_ARM) emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno)); - else if (TARGET_THUMB2) - emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno)); - else /* TARGET_THUMB1 */ + else emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno)); - - *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, LCT_PURE, /* LCT_CONST? */ + + *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, + LCT_PURE, /* LCT_CONST? */ Pmode, 1, reg, Pmode); - + insns = get_insns (); end_sequence (); return insns; } +static rtx +arm_tls_descseq_addr (rtx x, rtx reg) +{ + rtx labelno = GEN_INT (pic_labelno++); + rtx label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL); + rtx sum = gen_rtx_UNSPEC (Pmode, + gen_rtvec (4, x, GEN_INT (TLS_DESCSEQ), + gen_rtx_CONST (VOIDmode, label), + GEN_INT (!TARGET_ARM)), + UNSPEC_TLS); + rtx reg0 = load_tls_operand (sum, gen_rtx_REG (SImode, 0)); + + emit_insn (gen_tlscall (x, labelno)); + if (!reg) + reg = gen_reg_rtx (SImode); + else + gcc_assert (REGNO (reg) != 0); + + emit_move_insn (reg, reg0); + + return reg; +} + rtx legitimize_tls_address (rtx x, rtx reg) { @@ -5918,26 +5942,51 @@ legitimize_tls_address (rtx x, rtx reg) switch (model) { case TLS_MODEL_GLOBAL_DYNAMIC: - insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32); - dest = gen_reg_rtx (Pmode); - emit_libcall_block (insns, dest, ret, x); + if (TARGET_GNU2_TLS) + { + reg = arm_tls_descseq_addr (x, reg); + + tp = arm_load_tp (NULL_RTX); + + dest = gen_rtx_PLUS (Pmode, tp, reg); + } + else + { + /* Original scheme */ + insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32); + dest = gen_reg_rtx (Pmode); + emit_libcall_block (insns, dest, ret, x); + } return dest; case TLS_MODEL_LOCAL_DYNAMIC: - insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32); - - /* Attach a unique REG_EQUIV, to allow the RTL optimizers to - share the LDM result with other LD model accesses. */ - eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx), - UNSPEC_TLS); - dest = gen_reg_rtx (Pmode); - emit_libcall_block (insns, dest, ret, eqv); + if (TARGET_GNU2_TLS) + { + reg = arm_tls_descseq_addr (x, reg); - /* Load the addend. */ - addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LDO32)), - UNSPEC_TLS); - addend = force_reg (SImode, gen_rtx_CONST (SImode, addend)); - return gen_rtx_PLUS (Pmode, dest, addend); + tp = arm_load_tp (NULL_RTX); + + dest = gen_rtx_PLUS (Pmode, tp, reg); + } + else + { + insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32); + + /* Attach a unique REG_EQUIV, to allow the RTL optimizers to + share the LDM result with other LD model accesses. */ + eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx), + UNSPEC_TLS); + dest = gen_reg_rtx (Pmode); + emit_libcall_block (insns, dest, ret, eqv); + + /* Load the addend. */ + addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, + GEN_INT (TLS_LDO32)), + UNSPEC_TLS); + addend = force_reg (SImode, gen_rtx_CONST (SImode, addend)); + dest = gen_rtx_PLUS (Pmode, dest, addend); + } + return dest; case TLS_MODEL_INITIAL_EXEC: labelno = GEN_INT (pic_labelno++); @@ -9384,6 +9433,11 @@ arm_note_pic_base (rtx *x, void *date ATTRIBUTE_UNUSED) static bool arm_cannot_copy_insn_p (rtx insn) { + /* The tls call insn cannot be copied, as it is paired with a data + word. */ + if (recog_memoized (insn) == CODE_FOR_tlscall) + return true; + return for_each_rtx (&PATTERN (insn), arm_note_pic_base, NULL); } @@ -22912,6 +22966,9 @@ arm_emit_tls_decoration (FILE *fp, rtx x) case TLS_LE32: fputs ("(tpoff)", fp); break; + case TLS_DESCSEQ: + fputs ("(tlsdesc)", fp); + break; default: gcc_unreachable (); } @@ -22921,9 +22978,11 @@ arm_emit_tls_decoration (FILE *fp, rtx x) case TLS_GD32: case TLS_LDM32: case TLS_IE32: + case TLS_DESCSEQ: fputs (" + (. - ", fp); output_addr_const (fp, XVECEXP (x, 0, 2)); - fputs (" - ", fp); + /* For DESCSEQ the 3rd operand encodes thumbness, and is added */ + fputs (reloc == TLS_DESCSEQ ? " + " : " - ", fp); output_addr_const (fp, XVECEXP (x, 0, 3)); fputc (')', fp); break; diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index c32ef1ad030..f030f418b8a 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -220,6 +220,7 @@ extern void (*arm_lang_output_object_attributes_hook)(void); #define TARGET_HARD_TP (target_thread_pointer == TP_CP15) #define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT) +#define TARGET_GNU2_TLS (target_tls_dialect == TLS_GNU2) /* Only 16-bit thumb code. */ #define TARGET_THUMB1 (TARGET_THUMB && !arm_arch_thumb2) @@ -313,7 +314,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void); by -march). --with-float is ignored if -mfloat-abi is specified. --with-fpu is ignored if -mfpu is specified. - --with-abi is ignored is -mabi is specified. */ + --with-abi is ignored if -mabi is specified. + --with-tls is ignored if -mtls-dialect is specified. */ #define OPTION_DEFAULT_SPECS \ {"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \ {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \ @@ -321,7 +323,8 @@ extern void (*arm_lang_output_object_attributes_hook)(void); {"float", "%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}" }, \ {"fpu", "%{!mfpu=*:-mfpu=%(VALUE)}"}, \ {"abi", "%{!mabi=*:-mabi=%(VALUE)}"}, \ - {"mode", "%{!marm:%{!mthumb:-m%(VALUE)}}"}, + {"mode", "%{!marm:%{!mthumb:-m%(VALUE)}}"}, \ + {"tls", "%{!mtls-dialect:-mtls-dialect=%(VALUE)}"}, /* Which floating point model to use. */ enum arm_fp_model diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 70f703c3e7b..431208ef7d2 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -31,6 +31,7 @@ ;; Register numbers (define_constants [(R0_REGNUM 0) ; First CORE register + (R1_REGNUM 1) ; Second CORE register (IP_REGNUM 12) ; Scratch register (SP_REGNUM 13) ; Stack pointer (LR_REGNUM 14) ; Return address register @@ -10719,6 +10720,27 @@ [(set_attr "conds" "clob")] ) +;; tls descriptor call +(define_insn "tlscall" + [(set (reg:SI R0_REGNUM) + (unspec:SI [(reg:SI R0_REGNUM) + (match_operand:SI 0 "" "X") + (match_operand 1 "" "")] UNSPEC_TLS)) + (clobber (reg:SI R1_REGNUM)) + (clobber (reg:SI LR_REGNUM)) + (clobber (reg:SI CC_REGNUM))] + "TARGET_GNU2_TLS" + { + targetm.asm_out.internal_label (asm_out_file, "LPIC", + INTVAL (operands[1])); + return "bl\\t%c0(tlscall)"; + } + [(set_attr "conds" "clob") + (set_attr "length" "4")] +) + +;; + ;; We only care about the lower 16 bits of the constant ;; being inserted into the upper 16 bits of the register. (define_insn "*arm_movtas_ze" diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt index c45bc774bdc..48a5cb346f7 100644 --- a/gcc/config/arm/arm.opt +++ b/gcc/config/arm/arm.opt @@ -21,6 +21,16 @@ HeaderInclude config/arm/arm-opts.h +Enum +Name(tls_type) Type(enum arm_tls_type) +TLS dialect to use: + +EnumValue +Enum(tls_type) String(gnu) Value(TLS_GNU) + +EnumValue +Enum(tls_type) String(gnu2) Value(TLS_GNU2) + mabi= Target RejectNegative Joined Enum(arm_abi_type) Var(arm_abi) Init(ARM_DEFAULT_ABI) Specify an ABI @@ -190,6 +200,10 @@ mthumb-interwork Target Report Mask(INTERWORK) Support calls between Thumb and ARM instruction sets +mtls-dialect= +Target RejectNegative Joined Enum(tls_type) Var(target_tls_dialect) Init(TLS_GNU) +Specify thread local storage scheme + mtp= Target RejectNegative Joined Enum(arm_tp_type) Var(target_thread_pointer) Init(TP_AUTO) Specify how to access the thread pointer diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 7ebcd924b3e..a4a1b04519c 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -1016,6 +1016,12 @@ information normally used on 386 SVR4 platforms; stabs provide a workable alternative. This requires gas and gdb, as the normal SVR4 tools can not generate or interpret stabs. +@item --with-tls=@var{dialect} +Specify the default TLS dialect, for systems were there is a choice. +For ARM targets, possible values for @var{dialect} are @code{gnu} or +@code{gnu2}, which select between the original GNU dialect and the GNU TLS +descriptor-based dialect. + @item --disable-multilib Specify that multiple target libraries to support different target variants, calling diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index e747f1d7841..d397d607f1c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -477,7 +477,7 @@ Objective-C and Objective-C++ Dialects}. -mthumb -marm @gol -mtpcs-frame -mtpcs-leaf-frame @gol -mcaller-super-interworking -mcallee-super-interworking @gol --mtp=@var{name} @gol +-mtp=@var{name} -mtls-dialect=@var{dialect} @gol -mword-relocations @gol -mfix-cortex-m3-ldrd} @@ -10471,6 +10471,18 @@ models are @option{soft}, which generates calls to @code{__aeabi_read_tp}, best available method for the selected processor. The default setting is @option{auto}. +@item -mtls-dialect=@var{dialect} +@opindex mtls-dialect +Specify the dialect to use for accessing thread local storage. Two +dialects are supported --- @option{gnu} and @option{gnu2}. The +@option{gnu} dialect selects the original GNU scheme for supporting +local and global dynamic TLS models. The @option{gnu2} dialect +selects the GNU descriptor scheme, which provides better performance +for shared libraries. The GNU descriptor scheme is compatible with +the original scheme, but does require new assembler, linker and +library support. Initial and local exec TLS models are unaffected by +this option and always use the original scheme. + @item -mword-relocations @opindex mword-relocations Only generate absolute relocations on word sized values (i.e. R_ARM_ABS32). diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 413548e4774..883d355903d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2011-06-22 Nathan Sidwell + + * gcc.target/arm/tlscall.c: New. + 2011-06-21 Jason Merrill PR c++/49172 diff --git a/gcc/testsuite/gcc.target/arm/tlscall.c b/gcc/testsuite/gcc.target/arm/tlscall.c new file mode 100644 index 00000000000..366c1ae7123 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/tlscall.c @@ -0,0 +1,31 @@ +/* Test non-duplication of tlscall insn */ + +/* { dg-do assemble } */ +/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */ + +typedef struct _IO_FILE FILE; + +extern int foo(void); +extern int bar(void); + +void uuid__generate_time() +{ + static int has_init = 0; + static __thread int state_fd = -2; + static __thread FILE *state_f; + + if (!has_init) { + foo(); + has_init = 1; + } + + if (state_fd == -2) { + if (!state_f) { + state_fd = -1; + } + } + if (state_fd >= 0) { + while (bar() < 0) {} + } + +} -- 2.30.2