This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH/RFA] SH: Cleanup TLS handling


Hi,

The attached patch is to cleanup TLS handling of SH.  It was suggested
by Joern and waiting stage1 for a while.  Bootstrapped and tested with
"make -k check" on sh4-unknown-linux-gnu with no regressions.  It's also
tested with build&test of the latest glibc for the same target.
Ok for mainline?

Regards,
	kaz
--
2005-02-28  Kaz Kojima  <kkojima@gcc.gnu.org>

	* config/sh/sh-protos.h (legitimize_tls_address): Add prototype.
	* config/sh/sh.c (legitimize_tls_address): New.
	(prepare_move_operands): Use legitimize_tls_address.
	* config/sh/sh.h: (LEGITIMIZE_ADDRESS): Call legitimize_tls_address
	for TLS symbolic operands.

diff -uprN ORIG/gcc/gcc/config/sh/sh-protos.h LOCAL/gcc/gcc/config/sh/sh-protos.h
--- ORIG/gcc/gcc/config/sh/sh-protos.h	2004-09-29 08:49:55.000000000 +0900
+++ LOCAL/gcc/gcc/config/sh/sh-protos.h	2005-02-24 13:48:41.000000000 +0900
@@ -47,6 +47,7 @@ extern int fp_one_operand (rtx);
 extern int fp_int_operand (rtx);
 extern rtx get_fpscr_rtx (void);
 extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+extern rtx legitimize_tls_address (rtx, enum machine_mode);
 extern int nonpic_symbol_mentioned_p (rtx);
 extern void emit_sf_insn (rtx);
 extern void emit_df_insn (rtx);
diff -uprN ORIG/gcc/gcc/config/sh/sh.c LOCAL/gcc/gcc/config/sh/sh.c
--- ORIG/gcc/gcc/config/sh/sh.c	2005-02-17 09:03:05.000000000 +0900
+++ LOCAL/gcc/gcc/config/sh/sh.c	2005-02-26 20:31:49.745536808 +0900
@@ -1006,82 +1006,10 @@ prepare_move_operands (rtx operands[], e
 	       && GET_CODE (XEXP (operands[0], 0)) == PLUS
 	       && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == REG)
 	operands[1] = copy_to_mode_reg (mode, operands[1]);
-    }
-
-  if (mode == Pmode || mode == ptr_mode)
-    {
-      rtx op0, op1;
-      enum tls_model tls_kind;
-
-      op0 = operands[0];
-      op1 = operands[1];
-      if ((tls_kind = tls_symbolic_operand (op1, Pmode)))
-	{
-	  rtx tga_op1, tga_ret, tmp, tmp2;
-
-	  switch (tls_kind)
-	    {
-	    case TLS_MODEL_GLOBAL_DYNAMIC:
-	      tga_ret = gen_rtx_REG (Pmode, R0_REG);
-	      emit_call_insn (gen_tls_global_dynamic (tga_ret, op1));
-	      op1 = tga_ret;
-	      break;
-
-	    case TLS_MODEL_LOCAL_DYNAMIC:
-	      tga_ret = gen_rtx_REG (Pmode, R0_REG);
-	      emit_call_insn (gen_tls_local_dynamic (tga_ret, op1));
-
-	      tmp = gen_reg_rtx (Pmode);
-	      emit_move_insn (tmp, tga_ret);
-
-	      if (register_operand (op0, Pmode))
-		tmp2 = op0;
-	      else
-		tmp2 = gen_reg_rtx (Pmode);
-
-	      emit_insn (gen_symDTPOFF2reg (tmp2, op1, tmp));
-	      op1 = tmp2;
-	      break;
-
-	    case TLS_MODEL_INITIAL_EXEC:
-	      if (! flag_pic)
-		{
-		  /* Don't schedule insns for getting GOT address when
-		     the first scheduling is enabled, to avoid spill
-		     failures for R0.  */
-		  if (flag_schedule_insns)
-		    emit_insn (gen_blockage ());
-		  emit_insn (gen_GOTaddr2picreg ());
-		  emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode,
-								 PIC_REG)));
-		  if (flag_schedule_insns)
-		    emit_insn (gen_blockage ());
-		}
-	      tga_op1 = no_new_pseudos ? op0 : gen_reg_rtx (Pmode);
-	      tmp = gen_sym2GOTTPOFF (op1);
-	      emit_insn (gen_tls_initial_exec (tga_op1, tmp));
-	      op1 = tga_op1;
-	      break;
 
