This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Fix PR35802: spill failure for tls_get_tp_<mode>
- From: Richard Sandiford <rdsandiford at googlemail dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: maxim at codesourcery dot com
- Date: Wed, 09 Jul 2008 21:06:25 +0100
- Subject: Re: Fix PR35802: spill failure for tls_get_tp_<mode>
- References: <87bq19wjpv.fsf@firetop.home>
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--);
+ }
+}