From cb032feee848f70456b6265a5f7520371e719f35 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 11 May 2011 17:30:52 +0200 Subject: [PATCH] i386.c (legitimize_tls_address): Call gen_tls_dynamic_gnu2_{32,64} expanders directly for TARGET_GNU2_TLS. * config/i386/i386.c (legitimize_tls_address) : 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. : 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. From-SVN: r173662 --- gcc/ChangeLog | 38 +++++-- gcc/config/i386/i386-protos.h | 1 - gcc/config/i386/i386.c | 190 ++++++++++++++++++++-------------- gcc/config/i386/i386.md | 77 +++----------- 4 files changed, 157 insertions(+), 149 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6db1f29e8ae..8c799370220 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2011-05-11 Uros Bizjak + + * config/i386/i386.c (legitimize_tls_address) + : 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. + : 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 * function.c (expand_function_start): Initialize stack_check_probe_note @@ -13,8 +36,7 @@ 2011-05-11 Nathan Froyd - * 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. @@ -100,10 +122,8 @@ 2011-05-11 Joseph Myers - * 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 @@ -192,8 +212,7 @@ 2011-05-10 Joseph Myers - * 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. @@ -230,8 +249,7 @@ * 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. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index ccba8484bdc..a58c964475b 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -193,7 +193,6 @@ extern unsigned int ix86_get_callcvt (const_tree); #endif -extern rtx ix86_tls_get_addr (void); extern rtx ix86_tls_module_base (void); extern void ix86_expand_vector_init (bool, rtx, rtx); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index afba1a7049d..1cf8933e4df 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -12657,7 +12657,7 @@ legitimize_pic_address (rtx orig, rtx reg) /* 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; @@ -12672,76 +12672,154 @@ get_thread_pointer (int to_reg) 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); @@ -12755,7 +12833,6 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov) set_unique_reg_note (get_last_insn (), REG_EQUIV, x); } - break; case TLS_MODEL_INITIAL_EXEC: @@ -22166,43 +22243,6 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n) 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; -} /* Calculate the length of the memory address in the instruction encoding. Does not include the one-byte modrm, opcode, or prefix. */ diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index b1fc57314a2..028eafd3ee1 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -12555,30 +12555,13 @@ (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") @@ -12593,19 +12576,11 @@ (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") @@ -12622,28 +12597,12 @@ (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") @@ -12657,18 +12616,10 @@ (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. -- 2.30.2