-	    case TLS_MODEL_LOCAL_EXEC:
-	      tmp2 = gen_reg_rtx (Pmode);
-	      emit_insn (gen_load_gbr (tmp2));
-	      tmp = gen_reg_rtx (Pmode);
-	      emit_insn (gen_symTPOFF2reg (tmp, op1));
-
-	      if (register_operand (op0, Pmode))
-		op1 = op0;
-	      else
-		op1 = gen_reg_rtx (Pmode);
-
-	      emit_insn (gen_addsi3 (op1, tmp, tmp2));
-	      break;
-
-	    default:
-	      abort ();
-	    }
-	  operands[1] = op1;
-	}
+      if ((mode == Pmode || mode == ptr_mode)
+	  && tls_symbolic_operand (operands[1], Pmode) != 0)
+	operands[1] = legitimize_tls_address (operands[1], mode);
     }
 
   return 0;
@@ -8441,6 +8369,79 @@ legitimize_pic_address (rtx orig, enum m
   return orig;
 }
 
+/* A subroutine for LEGITIMIZE_ADDRESS.  Generate the TLS sequence for
+   TLS addresses and return X itself othrewise.  */
+rtx
+legitimize_tls_address (rtx x, enum machine_mode mode)
+{
+
+  if (mode == Pmode || mode == ptr_mode)
+    {
+      enum tls_model tls_kind;
+
+      if ((tls_kind = tls_symbolic_operand (x, Pmode)))
+	{
+	  rtx dest, tga_dest, tga_ret, tmp, tmp2;
+
+	  switch (tls_kind)
+	    {
+	    case TLS_MODEL_GLOBAL_DYNAMIC:
+	      tga_ret = gen_rtx_REG (Pmode, R0_REG);
+	      emit_call_insn (gen_tls_global_dynamic (tga_ret, x));
+	      dest = tga_ret;
+	      break;
+
+	    case TLS_MODEL_LOCAL_DYNAMIC:
+	      tga_ret = gen_rtx_REG (Pmode, R0_REG);
+	      emit_call_insn (gen_tls_local_dynamic (tga_ret, x));
+
+	      tmp = gen_reg_rtx (Pmode);
+	      emit_move_insn (tmp, tga_ret);
+	      tmp2 = gen_reg_rtx (Pmode);
+	      emit_insn (gen_symDTPOFF2reg (tmp2, x, tmp));
+	      dest = tmp2;
+	      break;
+
+	    case TLS_MODEL_INITIAL_EXEC:
+	      if (! flag_pic)
+		{
+		  /* Don't schedule insns for getting GOT address when
+		     the first scheduling is enabled, to avoid spill
+		     failures for R0.  */
+		  if (flag_schedule_insns)
+		    emit_insn (gen_blockage ());
+		  emit_insn (gen_GOTaddr2picreg ());
+		  emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode,
+								 PIC_REG)));
+		  if (flag_schedule_insns)
+		    emit_insn (gen_blockage ());
+		}
+	      tga_dest = gen_reg_rtx (Pmode);
+	      tmp = gen_sym2GOTTPOFF (x);
+	      emit_insn (gen_tls_initial_exec (tga_dest, tmp));
+	      dest = tga_dest;
+	      break;
+
+	    case TLS_MODEL_LOCAL_EXEC:
+	      tmp2 = gen_reg_rtx (Pmode);
+	      emit_insn (gen_load_gbr (tmp2));
+	      tmp = gen_reg_rtx (Pmode);
+	      emit_insn (gen_symTPOFF2reg (tmp, x));
+	      dest = gen_reg_rtx (Pmode);
+	      emit_insn (gen_addsi3 (dest, tmp, tmp2));
+	      break;
+
+	    default:
+	      abort ();
+	    }
+
+	  return dest;
+	}
+    }
+
+  return x;
+}
+
 /* Mark the use of a constant in the literal table. If the constant
    has multiple labels, make it unique.  */
 static rtx
diff -uprN ORIG/gcc/gcc/config/sh/sh.h LOCAL/gcc/gcc/config/sh/sh.h
--- ORIG/gcc/gcc/config/sh/sh.h	2005-01-04 10:48:38.000000000 +0900
+++ LOCAL/gcc/gcc/config/sh/sh.h	2005-02-24 13:56:51.000000000 +0900
@@ -2673,7 +2673,9 @@ struct sh_args {
 
 #define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN)			\
 {								\
-  if (flag_pic)							\
+  if (tls_symbolic_operand (X, MODE) != 0)			\
+    (X) = legitimize_tls_address (X, MODE);			\
+  else if (flag_pic)						\
     (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX);	\
   if (GET_CODE (X) == PLUS					\
       && (GET_MODE_SIZE (MODE) == 4				\


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]