Message ID | 20110728025508.GA9511@intel.com |
---|---|
State | New |
Headers | show |
On Thu, Jul 28, 2011 at 4:55 AM, H.J. Lu <hongjiu.lu@intel.com> wrote: > TLS on X32 is almost identical to TLS on x86-64. The only difference is > x32 address space is 32bit. That means TLS symbols can be in either > SImode or DImode with upper 32bit zero. This patch updates > tls_global_dynamic_64 to support x32. OK for trunk? > 2011-07-27 H.J. Lu <hongjiu.lu@intel.com> > > PR target/47715 > * config/i386/i386.md (PTR64): New. > (*tls_global_dynamic_64): Rename to ... > (*tls_global_dynamic_64_<mode>): This. Put PTR64 on operand 1. > (tls_global_dynamic_64): Rename to ... > (tls_global_dynamic_64_<mode>): This. Put PTR64 on operand 1. > * config/i386/i386.c (legitimize_tls_address): Updated. Just remove mode check, so: (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")] at both sites. - fputs (ASM_BYTE "0x66\n", asm_out_file); + if (!TARGET_X32) + fputs (ASM_BYTE "0x66\n", asm_out_file); Are you sure? There are some scary comments in binutils that these sequences have to be written _exactly_ as shown to enable certain linker relaxations w.r.t. TLS relocs. Uros.
On Wed, Jul 27, 2011 at 11:52 PM, Uros Bizjak <ubizjak@gmail.com> wrote: > On Thu, Jul 28, 2011 at 4:55 AM, H.J. Lu <hongjiu.lu@intel.com> wrote: >> TLS on X32 is almost identical to TLS on x86-64. The only difference is >> x32 address space is 32bit. That means TLS symbols can be in either >> SImode or DImode with upper 32bit zero. This patch updates >> tls_global_dynamic_64 to support x32. OK for trunk? > >> 2011-07-27 H.J. Lu <hongjiu.lu@intel.com> >> >> PR target/47715 >> * config/i386/i386.md (PTR64): New. >> (*tls_global_dynamic_64): Rename to ... >> (*tls_global_dynamic_64_<mode>): This. Put PTR64 on operand 1. >> (tls_global_dynamic_64): Rename to ... >> (tls_global_dynamic_64_<mode>): This. Put PTR64 on operand 1. >> * config/i386/i386.c (legitimize_tls_address): Updated. > > Just remove mode check, so: > > (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")] > > at both sites. > > - fputs (ASM_BYTE "0x66\n", asm_out_file); > + if (!TARGET_X32) > + fputs (ASM_BYTE "0x66\n", asm_out_file); > > Are you sure? There are some scary comments in binutils that these > sequences have to be written _exactly_ as shown to enable certain > linker relaxations w.r.t. TLS relocs. That is true. I updated those scary comments in binutils for x32 :-). Since x32 is 32bit, we can use 32bit move instructions instead 64bit. We don't need REX prefix in x32. Now those scary comments read: /* Check transition from GD access model. For 64bit, only .byte 0x66; leaq foo@tlsgd(%rip), %rdi .word 0x6666; rex64; call __tls_get_addr can transit to different access model. For 32bit, only leaq foo@tlsgd(%rip), %rdi .word 0x6666; rex64; call __tls_get_addr can transit to different access model. */ The difference is one less 0x66 byte.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 8723dc5..31d5b8e 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -12215,9 +12215,22 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov) if (TARGET_64BIT) { rtx rax = gen_rtx_REG (Pmode, AX_REG), insns; + rtx (*tls_global_dynamic) (rtx, rtx, rtx); + + switch (GET_MODE (x)) + { + case SImode: + tls_global_dynamic = gen_tls_global_dynamic_64_si; + break; + case DImode: + tls_global_dynamic = gen_tls_global_dynamic_64_di; + break; + default: + gcc_unreachable (); + } start_sequence (); - emit_call_insn (gen_tls_global_dynamic_64 (rax, x, caddr)); + emit_call_insn (tls_global_dynamic (rax, x, caddr)); insns = get_insns (); end_sequence (); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index e91a299..06d65fc 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -951,6 +951,9 @@ ;; This mode iterator allows :P to be used for patterns that operate on ;; pointer-sized quantities. Exactly one of the two alternatives will match. (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) + +;; Pointer modes in 64bit. +(define_mode_iterator PTR64 [(SI "TARGET_X32") DI]) ;; Scheduling descriptions @@ -12322,16 +12325,17 @@ (clobber (match_scratch:SI 5 "")) (clobber (reg:CC FLAGS_REG))])]) -(define_insn "*tls_global_dynamic_64" +(define_insn "*tls_global_dynamic_64_<mode>" [(set (match_operand:DI 0 "register_operand" "=a") (call:DI (mem:QI (match_operand:DI 2 "constant_call_address_operand" "z")) (match_operand:DI 3 "" ""))) - (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + (unspec:DI [(match_operand:PTR64 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)] "TARGET_64BIT" { - fputs (ASM_BYTE "0x66\n", asm_out_file); + if (!TARGET_X32) + fputs (ASM_BYTE "0x66\n", asm_out_file); output_asm_insn ("lea{q}\t{%a1@tlsgd(%%rip), %%rdi|rdi, %a1@tlsgd[rip]}", operands); fputs (ASM_SHORT "0x6666\n", asm_out_file); @@ -12343,13 +12347,13 @@ [(set_attr "type" "multi") (set_attr "length" "16")]) -(define_expand "tls_global_dynamic_64" +(define_expand "tls_global_dynamic_64_<mode>" [(parallel [(set (match_operand:DI 0 "register_operand" "") (call:DI (mem:QI (match_operand:DI 2 "constant_call_address_operand" "")) (const_int 0))) - (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + (unspec:DI [(match_operand:PTR64 1 "tls_symbolic_operand" "")] UNSPEC_TLS_GD)])]) (define_insn "*tls_local_dynamic_base_32_gnu"