From 256f27f13cbdfdfc5143b422c2b4a11f234a56e8 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 9 Jul 2008 20:03:40 +0000 Subject: [PATCH] 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_): Allow any GPR destination and clobber $3. After reload, split into a move and ... (*tls_get_tp__split): ...this new instruction. gcc/testsuite/ PR target/35802 * gcc.target/mips/pr35802.c: New test. From-SVN: r137670 --- gcc/ChangeLog | 15 ++++++++++ gcc/config/mips/constraints.md | 3 -- gcc/config/mips/mips.c | 42 ++++++++++++++------------ gcc/config/mips/mips.h | 3 -- gcc/config/mips/mips.md | 52 +++++++++++++++++++++++---------- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/gcc.target/mips/pr35802.c | 17 +++++++++++ 7 files changed, 97 insertions(+), 40 deletions(-) create mode 100644 gcc/testsuite/gcc.target/mips/pr35802.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 06cd42f..c0e874b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2008-07-09 Richard Sandiford + + 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_): Allow any GPR destination and clobber $3. + After reload, split into a move and ... + (*tls_get_tp__split): ...this new instruction. + 2008-07-09 David Daney * config/mips/driver-native.c: Include coretypes.h and tm.h. diff --git a/gcc/config/mips/constraints.md b/gcc/config/mips/constraints.md index a387489..ee44783 100644 --- a/gcc/config/mips/constraints.md +++ b/gcc/config/mips/constraints.md @@ -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.") diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index e8d51bc..3bbae44 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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; diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 8518a86..c29a5e8 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -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*/ \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 6b2f5fa..43c47e5 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -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_" - [(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_" + [(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" "") + (set_attr "length" "8")]) + +(define_insn "*tls_get_tp__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_ + (set_attr "can_delay" "no") (set_attr "mode" "")]) ; The MIPS Paired-Single Floating Point and MIPS-3D Instructions. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 196c3fa..a71c1cc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-07-09 Richard Sandiford + + PR target/35802 + * gcc.target/mips/pr35802.c: New test. + 2008-07-09 Paolo Carlini PR c++/36760 diff --git a/gcc/testsuite/gcc.target/mips/pr35802.c b/gcc/testsuite/gcc.target/mips/pr35802.c new file mode 100644 index 0000000..3430098 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr35802.c @@ -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--); + } +} -- 2.7.4