Patchwork [i386] : Cleanup TARGET_GNU2_TLS usage

login
register
mail settings
Submitter Uros Bizjak
Date May 11, 2011, 3:42 p.m.
Message ID <BANLkTikEFxtptQv-pgO5NSd1eKVjJ_CcJQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/95165/
State New
Headers show

Comments

Uros Bizjak - May 11, 2011, 3:42 p.m.
Hello!

Attached patch cleans legitimize_tls_address and corresponding
expanders to call gen_tls_dynamic_gnu2_{32,64} directly in case of
TARGET_GNU2_TLS target. The patch also changes unique REG_EQUIV note
to __tls_get_addr call to UNSPEC (the same approach MIPS does) instead
of some strange nested EXPR_LISTs. Additionally, ix86_tls_get_address
is now used only in i386.c, so it can be declared static.

The patch does not introduce any functional change, leaving also
previous ICE on 64bit targets with -mcmodel=large and
-mtls-dialect=gnu:

tls.c:6:1: error: unrecognizable insn:
(call_insn/u 5 4 6 3 (parallel [
            (set (reg:DI 0 ax)
                (call:DI (mem:QI (symbol_ref:DI ("__tls_get_addr")) [0 S1 A8])
                    (const_int 0 [0])))
            (unspec:DI [
                    (symbol_ref:DI ("tls_gd") [flags 0x12] <var_decl
0x7f3846c08000 tls_gd>)
                ] UNSPEC_TLS_GD)
        ]) tls.c:5 -1
     (expr_list:REG_EH_REGION (const_int -2147483648 [0xffffffff80000000])
        (nil))
    (nil))

The test (tls.c), used to check all TLS models is attached to the
message. I plan to convert it to proper dg test... ;)

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.

Patch was tested on x86_64-pc-linux-gnu {,-m32} and committed to mainline SVN.

Uros.
Rainer Orth - May 18, 2011, 11:30 a.m.
Uros,

> The test (tls.c), used to check all TLS models is attached to the
> message. I plan to convert it to proper dg test... ;)

I've got it in my tree since you sent it to me while debugging/testing
support for the various TLS models on Solaris.  I'd really prefer (and
have modified it this way) the test to be split into one test per access
model so it becomes easier to figure out what is failing.

I can provide such a patch if desired.

Thanks.
	Rainer
Uros Bizjak - May 18, 2011, 2:05 p.m.
On Wed, May 18, 2011 at 1:30 PM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:

>> The test (tls.c), used to check all TLS models is attached to the
>> message. I plan to convert it to proper dg test... ;)
>
> I've got it in my tree since you sent it to me while debugging/testing
> support for the various TLS models on Solaris.  I'd really prefer (and
> have modified it this way) the test to be split into one test per access
> model so it becomes easier to figure out what is failing.
>
> I can provide such a patch if desired.

Yes, IMO this patch would be much appreciated...

Uros.

Patch

Index: i386.md
===================================================================
--- i386.md	(revision 173620)
+++ i386.md	(working copy)
@@ -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.
Index: i386-protos.h
===================================================================
--- i386-protos.h	(revision 173620)
+++ i386-protos.h	(working copy)
@@ -193,7 +193,6 @@  extern unsigned int ix86_get_callcvt (co
 
 #endif
 
-extern rtx ix86_tls_get_addr (void);
 extern rtx ix86_tls_module_base (void);
 
 extern void ix86_expand_vector_init (bool, rtx, rtx);
Index: i386.c
===================================================================
--- i386.c	(revision 173620)
+++ i386.c	(working copy)
@@ -12657,7 +12657,7 @@  legitimize_pic_address (rtx orig, rtx re
 /* 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_
 
 	  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_mod
   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.  */