Patchwork Fix 64-bit Solaris 2/x86 IE TLS code sequence (PR target/43309)

login
register
mail settings
Submitter Uros Bizjak
Date Dec. 20, 2010, 7:26 p.m.
Message ID <AANLkTi=2EXYi5YOfG6KBYWWc3v-gAk+jPd4qFcKst3pT@mail.gmail.com>
Download mbox | patch
Permalink /patch/76219/
State New
Headers show

Comments

Uros Bizjak - Dec. 20, 2010, 7:26 p.m.
On Mon, Dec 20, 2010 at 4:07 PM, Uros Bizjak <ubizjak@gmail.com> wrote:
> On Mon, Dec 20, 2010 at 1:02 PM, Rainer Orth
> <ro@cebitec.uni-bielefeld.de> wrote:
>> I've finally managed to fix PR target/43309, where Sun ld cannot handle
>> the 64-bit TLS IE code sequence emitted by gcc.
>>
>> The issue was discussed within the original patch submission
>>
>>        PATCH: Fix 64-bit Solaris 2/x86 IE TLS code sequence
>>        http://gcc.gnu.org/ml/gcc-patches/2010-02/msg00993.html
>>
>> and the PR.
>>
>> While the Solaris linker maintainers have meanwhile agreed that their
>> literal interpretation of the AMD64 TLS IE code sequence is too strict
>> and intend to relax that to accomodate the code GCC emits, for the time
>> being it is still necessary to work around the issue in GCC as below.
>>
>> Bootstrapped on i386-pc-solaris2.11 with Sun as and ld without
>> regressions, fixing all outstanding TLS IE testsuite failures.
>>
>> Ok for mainline now and 4.4/4.5 backports (slightly modified since they
>> lack define_c_enum) later?
>>
>> Thanks.
>>        Rainer
>>
>>
>> 2010-03-06  Uros Bizjak <ubizjak@gmail.com>
>>            Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
>>
>>        PR target/43309
>>        * config/i386/i386.c (legitimize_tls_address)
>>        <TLS_MODEL_INITIAL_EXEC>: Handle TARGET_64BIT && TARGET_SUN_TLS.
>>        * config/i386/i386.md (UNSPEC_TLS_IE_SUN): Declare.
>>        (*tls_initial_exec_64_sun): New pattern.
>>        (tls_initial_exec_64_sun): New expander.
>
> This can be handled without expander, by declaring named pattern only.

Rainer, what do you think about attached patch? This patch splits TLS
sequence into "movq" and "addq" insn, but decorates "add" insn with an
unspec to separate it from generic add insn.

Uros.
Richard Henderson - Dec. 20, 2010, 9:03 p.m.
On 12/20/2010 11:26 AM, Uros Bizjak wrote:
> +	  /* The SUN linker took the AMD64 TLS spec literally
> +	     and can only handle %rax as destination of the
> +	     initial executable code sequence.  */
> +
> +	  rtx rax = gen_rtx_REG (Pmode, AX_REG);

It's much better not to use an explicit hard register
and instead rely on the 'a' constraint in the pattern.


r~

Patch

Index: i386.c
===================================================================
--- i386.c	(revision 168050)
+++ i386.c	(working copy)
@@ -12571,7 +12571,23 @@  legitimize_tls_address (rtx x, enum tls_
       off = gen_const_mem (Pmode, off);
       set_mem_alias_set (off, ix86_GOT_alias_set ());
 
-      if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
+      if (TARGET_64BIT && TARGET_SUN_TLS)
+	{
+	  /* The SUN linker took the AMD64 TLS spec literally
+	     and can only handle %rax as destination of the
+	     initial executable code sequence.  */
+
+	  rtx rax = gen_rtx_REG (Pmode, AX_REG);
+
+	  base = get_thread_pointer (false);
+	  emit_insn (gen_rtx_SET (VOIDmode, rax, base));
+	  emit_insn (gen_add_tls_addr_di_sun (rax, rax, off));
+
+	  dest = gen_reg_rtx (Pmode);
+	  emit_move_insn (dest, rax);
+	  return dest;
+	}
+      else if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
 	{
           base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
 	  off = force_reg (Pmode, off);
Index: i386.md
===================================================================
--- i386.md	(revision 168050)
+++ i386.md	(working copy)
@@ -93,6 +93,7 @@ 
   UNSPEC_TLS_GD
   UNSPEC_TLS_LD_BASE
   UNSPEC_TLSDESC
+  UNSPEC_TLSDESC_SUN
 
   ;; Other random patterns
   UNSPEC_SCAS
@@ -12661,6 +12664,31 @@ 
 ;; Segment register for the thread base ptr load
 (define_mode_attr tp_seg [(SI "gs") (DI "fs")])
 
+;; The SUN linker took the AMD64 TLS spec literally and can only handle
+;; %rax as the destination of the initial executable code sequence.
+(define_insn "*load_tp_di_sun"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+	(unspec:DI [(const_int 0)] UNSPEC_TP))]
+  "TARGET_64BIT && TARGET_SUN_TLS"
+  "mov{q}\t{%%fs:0, %0|%0, QWORD PTR fs:0}"
+  [(set_attr "type" "imov")
+   (set_attr "modrm" "0")
+   (set_attr "length" "7")
+   (set_attr "memory" "load")
+   (set_attr "imm_disp" "false")])
+
+(define_insn "add_tls_addr_di_sun"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+  	(plus:DI
+	  (match_operand:DI 1 "register_operand" "0")
+	  (match_operand:DI 2 "memory_operand" "m")))
+   (clobber (reg:CC FLAGS_REG))
+   (unspec [(const_int 0)] UNSPEC_TLSDESC_SUN)]
+  "TARGET_64BIT && TARGET_SUN_TLS"
+  "add{q}\t{%2, %0|%0, %2}";
+  [(set_attr "type" "alu")
+   (set_attr "mode" "DI")])
+
 ;; Load and add the thread base pointer from %gs:0.
 (define_insn "*load_tp_<mode>"
   [(set (match_operand:P 0 "register_operand" "=r")