From: Richard Stallman Date: Sun, 22 Mar 1992 03:36:46 +0000 (+0000) Subject: *** empty log message *** X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=333e0f7d36aa66fb00cf587d04a6738ee6c9f73a;p=gcc.git *** empty log message *** From-SVN: r562 --- 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. */ diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c index 90cac29b0a0..fc45217d11a 100644 --- a/gcc/local-alloc.c +++ b/gcc/local-alloc.c @@ -1729,7 +1729,8 @@ reg_is_born (reg, birth) /* Record the death of REG in the current insn. If OUTPUT_P is non-zero, REG is an output that is dying (i.e., it is never used), otherwise it - is an input (the normal case). */ + is an input (the normal case). + If OUTPUT_P is 1, then we extend the life past the end of this insn. */ static void wipe_dead_reg (reg, output_p) @@ -1738,6 +1739,25 @@ wipe_dead_reg (reg, output_p) { register int regno = REGNO (reg); + /* If this insn has multiple results, + and the dead reg is used in one of the results, + extend its life to after this insn, + so it won't get allocated together with any other result of this insn. */ + if (GET_CODE (PATTERN (this_insn)) == PARALLEL + && !single_set (this_insn)) + { + int i; + for (i = XVECLEN (PATTERN (this_insn), 0) - 1; i >= 0; i--) + { + rtx set = XVECEXP (PATTERN (this_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))) + output_p = 1; + } + } + if (regno < FIRST_PSEUDO_REGISTER) { mark_life (regno, GET_MODE (reg), 0);