This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix PR target/14599 (mips16 memory corruption)
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 16 Mar 2004 09:44:56 +0000
- Subject: Fix PR target/14599 (mips16 memory corruption)
MIPS16 uses a pseudo register as the global pointer, initialising it to
a special constant at the beginning of the function. This constant has
traditionally been (const (reg $gp)) (a register inside a CONST ;),
which has finally got the hammering it deserves.
In the test case, we have a libcall whose REG_EQUAL note is:
(float_truncate:DF (mem:DF (lo_sum:SI (reg:SI 183)
(symbol_ref:SI "ud"))))
where reg 183 is the gp pseudo. During gcse, cselib sets up the
following replacements:
(reg $gp) -> a VALUE rtx
(reg 183) -> (const (reg $gp)) -> (const (value))
so when do_local_cprop() processes the libcall, it tries to replace
(reg 183) with (const (value)). The substitution fails in the libcall
patterns themselves, but try_replace_reg() still makes the suggested
change to the REG_EQUAL. And AFAIK, that's correct, if not always optimal.
Anyway, the upshot is, a VALUE rtx enters the rtl stream and stays
around until after cselib_finish(). This causes memory access problems
later on.
I suspect the same thing could have happened in 3.3 and earlier,
but it's become more a problem now that cselib uses alloc pools
to handle VALUE rtxes.
The problem is easily fixed by replacing (const (reg $gp)) with
a more sensible representation, such as a (const (unspec ...)).
Patch tested on mips64vrel-elf. Also bootstrapped & regression
tested on mips-sgi-irix6.5 and mips64{,el}-linux-gnu. Applied
to head.
Richard
PR target/14599
* config/mips/mips.md (UNSPEC_GP): New constant.
* config/mips/mips.c (CONST_GP_P): Expect the CONST to contain
an UNSPEC instead of (reg $gp).
(mips16_gp_pseudo_reg): Change accordingly.
(print_operand): Print $gp directly when handling CONST_GP_P.
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.362.4.11
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.362.4.11 mips.c
--- config/mips/mips.c 7 Mar 2004 10:52:40 -0000 1.362.4.11
+++ config/mips/mips.c 15 Mar 2004 22:08:42 -0000
@@ -92,10 +92,12 @@ #define UNSPEC_ADDRESS(X) \
#define UNSPEC_ADDRESS_TYPE(X) \
((enum mips_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
-/* True if X is (const $gp). This is used to initialize the mips16
- gp pseudo register. */
+/* True if X is (const (unspec [(const_int 0)] UNSPEC_GP)). This is used
+ to initialize the mips16 gp pseudo register. */
#define CONST_GP_P(X) \
- (GET_CODE (X) == CONST && XEXP (X, 0) == pic_offset_table_rtx)
+ (GET_CODE (X) == CONST \
+ && GET_CODE (XEXP (X, 0)) == UNSPEC \
+ && XINT (XEXP (X, 0), 1) == UNSPEC_GP)
/* The maximum distance between the top of the stack frame and the
value $sp has when we save & restore registers.
@@ -5601,7 +5603,7 @@ print_operand (FILE *file, rtx op, int l
fputs (code == EQ ? "t" : "f", file);
else if (CONST_GP_P (op))
- print_operand (file, XEXP (op, 0), letter);
+ fputs (reg_names[GLOBAL_POINTER_REGNUM], file);
else
output_addr_const (file, op);
@@ -7841,7 +7843,7 @@ mips16_gp_pseudo_reg (void)
{
if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
{
- rtx const_gp;
+ rtx unspec;
rtx insn, scan;
cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode);
@@ -7849,10 +7851,10 @@ mips16_gp_pseudo_reg (void)
/* We want to initialize this to a value which gcc will believe
is constant. */
- const_gp = gen_rtx_CONST (Pmode, pic_offset_table_rtx);
start_sequence ();
+ unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_GP);
emit_move_insn (cfun->machine->mips16_gp_pseudo_rtx,
- const_gp);
+ gen_rtx_CONST (Pmode, unspec));
insn = get_insns ();
end_sequence ();
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.211.4.4
diff -u -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.211.4.4 mips.md
--- config/mips/mips.md 19 Feb 2004 22:56:11 -0000 1.211.4.4
+++ config/mips/mips.md 15 Mar 2004 22:08:43 -0000
@@ -55,6 +55,7 @@ (define_constants
(UNSPEC_SDR 25)
(UNSPEC_LOADGP 26)
(UNSPEC_LOAD_CALL 27)
+ (UNSPEC_GP 29)
(UNSPEC_ADDRESS_FIRST 100)