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:
Nathan Sidwell 2011-06-22 09:57:02 +00:00 committed by Nathan Sidwell
parent 70e41a6a27
commit ccdc216414
10 changed files with 204 additions and 27 deletions

View file

@ -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

View file

@ -68,4 +68,9 @@ enum arm_tp_type {
TP_CP15
};
/* Which TLS scheme to use. */
enum arm_tls_type {
TLS_GNU,
TLS_GNU2
};
#endif

View file

@ -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;

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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).

View file

@ -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

View 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) {}
}
}