summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/flow.c38
-rw-r--r--gcc/rtlanal.c21
3 files changed, 60 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6b2f642deff..63646a0f67a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+Fri Sep 11 23:55:54 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
+
+ * flow.c (mark_set_1): Recognize multi-register structure return
+ values in CALL insns.
+ (mark_used_regs): Likewise.
+ (count_reg_sets_1): Likewise.
+ (count_reg_references): Likewise.
+ * rtlanal.c (note_stores): Likewise.
+
Fri Sep 11 22:57:55 1998 Eric Dumazet <dumazet@cosmosbay.com>
* config/i386/sco5.h (ASM_WEAKEN_LABEL): Defined as in svr4.h.
diff --git a/gcc/flow.c b/gcc/flow.c
index af9eb1cde83..a7ce4a367e0 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -2133,6 +2133,19 @@ mark_set_1 (needed, dead, x, insn, significant)
register int regno;
register rtx reg = SET_DEST (x);
+ /* Some targets place small structures in registers for
+ return values of functions. We have to detect this
+ case specially here to get correct flow information. */
+ if (GET_CODE (reg) == PARALLEL
+ && GET_MODE (reg) == BLKmode)
+ {
+ register int i;
+
+ for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
+ mark_set_1 (needed, dead, XVECEXP (reg, 0, i), insn, significant);
+ return;
+ }
+
/* Modifying just one hardware register of a multi-reg value
or just a byte field of a register
does not mean the value from before this insn is now dead.
@@ -2794,15 +2807,17 @@ mark_used_regs (needed, live, x, final, insn)
/* If this is a store into a register,
recursively scan the value being stored. */
- if (GET_CODE (testreg) == REG
- && (regno = REGNO (testreg), regno != FRAME_POINTER_REGNUM)
+ if ((GET_CODE (testreg) == PARALLEL
+ && GET_MODE (testreg) == BLKmode)
+ || (GET_CODE (testreg) == REG
+ && (regno = REGNO (testreg), regno != FRAME_POINTER_REGNUM)
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
- && regno != HARD_FRAME_POINTER_REGNUM
+ && regno != HARD_FRAME_POINTER_REGNUM
#endif
#if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
- && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
+ && ! (regno == ARG_POINTER_REGNUM && fixed_regs[regno])
#endif
- )
+ ))
/* We used to exclude global_regs here, but that seems wrong.
Storing in them is like storing in mem. */
{
@@ -4043,6 +4058,15 @@ count_reg_sets_1 (x)
|| GET_CODE (reg) == STRICT_LOW_PART)
reg = XEXP (reg, 0);
+ if (GET_CODE (reg) == PARALLEL
+ && GET_MODE (reg) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (reg, 0) - 1; i >= 0; i--)
+ count_reg_sets_1 (XVECEXP (reg, 0, i));
+ return;
+ }
+
if (GET_CODE (reg) == REG)
{
regno = REGNO (reg);
@@ -4175,7 +4199,9 @@ count_reg_references (x)
/* If this is a store into a register,
recursively scan the value being stored. */
- if (GET_CODE (testreg) == REG)
+ if ((GET_CODE (testreg) == PARALLEL
+ && GET_MODE (testreg) == BLKmode)
+ || GET_CODE (testreg) == REG)
{
count_reg_references (SET_SRC (x));
if (mark_dest)
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index fb4176264b3..41625ee2868 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -1086,7 +1086,16 @@ note_stores (x, fun)
|| GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- (*fun) (dest, x);
+
+ if (GET_CODE (dest) == PARALLEL
+ && GET_MODE (dest) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ (*fun) (SET_DEST (XVECEXP (dest, 0, i)), x);
+ }
+ else
+ (*fun) (dest, x);
}
else if (GET_CODE (x) == PARALLEL)
{
@@ -1105,7 +1114,15 @@ note_stores (x, fun)
|| GET_CODE (dest) == SIGN_EXTRACT
|| GET_CODE (dest) == STRICT_LOW_PART)
dest = XEXP (dest, 0);
- (*fun) (dest, y);
+ if (GET_CODE (dest) == PARALLEL
+ && GET_MODE (dest) == BLKmode)
+ {
+ register int i;
+ for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ (*fun) (SET_DEST (XVECEXP (dest, 0, i)), y);
+ }
+ else
+ (*fun) (dest, y);
}
}
}