summaryrefslogtreecommitdiff
path: root/gcc/global.c
diff options
context:
space:
mode:
authorrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>1992-03-22 03:36:46 +0000
committerrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>1992-03-22 03:36:46 +0000
commiteea407a779797d87e7de3af9d6d9a8eb9b404c03 (patch)
tree5afa8a4ff7b83ce9fc4b920f91acf86fa420ddcf /gcc/global.c
parent94a720c880c2e986637c05eb7abc81dc8b0a67fc (diff)
downloadgcc-eea407a779797d87e7de3af9d6d9a8eb9b404c03.tar.gz
*** empty log message ***
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@562 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/global.c')
-rw-r--r--gcc/global.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/gcc/global.c b/gcc/global.c
index 913c61eff5e..fca911e247f 100644
--- a/gcc/global.c
+++ b/gcc/global.c
@@ -248,6 +248,7 @@ static HARD_REG_SET eliminable_regset;
static int allocno_compare ();
static void mark_reg_store ();
static void mark_reg_clobber ();
+static void mark_reg_conflicts ();
static void mark_reg_live_nc ();
static void mark_reg_death ();
static void dump_conflicts ();
@@ -698,6 +699,31 @@ global_conflicts ()
mark_reg_store (XEXP (link, 0), 0);
#endif
+ /* If INSN has multiple outputs, then any reg that dies here
+ and is used inside of an output
+ must conflict with the other outputs. */
+
+ if (GET_CODE (PATTERN (insn)) == PARALLEL && !single_set (insn))
+ for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
+ if (REG_NOTE_KIND (link) == REG_DEAD)
+ {
+ int used_in_output = 0;
+ int i;
+ rtx reg = XEXP (link, 0);
+
+ for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
+ {
+ rtx set = XVECEXP (PATTERN (insn), 0, i);
+ if (GET_CODE (set) == SET
+ && GET_CODE (SET_DEST (set)) != REG
+ && !rtx_equal_p (reg, SET_DEST (set))
+ && reg_overlap_mentioned_p (reg, SET_DEST (set)))
+ used_in_output = 1;
+ }
+ if (used_in_output)
+ mark_reg_conflicts (reg);
+ }
+
/* Mark any registers set in INSN and then never used. */
while (n_regs_set > 0)
@@ -1334,6 +1360,45 @@ mark_reg_clobber (reg, setter)
}
}
}
+
+/* Record that REG has conflicts with all the regs currently live.
+ Do not mark REG itself as live. */
+
+static void
+mark_reg_conflicts (reg)
+ rtx reg;
+{
+ register int regno;
+
+ if (GET_CODE (reg) == SUBREG)
+ reg = SUBREG_REG (reg);
+
+ if (GET_CODE (reg) != REG)
+ return;
+
+ regno = REGNO (reg);
+
+ if (reg_renumber[regno] >= 0)
+ regno = reg_renumber[regno];
+
+ /* Either this is one of the max_allocno pseudo regs not allocated,
+ or it is or has a hardware reg. First handle the pseudo-regs. */
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ if (reg_allocno[regno] >= 0)
+ record_one_conflict (regno);
+ }
+ /* Handle hardware regs (and pseudos allocated to hard regs). */
+ else if (! fixed_regs[regno])
+ {
+ register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ while (regno < last)
+ {
+ record_one_conflict (regno);
+ regno++;
+ }
+ }
+}
/* Mark REG as being dead (following the insn being scanned now).
Store a 0 in regs_live or allocnos_live for this register. */