summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog21
-rw-r--r--gcc/config/arm/arm-opts.h5
-rw-r--r--gcc/config/arm/arm.c107
-rw-r--r--gcc/config/arm/arm.h7
-rw-r--r--gcc/config/arm/arm.md22
-rw-r--r--gcc/config/arm/arm.opt14
-rw-r--r--gcc/doc/install.texi6
-rw-r--r--gcc/doc/invoke.texi14
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.target/arm/tlscall.c31
10 files changed, 204 insertions, 27 deletions
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 <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
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 <nathan@codesourcery.com>
+
+ * gcc.target/arm/tlscall.c: New.
+
2011-06-21 Jason Merrill <jason@redhat.com>
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) {}
+ }
+
+}
OpenPOWER on IntegriCloud