public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, i386]: Cleanup TARGET_GNU2_TLS usage
@ 2011-05-11 19:28 Uros Bizjak
  2011-05-18 15:28 ` Rainer Orth
  0 siblings, 1 reply; 3+ messages in thread
From: Uros Bizjak @ 2011-05-11 19:28 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2421 bytes --]

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.

[-- Attachment #2: p.diff.txt --]
[-- Type: text/plain, Size: 10708 bytes --]

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;
-}
 \f
 /* Calculate the length of the memory address in the instruction
    encoding.  Does not include the one-byte modrm, opcode, or prefix.  */

[-- Attachment #3: tls.c --]
[-- Type: text/x-csrc, Size: 660 bytes --]

__thread int tls_gd __attribute__((tls_model("global-dynamic")));

int get_gd(void)
{
  return tls_gd;
}

int *get_gdp(void)
{
  return &tls_gd;
}

__thread int tls_ld __attribute__((tls_model("local-dynamic")));
__thread int tls_ld2 __attribute__((tls_model("local-dynamic")));

int get_ld(void)
{
  return tls_ld + tls_ld2;
}

int *get_ldp(void)
{
  return &tls_ld;
}

__thread int tls_le __attribute__((tls_model("local-exec")));

int get_le(void)
{
  return tls_le;
}

int *get_lep(void)
{
  return &tls_le;
}

__thread int tls_ie __attribute__((tls_model("initial-exec")));

int get_ie(void)
{
  return tls_ie;
}

int *get_iep(void)
{
  return &tls_ie;
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH, i386]: Cleanup TARGET_GNU2_TLS usage
  2011-05-11 19:28 [PATCH, i386]: Cleanup TARGET_GNU2_TLS usage Uros Bizjak
@ 2011-05-18 15:28 ` Rainer Orth
  2011-05-18 15:53   ` Uros Bizjak
  0 siblings, 1 reply; 3+ messages in thread
From: Rainer Orth @ 2011-05-18 15:28 UTC (permalink / raw)
  To: Uros Bizjak; +Cc: gcc-patches

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

-- 
-----------------------------------------------------------------------------
Rainer Orth, Center for Biotechnology, Bielefeld University

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH, i386]: Cleanup TARGET_GNU2_TLS usage
  2011-05-18 15:28 ` Rainer Orth
@ 2011-05-18 15:53   ` Uros Bizjak
  0 siblings, 0 replies; 3+ messages in thread
From: Uros Bizjak @ 2011-05-18 15:53 UTC (permalink / raw)
  To: Rainer Orth; +Cc: gcc-patches

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.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2011-05-18 14:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-11 19:28 [PATCH, i386]: Cleanup TARGET_GNU2_TLS usage Uros Bizjak
2011-05-18 15:28 ` Rainer Orth
2011-05-18 15:53   ` Uros Bizjak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).