OSDN Git Service

* doc/invoke.texi (ARM Options): Document -mtls-dialect option.
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Jun 2011 09:57:02 +0000 (09:57 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 22 Jun 2011 09:57:02 +0000 (09:57 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175287 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/arm/arm-opts.h
gcc/config/arm/arm.c
gcc/config/arm/arm.h
gcc/config/arm/arm.md
gcc/config/arm/arm.opt
gcc/doc/install.texi
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/tlscall.c [new file with mode: 0644]

index aa89cdd..83c9b10 100644 (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
index c35224e..6e604db 100644 (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
index 547acc8..88e3b62 100644 (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)
-    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;
index c32ef1a..f030f41 100644 (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
index 70f703c..431208e 100644 (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
   [(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" 
index c45bc77..48a5cb3 100644 (file)
 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
index 7ebcd92..a4a1b04 100644 (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
index e747f1d..d397d60 100644 (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).
index 413548e..883d355 100644 (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
diff --git a/gcc/testsuite/gcc.target/arm/tlscall.c b/gcc/testsuite/gcc.target/arm/tlscall.c
new file mode 100644 (file)
index 0000000..366c1ae
--- /dev/null
@@ -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) {}
+ }
+
+}