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

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).