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]

Re: Fix PR35802: spill failure for tls_get_tp_<mode>


Richard Sandiford <rdsandiford@googlemail.com> writes:
> Tested on mips64el-linux-gnu.  I'll apply in the next day or so if there
> are no objections.  (I'll come up with a testcase before then too.)

Here's what I applied to mainline and gcc-4_3-branch.

Richard


gcc/
	PR target/35802
	* config/mips/mips.h (reg_class): Remove V1_REG.
	(REG_CLASS_NAMES, REG_CLASS_CONTENTS): Update accordingly.
	* config/mips/mips.c (mips_regno_to_class): Map $3 to M16_NA_REGS
	instead of V1_REGS.
	(mips_get_tp): New function.
	(mips_legitimize_tls_address): Use it.
	* config/mips/constraints.md (v): Delete.
	* config/mips/mips.md (TLS_GET_TP_REGNUM): New constant.
	(tls_get_tp_<mode>): Allow any GPR destination and clobber $3.
	After reload, split into a move and ...
	(*tls_get_tp_<mode>_split): ...this new instruction.

gcc/testsuite/
	PR target/35802
	* gcc.target/mips/pr35802.c: New test.

Index: gcc/config/mips/mips.h
===================================================================
--- gcc/config/mips/mips.h	2008-07-07 20:19:43.000000000 +0100
+++ gcc/config/mips/mips.h	2008-07-07 20:45:56.000000000 +0100
@@ -1690,7 +1690,6 @@ enum reg_class
   T_REG,			/* mips16 T register ($24) */
   M16_T_REGS,			/* mips16 registers plus T register */
   PIC_FN_ADDR_REG,		/* SVR4 PIC function address register */
-  V1_REG,			/* Register $v1 ($3) used for TLS access.  */
   LEA_REGS,			/* Every GPR except $25 */
   GR_REGS,			/* integer registers */
   FP_REGS,			/* floating point registers */
@@ -1731,7 +1730,6 @@ #define REG_CLASS_NAMES							\
   "T_REG",								\
   "M16_T_REGS",								\
   "PIC_FN_ADDR_REG",							\
-  "V1_REG",								\
   "LEA_REGS",								\
   "GR_REGS",								\
   "FP_REGS",								\
@@ -1775,7 +1773,6 @@ #define REG_CLASS_CONTENTS						        
   { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* mips16 T register */	\
   { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* mips16 and T regs */ \
   { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* SVR4 PIC function address register */ \
-  { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* only $v1 */ \
   { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* Every other GPR except $25 */   \
   { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* integer registers */	\
   { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },	/* floating registers*/	\
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c	2008-07-07 20:19:43.000000000 +0100
+++ gcc/config/mips/mips.c	2008-07-07 20:45:56.000000000 +0100
@@ -479,7 +479,7 @@ static GTY (()) int mips_output_filename
 
 /* Index R is the smallest register class that contains register R.  */
 const enum reg_class mips_regno_to_class[FIRST_PSEUDO_REGISTER] = {
-  LEA_REGS,	LEA_REGS,	M16_NA_REGS,	V1_REG,
+  LEA_REGS,	LEA_REGS,	M16_NA_REGS,	M16_NA_REGS,
   M16_REGS,	M16_REGS,	M16_REGS,	M16_REGS,
   LEA_REGS,	LEA_REGS,	LEA_REGS,	LEA_REGS,
   LEA_REGS,	LEA_REGS,	LEA_REGS,	LEA_REGS,
@@ -2465,6 +2465,21 @@ mips_call_tls_get_addr (rtx sym, enum mi
   return insn;
 }
 
+/* Return a pseudo register that contains the current thread pointer.  */
+
+static rtx
+mips_get_tp (void)
+{
+  rtx tp;
+
+  tp = gen_reg_rtx (Pmode);
+  if (Pmode == DImode)
+    emit_insn (gen_tls_get_tp_di (tp));
+  else
+    emit_insn (gen_tls_get_tp_si (tp));
+  return tp;
+}
+
 /* Generate the code to access LOC, a thread-local SYMBOL_REF, and return
    its address.  The return value will be both a valid address and a valid
    SET_SRC (either a REG or a LO_SUM).  */
@@ -2472,7 +2487,7 @@ mips_call_tls_get_addr (rtx sym, enum mi
 static rtx
 mips_legitimize_tls_address (rtx loc)
 {
-  rtx dest, insn, v0, v1, tmp1, tmp2, eqv;
+  rtx dest, insn, v0, tp, tmp1, tmp2, eqv;
   enum tls_model model;
 
   if (TARGET_MIPS16)
@@ -2514,31 +2529,20 @@ mips_legitimize_tls_address (rtx loc)
       break;
 
     case TLS_MODEL_INITIAL_EXEC:
-      v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
+      tp = mips_get_tp ();
       tmp1 = gen_reg_rtx (Pmode);
       tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL);
       if (Pmode == DImode)
-	{
-	  emit_insn (gen_tls_get_tp_di (v1));
-	  emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
-	}
+	emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
       else
-	{
-	  emit_insn (gen_tls_get_tp_si (v1));
-	  emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
-	}
+	emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
       dest = gen_reg_rtx (Pmode);
-      emit_insn (gen_add3_insn (dest, tmp1, v1));
+      emit_insn (gen_add3_insn (dest, tmp1, tp));
       break;
 
     case TLS_MODEL_LOCAL_EXEC:
-      v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
-      if (Pmode == DImode)
-	emit_insn (gen_tls_get_tp_di (v1));
-      else
-	emit_insn (gen_tls_get_tp_si (v1));
-
-      tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL);
+      tp = mips_get_tp ();
+      tmp1 = mips_unspec_offset_high (NULL, tp, loc, SYMBOL_TPREL);
       dest = gen_rtx_LO_SUM (Pmode, tmp1,
 			     mips_unspec_address (loc, SYMBOL_TPREL));
       break;
Index: gcc/config/mips/constraints.md
===================================================================
--- gcc/config/mips/constraints.md	2008-07-07 20:19:43.000000000 +0100
+++ gcc/config/mips/constraints.md	2008-07-07 20:45:56.000000000 +0100
@@ -55,9 +55,6 @@ (define_register_constraint "e" "LEA_REG
 (define_register_constraint "j" "PIC_FN_ADDR_REG"
   "@internal")
 
-(define_register_constraint "v" "V1_REG"
-  "@internal")
-
 (define_register_constraint "y" "GR_REGS"
   "Equivalent to @code{r}; retained for backwards compatibility.")
 
Index: gcc/config/mips/mips.md
===================================================================
--- gcc/config/mips/mips.md	2008-07-07 20:19:43.000000000 +0100
+++ gcc/config/mips/mips.md	2008-07-07 20:45:56.000000000 +0100
@@ -69,6 +69,7 @@ (define_constants
    
    (UNSPEC_ADDRESS_FIRST	100)
 
+   (TLS_GET_TP_REGNUM		3)
    (GOT_VERSION_REGNUM		79)
 
    ;; For MIPS Paired-Singled Floating Point Instructions.
@@ -6499,26 +6500,47 @@ (define_insn "*mips16e_save_restore"
   [(set_attr "type" "arith")
    (set_attr "extended_mips16" "yes")])
 
-; Thread-Local Storage
+;; Thread-Local Storage
 
-; The TLS base pointer is accessed via "rdhwr $v1, $29".  No current
-; MIPS architecture defines this register, and no current
-; implementation provides it; instead, any OS which supports TLS is
-; expected to trap and emulate this instruction.  rdhwr is part of the
-; MIPS 32r2 specification, but we use it on any architecture because
-; we expect it to be emulated.  Use .set to force the assembler to
-; accept it.
-
-(define_insn "tls_get_tp_<mode>"
-  [(set (match_operand:P 0 "register_operand" "=v")
-	(unspec:P [(const_int 0)]
-		  UNSPEC_TLS_GET_TP))]
+;; The TLS base pointer is accessed via "rdhwr $3, $29".  No current
+;; MIPS architecture defines this register, and no current
+;; implementation provides it; instead, any OS which supports TLS is
+;; expected to trap and emulate this instruction.  rdhwr is part of the
+;; MIPS 32r2 specification, but we use it on any architecture because
+;; we expect it to be emulated.  Use .set to force the assembler to
+;; accept it.
+;;
+;; We do not use a constraint to force the destination to be $3
+;; because $3 can appear explicitly as a function return value.
+;; If we leave the use of $3 implicit in the constraints until
+;; reload, we may end up making a $3 return value live across
+;; the instruction, leading to a spill failure when reloading it.
+(define_insn_and_split "tls_get_tp_<mode>"
+  [(set (match_operand:P 0 "register_operand" "=d")
+	(unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP))
+   (clobber (reg:P TLS_GET_TP_REGNUM))]
   "HAVE_AS_TLS && !TARGET_MIPS16"
-  ".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop"
+  "#"
+  "&& reload_completed"
+  [(set (reg:P TLS_GET_TP_REGNUM)
+	(unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP))
+   (set (match_dup 0) (reg:P TLS_GET_TP_REGNUM))]
+  ""
   [(set_attr "type" "unknown")
    ; Since rdhwr always generates a trap for now, putting it in a delay
    ; slot would make the kernel's emulation of it much slower.
    (set_attr "can_delay" "no")
+   (set_attr "mode" "<MODE>")
+   (set_attr "length" "8")])
+
+(define_insn "*tls_get_tp_<mode>_split"
+  [(set (reg:P TLS_GET_TP_REGNUM)
+	(unspec:P [(const_int 0)] UNSPEC_TLS_GET_TP))]
+  "HAVE_AS_TLS && !TARGET_MIPS16"
+  ".set\tpush\;.set\tmips32r2\t\;rdhwr\t$3,$29\;.set\tpop"
+  [(set_attr "type" "unknown")
+   ; See tls_get_tp_<mode>
+   (set_attr "can_delay" "no")
    (set_attr "mode" "<MODE>")])
 
 ; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
Index: gcc/testsuite/gcc.target/mips/pr35802.c
===================================================================
--- /dev/null	2008-07-06 10:30:39.548096750 +0100
+++ gcc/testsuite/gcc.target/mips/pr35802.c	2008-07-07 22:38:13.000000000 +0100
@@ -0,0 +1,17 @@
+/* { dg-mips-options "-O2 -march=74kc -mgp32" } */
+__thread int x __attribute__((tls_model("initial-exec")));
+__thread int y __attribute__((tls_model("initial-exec")));
+
+int bar (void);
+
+NOMIPS16 void
+foo (int n)
+{
+  if (n > 5)
+    {
+      y = 0;
+      do
+	x += bar ();
+      while (n--);
+    }
+}


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