+2011-05-11 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (legitimize_tls_address)
+ <TLS_MODEL_GLOBAL_DYNAMIC>: Call gen_tls_dynamic_gnu2_{32,64}
+ expanders directly for TARGET_GNU2_TLS. Determine pic and
+ __tls_get_addr symbol reference here. Update call to
+ gen_tls_global_dynamic_{32,64} for added arguments.
+ <TLS_MODEL_LOCAL_DYNAMIC>: Call gen_tls_dynamic_gnu2_{32,64}
+ expanders directly for TARGET_GNU2_TLS. Determine
+ __tls_get_addr symbol reference here. Update call to
+ gen_tls_local_dynamic_base_{32,64} for added arguments. Attach
+ unique UNSPEC REG_EQUIV to libcall block.
+ (ix86_tls_get_addr): Declare static.
+ * config/i386/i386-protos.h (ix86_tls_get_addr): Remove declaration.
+ * config/i386/i386.md (tls_global_dynamic_32): Add operand 2 and 3.
+ Do not determine pic and __tls_get_addr symbol reference here. Do not
+ call gen_tls_dynamic_gnu2_32 for TARGET_GNU2_TLS.
+ (tls_local_dynamic_base_32): Ditto for operands 1 and 2.
+ (tls_global_dynamic_64): Add operand 2. Do not determine
+ __tls_get_addr symbol reference here. Do not call
+ gen_tls_dynamic_gnu2_64 for TARGET_GNU2_TLS here.
+ (tls_local_dynamic_base64): Ditto for operand 1.
+
2011-05-11 Eric Botcazou <ebotcazou@adacore.com>
* function.c (expand_function_start): Initialize stack_check_probe_note
2011-05-11 Nathan Froyd <froydnj@codesourcery.com>
- * ggc-page.c (extra_order_size_table): Use struct
- tree_type_non_common.
+ * ggc-page.c (extra_order_size_table): Use struct tree_type_non_common.
* lto-streamer-in.c (unpack_ts_type_value_fields): Rename to...
(unpack_ts_type_common_value_fields): ...this. Update comment.
(unpack_value_fields): Adjust for renaming.
2011-05-11 Joseph Myers <joseph@codesourcery.com>
- * opts.c (finish_options): Move warning settings from
- process_options.
- * toplev.c (process_options): Move warning settings to
- finish_options.
+ * opts.c (finish_options): Move warning settings from process_options.
+ * toplev.c (process_options): Move warning settings to finish_options.
2011-05-11 Richard Guenther <rguenther@suse.de>
2011-05-10 Joseph Myers <joseph@codesourcery.com>
- * config/rs6000/genopt.sh, config/rs6000/rs6000-cpus.def: New
- files.
+ * config/rs6000/genopt.sh, config/rs6000/rs6000-cpus.def: New files.
* config/rs6000/rs6000-tables.opt: New file (generated).
* config.gcc (powerpc*-*-*, rs6000*-*-*): Add
rs6000/rs6000-tables.opt to extra_options.
* config.gcc (libgcc_tm_file): Define instead of including files
from ../../libgcc/config/ in tm_file.
- * configure.ac (libgcc_tm_file_list, libgcc_tm_include_list):
- Define.
+ * configure.ac (libgcc_tm_file_list, libgcc_tm_include_list): Define.
* configure: Regenerate.
* Makefile.in (libgcc_tm_file_list, libgcc_tm_include_list,
libgcc_tm.h, cs-libgcc_tm.h): New.
/* Load the thread pointer. If TO_REG is true, force it into a register. */
static rtx
-get_thread_pointer (int to_reg)
+get_thread_pointer (bool to_reg)
{
rtx tp, reg, insn;
return reg;
}
+/* Construct the SYMBOL_REF for the tls_get_addr function. */
+
+static GTY(()) rtx ix86_tls_symbol;
+
+static rtx
+ix86_tls_get_addr (void)
+{
+ if (!ix86_tls_symbol)
+ {
+ const char *sym
+ = ((TARGET_ANY_GNU_TLS && !TARGET_64BIT)
+ ? "___tls_get_addr" : "__tls_get_addr");
+
+ ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, sym);
+ }
+
+ return ix86_tls_symbol;
+}
+
+/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */
+
+static GTY(()) rtx ix86_tls_module_base_symbol;
+
+rtx
+ix86_tls_module_base (void)
+{
+ if (!ix86_tls_module_base_symbol)
+ {
+ ix86_tls_module_base_symbol
+ = gen_rtx_SYMBOL_REF (Pmode, "_TLS_MODULE_BASE_");
+
+ SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
+ |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
+ }
+
+ return ix86_tls_module_base_symbol;
+}
+
/* A subroutine of ix86_legitimize_address and ix86_expand_move. FOR_MOV is
false if we expect this to be used for a memory address and true if
we expect to load the address into a register. */
static rtx
-legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
+legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
{
- rtx dest, base, off, pic, tp;
+ rtx dest, base, off;
+ rtx pic = NULL_RTX, tp = NULL_RTX;
int type;
switch (model)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
dest = gen_reg_rtx (Pmode);
- tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
- if (TARGET_64BIT && ! TARGET_GNU2_TLS)
+ if (!TARGET_64BIT)
{
- rtx rax = gen_rtx_REG (Pmode, AX_REG), insns;
-
- start_sequence ();
- emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
- insns = get_insns ();
- end_sequence ();
-
- RTL_CONST_CALL_P (insns) = 1;
- emit_libcall_block (insns, dest, rax, x);
+ if (flag_pic)
+ pic = pic_offset_table_rtx;
+ else
+ {
+ pic = gen_reg_rtx (Pmode);
+ emit_insn (gen_set_got (pic));
+ }
}
- else if (TARGET_64BIT && TARGET_GNU2_TLS)
- emit_insn (gen_tls_global_dynamic_64 (dest, x));
- else
- emit_insn (gen_tls_global_dynamic_32 (dest, x));
if (TARGET_GNU2_TLS)
{
+ if (TARGET_64BIT)
+ emit_insn (gen_tls_dynamic_gnu2_64 (dest, x));
+ else
+ emit_insn (gen_tls_dynamic_gnu2_32 (dest, x, pic));
+
+ tp = get_thread_pointer (true);
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
}
+ else
+ {
+ rtx caddr = ix86_tls_get_addr ();
+
+ if (TARGET_64BIT)
+ {
+ rtx rax = gen_rtx_REG (Pmode, AX_REG), insns;
+
+ start_sequence ();
+ emit_call_insn (gen_tls_global_dynamic_64 (rax, x, caddr));
+ insns = get_insns ();
+ end_sequence ();
+
+ RTL_CONST_CALL_P (insns) = 1;
+ emit_libcall_block (insns, dest, rax, x);
+ }
+ else
+ emit_insn (gen_tls_global_dynamic_32 (dest, x, pic, caddr));
+ }
break;
case TLS_MODEL_LOCAL_DYNAMIC:
base = gen_reg_rtx (Pmode);
- tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
- if (TARGET_64BIT && ! TARGET_GNU2_TLS)
+ if (!TARGET_64BIT)
{
- rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, note;
-
- start_sequence ();
- emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
- insns = get_insns ();
- end_sequence ();
-
- note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
- note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
- RTL_CONST_CALL_P (insns) = 1;
- emit_libcall_block (insns, base, rax, note);
+ if (flag_pic)
+ pic = pic_offset_table_rtx;
+ else
+ {
+ pic = gen_reg_rtx (Pmode);
+ emit_insn (gen_set_got (pic));
+ }
}
- else if (TARGET_64BIT && TARGET_GNU2_TLS)
- emit_insn (gen_tls_local_dynamic_base_64 (base));
- else
- emit_insn (gen_tls_local_dynamic_base_32 (base));
if (TARGET_GNU2_TLS)
{
- rtx x = ix86_tls_module_base ();
+ rtx tmp = ix86_tls_module_base ();
+ if (TARGET_64BIT)
+ emit_insn (gen_tls_dynamic_gnu2_64 (base, tmp));
+ else
+ emit_insn (gen_tls_dynamic_gnu2_32 (base, tmp, pic));
+
+ tp = get_thread_pointer (true);
set_unique_reg_note (get_last_insn (), REG_EQUIV,
- gen_rtx_MINUS (Pmode, x, tp));
+ gen_rtx_MINUS (Pmode, tmp, tp));
+ }
+ else
+ {
+ rtx caddr = ix86_tls_get_addr ();
+
+ if (TARGET_64BIT)
+ {
+ rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, eqv;
+
+ start_sequence ();
+ emit_call_insn (gen_tls_local_dynamic_base_64 (rax, caddr));
+ insns = get_insns ();
+ end_sequence ();
+
+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+ share the LD_BASE result with other LD model accesses. */
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_TLS_LD_BASE);
+
+ RTL_CONST_CALL_P (insns) = 1;
+ emit_libcall_block (insns, base, rax, eqv);
+ }
+ else
+ emit_insn (gen_tls_local_dynamic_base_32 (base, pic, caddr));
}
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
}
-
break;
case TLS_MODEL_INITIAL_EXEC:
ix86_stack_locals = s;
return s->rtl;
}
-
-/* Construct the SYMBOL_REF for the tls_get_addr function. */
-
-static GTY(()) rtx ix86_tls_symbol;
-rtx
-ix86_tls_get_addr (void)
-{
-
- if (!ix86_tls_symbol)
- {
- ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
- (TARGET_ANY_GNU_TLS
- && !TARGET_64BIT)
- ? "___tls_get_addr"
- : "__tls_get_addr");
- }
-
- return ix86_tls_symbol;
-}
-
-/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */
-
-static GTY(()) rtx ix86_tls_module_base_symbol;
-rtx
-ix86_tls_module_base (void)
-{
-
- if (!ix86_tls_module_base_symbol)
- {
- ix86_tls_module_base_symbol = gen_rtx_SYMBOL_REF (Pmode,
- "_TLS_MODULE_BASE_");
- SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
- |= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
- }
-
- return ix86_tls_module_base_symbol;
-}
\f
/* Calculate the length of the memory address in the instruction
encoding. Does not include the one-byte modrm, opcode, or prefix. */
(define_expand "tls_global_dynamic_32"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(unspec:SI
- [(match_dup 2)
+ [(match_operand:SI 2 "register_operand" "")
(match_operand:SI 1 "tls_symbolic_operand" "")
- (match_dup 3)]
+ (match_operand:SI 3 "call_insn_operand" "")]
UNSPEC_TLS_GD))
(clobber (match_scratch:SI 4 ""))
(clobber (match_scratch:SI 5 ""))
- (clobber (reg:CC FLAGS_REG))])]
- ""
-{
- if (flag_pic)
- operands[2] = pic_offset_table_rtx;
- else
- {
- operands[2] = gen_reg_rtx (Pmode);
- emit_insn (gen_set_got (operands[2]));
- }
- if (TARGET_GNU2_TLS)
- {
- emit_insn (gen_tls_dynamic_gnu2_32
- (operands[0], operands[1], operands[2]));
- DONE;
- }
- operands[3] = ix86_tls_get_addr ();
-})
+ (clobber (reg:CC FLAGS_REG))])])
(define_insn "*tls_global_dynamic_64"
[(set (match_operand:DI 0 "register_operand" "=a")
(define_expand "tls_global_dynamic_64"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (call:DI (mem:QI (match_dup 2)) (const_int 0)))
+ (call:DI
+ (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
+ (const_int 0)))
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
- UNSPEC_TLS_GD)])]
- ""
-{
- if (TARGET_GNU2_TLS)
- {
- emit_insn (gen_tls_dynamic_gnu2_64
- (operands[0], operands[1]));
- DONE;
- }
- operands[2] = ix86_tls_get_addr ();
-})
+ UNSPEC_TLS_GD)])])
(define_insn "*tls_local_dynamic_base_32_gnu"
[(set (match_operand:SI 0 "register_operand" "=a")
(define_expand "tls_local_dynamic_base_32"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
- (unspec:SI [(match_dup 1) (match_dup 2)]
+ (unspec:SI [(match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "call_insn_operand" "")]
UNSPEC_TLS_LD_BASE))
(clobber (match_scratch:SI 3 ""))
(clobber (match_scratch:SI 4 ""))
- (clobber (reg:CC FLAGS_REG))])]
- ""
-{
- if (flag_pic)
- operands[1] = pic_offset_table_rtx;
- else
- {
- operands[1] = gen_reg_rtx (Pmode);
- emit_insn (gen_set_got (operands[1]));
- }
- if (TARGET_GNU2_TLS)
- {
- emit_insn (gen_tls_dynamic_gnu2_32
- (operands[0], ix86_tls_module_base (), operands[1]));
- DONE;
- }
- operands[2] = ix86_tls_get_addr ();
-})
+ (clobber (reg:CC FLAGS_REG))])])
(define_insn "*tls_local_dynamic_base_64"
[(set (match_operand:DI 0 "register_operand" "=a")
(define_expand "tls_local_dynamic_base_64"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
- (call:DI (mem:QI (match_dup 1)) (const_int 0)))
- (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
- ""
-{
- if (TARGET_GNU2_TLS)
- {
- emit_insn (gen_tls_dynamic_gnu2_64
- (operands[0], ix86_tls_module_base ()));
- DONE;
- }
- operands[1] = ix86_tls_get_addr ();
-})
+ (call:DI
+ (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
+ (const_int 0)))
+ (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])])
;; Local dynamic of a single variable is a lose. Show combine how
;; to convert that back to global dynamic.