OSDN Git Service

*** empty log message ***
authorrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 22 Mar 1992 03:36:46 +0000 (03:36 +0000)
committerrms <rms@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 22 Mar 1992 03:36:46 +0000 (03:36 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@562 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/global.c
gcc/local-alloc.c

index 913c61e..fca911e 100644 (file)
@@ -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++;
+       }
+    }
+}
 \f
 /* Mark REG as being dead (following the insn being scanned now).
    Store a 0 in regs_live or allocnos_live for this register.  */
index 90cac29..fc45217 100644 (file)
@@ -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);