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
This commit is contained in:
parent
70e41a6a27
commit
ccdc216414
10 changed files with 204 additions and 27 deletions
|
@ -1,3 +1,24 @@
|
|||
2011-06-22 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* 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 <nicola.pero@meta-innovation.com>
|
||||
|
||||
* attribs.c (register_attribute): Added assert to check that all
|
||||
|
|
|
@ -68,4 +68,9 @@ enum arm_tp_type {
|
|||
TP_CP15
|
||||
};
|
||||
|
||||
/* Which TLS scheme to use. */
|
||||
enum arm_tls_type {
|
||||
TLS_GNU,
|
||||
TLS_GNU2
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -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)
|
||||
else
|
||||
emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
|
||||
else /* TARGET_THUMB1 */
|
||||
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);
|
||||
if (TARGET_GNU2_TLS)
|
||||
{
|
||||
reg = arm_tls_descseq_addr (x, reg);
|
||||
|
||||
/* 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));
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2011-06-22 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* gcc.target/arm/tlscall.c: New.
|
||||
|
||||
2011-06-21 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/49172
|
||||
|
|
31
gcc/testsuite/gcc.target/arm/tlscall.c
Normal file
31
gcc/testsuite/gcc.target/arm/tlscall.c
Normal file
|
@ -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) {}
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue