Commit 256f27f1 by Richard Sandiford Committed by Richard Sandiford

re PR target/35802 (MIPS64: Unable to find a register to spill in class ‘V1_REG’)

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.

From-SVN: r137670
parent 432b5555
2008-07-09 Richard Sandiford <rdsandiford@googlemail.com>
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.
2008-07-09 David Daney <ddaney@avtrex.com>
* config/mips/driver-native.c: Include coretypes.h and tm.h.
......
......@@ -55,9 +55,6 @@
(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.")
......
......@@ -479,7 +479,7 @@ static const char *mips_hi_relocs[NUM_SYMBOL_TYPES];
/* 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 mips_symbol_type type, rtx v0)
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 mips_symbol_type type, rtx v0)
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;
......
......@@ -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 @@ enum reg_class
"T_REG", \
"M16_T_REGS", \
"PIC_FN_ADDR_REG", \
"V1_REG", \
"LEA_REGS", \
"GR_REGS", \
"FP_REGS", \
......@@ -1775,7 +1773,6 @@ enum reg_class
{ 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*/ \
......
......@@ -69,6 +69,7 @@
(UNSPEC_ADDRESS_FIRST 100)
(TLS_GET_TP_REGNUM 3)
(GOT_VERSION_REGNUM 79)
;; For MIPS Paired-Singled Floating Point Instructions.
......@@ -6499,26 +6500,47 @@
[(set_attr "type" "arith")
(set_attr "extended_mips16" "yes")])
; 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))]
;; Thread-Local Storage
;; 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.
......
2008-07-09 Richard Sandiford <rdsandiford@googlemail.com>
PR target/35802
* gcc.target/mips/pr35802.c: New test.
2008-07-09 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/36760
......
/* { 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--);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment