aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1993-03-05 17:37:11 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1993-03-05 17:37:11 -0500
commit02a10449e3f898314fa48b4e173f20c3e04bf552 (patch)
tree9317f96e8daf2ef4f03ef1c5bd8a935a9e58e6a3
parentc2ae03cb30827d0d28c78db0302b77824e3a4f2e (diff)
downloadgcc-02a10449e3f898314fa48b4e173f20c3e04bf552.zip
gcc-02a10449e3f898314fa48b4e173f20c3e04bf552.tar.gz
gcc-02a10449e3f898314fa48b4e173f20c3e04bf552.tar.bz2
(fixup_var_refs_insns): If SMALL_REGISTER_CLASSES...
(fixup_var_refs_insns): If SMALL_REGISTER_CLASSES, ensure we don't put any insns between the setting of the function return register and it's use. From-SVN: r3660
-rw-r--r--gcc/function.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/gcc/function.c b/gcc/function.c
index b1ce844..cc28884 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -999,6 +999,8 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
rtx insn;
int toplevel;
{
+ rtx call_dest = 0;
+
while (insn)
{
rtx next = NEXT_INSN (insn);
@@ -1022,6 +1024,46 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
}
else
{
+ struct fixup_replacement *replacements = 0;
+ rtx next_insn = NEXT_INSN (insn);
+
+#ifdef SMALL_REGISTER_CLASSES
+ /* If the insn that copies the results of a CALL_INSN
+ into a pseudo now references VAR, we have to use an
+ intermediate pseudo since we want the life of the
+ return value register to be only a single insn.
+
+ If we don't use an intermediate pseudo, such things as
+ address computations to make the address of VAR valid
+ if it is not can be placed beween the CALL_INSN and INSN.
+
+ To make sure this doesn't happen, we record the destination
+ of the CALL_INSN and see if the next insn uses both that
+ and VAR. */
+
+ if (call_dest != 0 && GET_CODE (insn) == INSN
+ && reg_mentioned_p (var, PATTERN (insn))
+ && reg_mentioned_p (call_dest, PATTERN (insn)))
+ {
+ rtx temp = gen_reg_rtx (GET_MODE (call_dest));
+
+ emit_insn_before (gen_move_insn (temp, call_dest), insn);
+
+ PATTERN (insn) = replace_rtx (PATTERN (insn),
+ call_dest, temp);
+ }
+
+ if (GET_CODE (insn) == CALL_INSN
+ && GET_CODE (PATTERN (insn)) == SET)
+ call_dest = SET_DEST (PATTERN (insn));
+ else if (GET_CODE (insn) == CALL_INSN
+ && GET_CODE (PATTERN (insn)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET)
+ call_dest = SET_DEST (XVECEXP (PATTERN (insn), 0, 0));
+ else
+ call_dest = 0;
+#endif
+
/* See if we have to do anything to INSN now that VAR is in
memory. If it needs to be loaded into a pseudo, use a single
pseudo for the entire insn in case there is a MATCH_DUP
@@ -1033,9 +1075,6 @@ fixup_var_refs_insns (var, promoted_mode, unsignedp, insn, toplevel)
If it allocated a pseudo for any replacement, we copy into
it here. */
- struct fixup_replacement *replacements = 0;
- rtx next_insn = NEXT_INSN (insn);
-
fixup_var_refs_1 (var, promoted_mode, &PATTERN (insn), insn,
&replacements);