aboutsummaryrefslogtreecommitdiff
path: root/gcc/flow.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@pierdol.cobaltmicro.com>1998-09-12 01:03:36 +0000
committerDavid S. Miller <davem@gcc.gnu.org>1998-09-11 18:03:36 -0700
commit86465af7347851ef4d3473eabb4c7088b5443e6d (patch)
tree6a94719da1d0636b9e8e23c1c16030b3eb36f44a /gcc/flow.c
parentb5754a68c62048dc0e0dd34afbe5a99a3df042f9 (diff)
downloadgcc-86465af7347851ef4d3473eabb4c7088b5443e6d.zip
gcc-86465af7347851ef4d3473eabb4c7088b5443e6d.tar.gz
gcc-86465af7347851ef4d3473eabb4c7088b5443e6d.tar.bz2
flow.c (mark_set_1): Recognize multi-register structure return values in CALL insns.
* 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. From-SVN: r22395
Diffstat (limited to 'gcc/flow.c')
-rw-r--r--gcc/flow.c38
1 files changed, 32 insertions, 6 deletions
diff --git a/gcc/flow.c b/gcc/flow.c
index af9eb1c..a7ce4a3 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)