caller-save.c (insert_one_insn): Returns struct insn_chain *.
authorJ"orn Rennecke <amylaar@cygnus.co.uk>
Wed, 15 Dec 1999 14:57:29 +0000 (14:57 +0000)
committerJoern Rennecke <amylaar@gcc.gnu.org>
Wed, 15 Dec 1999 14:57:29 +0000 (14:57 +0000)
* caller-save.c (insert_one_insn): Returns struct insn_chain *.
Handle live_throughout / dead_or_set instead of live_before /
live_after.
(save_call_clobbered_regs): Get register livenessinformation from
chain->live_throughout.
(add_stored_regs): New function.
(insert_restore, insert_save): Add restored / saved registers to
dead_or_set.
* global.c (reg_dies): New parameter chain.
(reg_becomes_live): Third parameter is regs_set now.
Changed all callers.
(reg_dies): New parameter chain.  Changed all callers.
(build_insn_chain): Set live_throughout instead of
live_before / live_after.
* reload.h (struct insn_chain): Replace members live_before /
live_after with live_throughout / dead_or_set.
* reload1.c (new_insn_chain): Handle live_throughout / dead_or_set
instead of live_before / live_after.
(maybe_fix_stack_asms, find_reload_regs, finish_spills): Likewise.
(order_regs_for_reload, find_reg, finish_spills): Likewise.
(choose_reload_regs_init): Likewise.
* stupid.c (current_chain, find_clobbered_regs): Delete.
(stupid_life_analysis): Set chain->live_throughout chain->dead_or_set
instead of chain->live_before / chain->live_after.
(mark_hard_ref): New function.
(stupid_mark_refs): Call mark_hard_ref. Clear chain->live_throughout.

From-SVN: r30957

gcc/ChangeLog
gcc/caller-save.c
gcc/global.c
gcc/reload.h
gcc/reload1.c
gcc/stupid.c

index aaf947041fdc6bc9f57c7633b8dbf607f3cac2e5..5bc25d70c7ea7e4b83365d320cad8bfccd026232 100644 (file)
@@ -1,3 +1,32 @@
+Wed Dec 15 14:55:24 1999  J"orn Rennecke <amylaar@cygnus.co.uk>
+
+       * caller-save.c (insert_one_insn): Returns struct insn_chain *.
+       Handle live_throughout / dead_or_set instead of live_before /
+       live_after.
+       (save_call_clobbered_regs): Get register livenessinformation from
+       chain->live_throughout.
+       (add_stored_regs): New function.
+       (insert_restore, insert_save): Add restored / saved registers to
+       dead_or_set.
+       * global.c (reg_dies): New parameter chain.
+       (reg_becomes_live): Third parameter is regs_set now.
+       Changed all callers.
+       (reg_dies): New parameter chain.  Changed all callers.
+       (build_insn_chain): Set live_throughout instead of
+       live_before / live_after.
+       * reload.h (struct insn_chain): Replace members live_before /
+       live_after with live_throughout / dead_or_set.
+       * reload1.c (new_insn_chain): Handle live_throughout / dead_or_set
+       instead of live_before / live_after.
+       (maybe_fix_stack_asms, find_reload_regs, finish_spills): Likewise.
+       (order_regs_for_reload, find_reg, finish_spills): Likewise.
+       (choose_reload_regs_init): Likewise.
+       * stupid.c (current_chain, find_clobbered_regs): Delete.
+       (stupid_life_analysis): Set chain->live_throughout chain->dead_or_set
+       instead of chain->live_before / chain->live_after.
+       (mark_hard_ref): New function.
+       (stupid_mark_refs): Call mark_hard_ref. Clear chain->live_throughout.
+
 1999-12-15  David S. Miller  <davem@redhat.com>
 
        * rtlanal.c (reg_overlap_mentioned_p): Handle CONCAT.
index b58fe871325eec7f96252350a43583c02a026f06..bbd783131d2bc4992c31bff79e1c418291ceac5e 100644 (file)
@@ -90,8 +90,8 @@ static int insert_save                        PROTO((struct insn_chain *, int, int,
                                               HARD_REG_SET *));
 static int insert_restore              PROTO((struct insn_chain *, int, int,
                                               int));
-static void insert_one_insn            PROTO((struct insn_chain *, int,
-                                              enum insn_code, rtx));
+static struct insn_chain *insert_one_insn PROTO((struct insn_chain *, int,
+                                                enum insn_code, rtx));
 \f
 /* Initialize for caller-save.
 
@@ -373,17 +373,20 @@ save_call_clobbered_regs ()
 
          if (code == CALL_INSN)
            {
-             rtx x;
-             int regno, nregs;
+             int regno;
              HARD_REG_SET hard_regs_to_save;
 
              /* Use the register life information in CHAIN to compute which
-                regs are live before the call.  */
-             REG_SET_TO_HARD_REG_SET (hard_regs_to_save, chain->live_before);
-             compute_use_by_pseudos (&hard_regs_to_save, chain->live_before);
+                regs are live during the call.  */
+             REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
+                                      chain->live_throughout);
+             compute_use_by_pseudos (&hard_regs_to_save,
+                                     chain->live_throughout);
 
              /* Record all registers set in this call insn.  These don't need
-                to be saved.  */
+                to be saved.  N.B. the call insn might set a subreg of a
+                multi-hard-reg pseudo; then the pseudo is considered live
+                during the call, but the subreg that is set isn't.  */
              CLEAR_HARD_REG_SET (this_insn_sets);
              note_stores (PATTERN (insn), mark_set_regs, NULL);
 
@@ -393,45 +396,6 @@ save_call_clobbered_regs ()
              AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved);
              AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set);
 
-             /* Registers used for function parameters need not be saved.  */
-             for (x = CALL_INSN_FUNCTION_USAGE (insn); x != 0;
-                  x = XEXP (x, 1))
-               {
-                 rtx y;
-
-                 if (GET_CODE (XEXP (x, 0)) != USE)
-                   continue;
-                 y = XEXP (XEXP (x, 0), 0);
-                 if (GET_CODE (y) != REG)
-                   abort ();
-                 regno = REGNO (y);
-                 if (REGNO (y) >= FIRST_PSEUDO_REGISTER)
-                   abort ();
-                 nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
-                 while (nregs-- > 0)
-                   CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);
-               }
-
-             /* Neither do registers for which we find a death note.  */
-             for (x = REG_NOTES (insn); x != 0; x = XEXP (x, 1))
-               {
-                 rtx y = XEXP (x, 0);
-
-                 if (REG_NOTE_KIND (x) != REG_DEAD)
-                   continue;
-                 if (GET_CODE (y) != REG)
-                   abort ();
-                 regno = REGNO (y);
-
-                 if (regno >= FIRST_PSEUDO_REGISTER)
-                   regno = reg_renumber[regno];
-                 if (regno < 0)
-                   continue;
-                 nregs = HARD_REGNO_NREGS (regno, GET_MODE (y));
-                 while (nregs-- > 0)
-                   CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs);                
-               }
-               
              for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
                  regno += insert_save (chain, 1, regno, &hard_regs_to_save);
@@ -490,6 +454,39 @@ mark_set_regs (reg, setter, data)
     SET_HARD_REG_BIT (this_insn_sets, i);
 }
 
+/* Here from note_stores when an insn stores a value in a register.
+   Set the proper bit or bits in the passed regset.  All pseudos that have
+   been assigned hard regs have had their register number changed already,
+   so we can ignore pseudos.  */
+static void
+add_stored_regs (reg, setter, data)
+     rtx reg;
+     rtx setter;
+     void *data;
+{
+  register int regno, endregno, i;
+  enum machine_mode mode = GET_MODE (reg);
+  int word = 0;
+
+  if (GET_CODE (setter) == CLOBBER)
+    return;
+
+  while (GET_CODE (reg) == SUBREG)
+    {
+      word += SUBREG_WORD (reg);
+      reg = SUBREG_REG (reg);
+    }
+
+  if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+    return;
+
+  regno = REGNO (reg) + word;
+  endregno = regno + HARD_REGNO_NREGS (regno, mode);
+
+  for (i = regno; i < endregno; i++)
+    SET_REGNO_REG_SET ((regset) data, i);
+}
+
 /* Walk X and record all referenced registers in REFERENCED_REGS.  */
 static void
 mark_referenced_regs (x)
@@ -568,10 +565,11 @@ insert_restore (chain, before_p, regno, maxrestore)
      int regno;
      int maxrestore;
 {
-  int i;
+  int i, k;
   rtx pat = NULL_RTX;
   enum insn_code code = CODE_FOR_nothing;
   int numregs = 0;
+  struct insn_chain *new;
 
   /* A common failure mode if register status is not correct in the RTL
      is for this routine to be called with a REGNO we didn't expect to
@@ -589,7 +587,7 @@ insert_restore (chain, before_p, regno, maxrestore)
      backwards to the single register case.  */
   for (i = maxrestore; i > 0; i--)
     {
-      int j, k;
+      int j;
       int ok = 1;
 
       if (regno_save_mem[regno][i] == 0)
@@ -605,24 +603,26 @@ insert_restore (chain, before_p, regno, maxrestore)
       if (! ok)
        continue;
 
-      pat = gen_rtx_SET (VOIDmode,
-                        gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]), 
-                                     regno), 
-                        regno_save_mem[regno][i]);
-      code = reg_restore_code[regno][i];
-
-      /* Clear status for all registers we restored.  */
-      for (k = 0; k < i; k++)
-       {
-         CLEAR_HARD_REG_BIT (hard_regs_saved, regno + k);
-         n_regs_saved--;
-       }
-
       numregs = i;
       break;
     }
 
-  insert_one_insn (chain, before_p, code, pat);
+  pat = gen_rtx_SET (VOIDmode,
+                    gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]), 
+                                 regno), 
+                    regno_save_mem[regno][numregs]);
+  code = reg_restore_code[regno][numregs];
+  new = insert_one_insn (chain, before_p, code, pat);
+
+  /* Clear status for all registers we restored.  */
+  for (k = 0; k < i; k++)
+    {
+      CLEAR_HARD_REG_BIT (hard_regs_saved, regno + k);
+      SET_REGNO_REG_SET (new->dead_or_set, regno + k);
+      n_regs_saved--;
+    }
+
+
 
   /* Tell our callers how many extra registers we saved/restored */
   return numregs - 1;
@@ -636,10 +636,11 @@ insert_save (chain, before_p, regno, to_save)
      int regno;
      HARD_REG_SET *to_save;
 {
-  int i;
+  int i, k;
   rtx pat = NULL_RTX;
   enum insn_code code = CODE_FOR_nothing;
   int numregs = 0;
+  struct insn_chain *new;
 
   /* A common failure mode if register status is not correct in the RTL
      is for this routine to be called with a REGNO we didn't expect to
@@ -657,7 +658,7 @@ insert_save (chain, before_p, regno, to_save)
      Work backwards to the single register case.  */
   for (i = MOVE_MAX_WORDS; i > 0; i--)
     {
-      int j, k;
+      int j;
       int ok = 1;
       if (regno_save_mem[regno][i] == 0)
        continue;
@@ -672,30 +673,30 @@ insert_save (chain, before_p, regno, to_save)
       if (! ok)
        continue;
 
-      pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
-                        gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
-                                     regno));
-      code = reg_save_code[regno][i];
-
-      /* Set hard_regs_saved for all the registers we saved.  */
-      for (k = 0; k < i; k++)
-       {
-         SET_HARD_REG_BIT (hard_regs_saved, regno + k);
-         n_regs_saved++;
-       }
-
       numregs = i;
       break;
     }
 
-  insert_one_insn (chain, before_p, code, pat);
+  pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][numregs],
+                    gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]),
+                                 regno));
+  code = reg_save_code[regno][numregs];
+  new = insert_one_insn (chain, before_p, code, pat);
+
+  /* Set hard_regs_saved and dead_or_set for all the registers we saved.  */
+  for (k = 0; k < numregs; k++)
+    {
+      SET_HARD_REG_BIT (hard_regs_saved, regno + k);
+      SET_REGNO_REG_SET (new->dead_or_set, regno + k);
+      n_regs_saved++;
+    }
 
   /* Tell our callers how many extra registers we saved/restored */
   return numregs - 1;
 }
 
 /* Emit a new caller-save insn and set the code.  */
-static void
+static struct insn_chain *
 insert_one_insn (chain, before_p, code, pat)
      struct insn_chain *chain;
      int before_p;
@@ -721,6 +722,8 @@ insert_one_insn (chain, before_p, code, pat)
   new = new_insn_chain ();
   if (before_p)
     {
+      rtx link;
+
       new->prev = chain->prev;
       if (new->prev != 0)
        new->prev->next = new;
@@ -732,8 +735,29 @@ insert_one_insn (chain, before_p, code, pat)
       new->insn = emit_insn_before (pat, insn);
       /* ??? It would be nice if we could exclude the already / still saved
         registers from the live sets.  */
-      COPY_REG_SET (new->live_before, chain->live_before);
-      COPY_REG_SET (new->live_after, chain->live_before);
+      COPY_REG_SET (new->live_throughout, chain->live_throughout);
+      /* Registers that die in CHAIN->INSN still live in the new insn.  */
+      for (link = REG_NOTES (chain->insn); link; link = XEXP (link, 1))
+       {
+         if (REG_NOTE_KIND (link) == REG_DEAD)
+           {
+             rtx reg = XEXP (link, 0);
+             int regno, i;
+
+             if (GET_CODE (reg) != REG)
+               abort ();
+
+             regno = REGNO (reg);
+             if (regno >= FIRST_PSEUDO_REGISTER)
+               regno = reg_renumber[regno];
+             if (regno < 0)
+               continue;
+             for (i = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1;
+                  i >= 0; i--)
+               SET_REGNO_REG_SET (new->live_throughout, regno + i);
+           }
+       }
+      CLEAR_REG_SET (new->dead_or_set);
       if (chain->insn == BLOCK_HEAD (chain->block))
        BLOCK_HEAD (chain->block) = new->insn;
     }
@@ -747,8 +771,13 @@ insert_one_insn (chain, before_p, code, pat)
       new->insn = emit_insn_after (pat, insn);
       /* ??? It would be nice if we could exclude the already / still saved
         registers from the live sets, and observe REG_UNUSED notes.  */
-      COPY_REG_SET (new->live_before, chain->live_after);
-      COPY_REG_SET (new->live_after, chain->live_after);
+      COPY_REG_SET (new->live_throughout, chain->live_throughout);
+      /* Registers that are set in CHAIN->INSN live in the new insn.
+         (Unless there is a REG_UNUSED note for them, but we don't
+         look for them here.) */
+      note_stores (PATTERN (chain->insn), add_stored_regs,
+                  new->live_throughout);
+      CLEAR_REG_SET (new->dead_or_set);
       if (chain->insn == BLOCK_END (chain->block))
        BLOCK_END (chain->block) = new->insn;
     }
@@ -756,4 +785,5 @@ insert_one_insn (chain, before_p, code, pat)
   new->is_caller_save_insn = 1;
 
   INSN_CODE (new->insn) = code;
+  return new;
 }
index c46c2970e4587437be925bc03850ff6c7cc23535..04058290cc6022888bdc597abf56cb403620146e 100644 (file)
@@ -303,7 +303,8 @@ static void mark_reg_live_nc        PROTO((int, enum machine_mode));
 static void set_preference     PROTO((rtx, rtx));
 static void dump_conflicts     PROTO((FILE *));
 static void reg_becomes_live   PROTO((rtx, rtx, void *));
-static void reg_dies           PROTO((int, enum machine_mode));
+static void reg_dies           PROTO((int, enum machine_mode,
+                                      struct insn_chain *));
 static void build_insn_chain   PROTO((rtx));
 \f
 /* Perform allocation of pseudo-registers not allocated by local_alloc.
@@ -1693,13 +1694,13 @@ mark_elimination (from, to)
    current life information.  */
 static regset live_relevant_regs;
 
-/* Record in live_relevant_regs that register REG became live.  This
-   is called via note_stores.  */
+/* Record in live_relevant_regs and REGS_SET that register REG became live.
+   This is called via note_stores.  */
 static void
-reg_becomes_live (reg, setter, data)
+reg_becomes_live (reg, setter, regs_set)
      rtx reg;
      rtx setter ATTRIBUTE_UNUSED;
-     void *data ATTRIBUTE_UNUSED;
+     void *regs_set;
 {
   int regno;
 
@@ -1714,26 +1715,44 @@ reg_becomes_live (reg, setter, data)
     {
       int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
       while (nregs-- > 0)
-       SET_REGNO_REG_SET (live_relevant_regs, regno++);
+       {
+         SET_REGNO_REG_SET (live_relevant_regs, regno);
+         if (! fixed_regs[regno])
+           SET_REGNO_REG_SET ((regset) regs_set, regno);
+         regno++;
+       }
     }
   else if (reg_renumber[regno] >= 0)
-    SET_REGNO_REG_SET (live_relevant_regs, regno);
+    {
+      SET_REGNO_REG_SET (live_relevant_regs, regno);
+      SET_REGNO_REG_SET ((regset) regs_set, regno);
+    }
 }
 
 /* Record in live_relevant_regs that register REGNO died.  */
 static void
-reg_dies (regno, mode)
+reg_dies (regno, mode, chain)
      int regno;
      enum machine_mode mode;
+     struct insn_chain *chain;
 {
   if (regno < FIRST_PSEUDO_REGISTER)
     {
       int nregs = HARD_REGNO_NREGS (regno, mode);
       while (nregs-- > 0)
-       CLEAR_REGNO_REG_SET (live_relevant_regs, regno++);
+       {
+         CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
+         if (! fixed_regs[regno])
+           SET_REGNO_REG_SET (chain->dead_or_set, regno);
+         regno++;
+       }
     }
   else
-    CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
+    {
+      CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
+      if (reg_renumber[regno] >= 0)
+       SET_REGNO_REG_SET (chain->dead_or_set, regno);
+    }
 }
 
 /* Walk the insns of the current function and build reload_insn_chain,
@@ -1778,8 +1797,6 @@ build_insn_chain (first)
          c->insn = first;
          c->block = b;
 
-         COPY_REG_SET (c->live_before, live_relevant_regs);
-
          if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
            {
              rtx link;
@@ -1789,16 +1806,18 @@ build_insn_chain (first)
              for (link = REG_NOTES (first); link; link = XEXP (link, 1))
                if (REG_NOTE_KIND (link) == REG_DEAD
                    && GET_CODE (XEXP (link, 0)) == REG)
-                 reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+                 reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)),
+                           c);
+
+             COPY_REG_SET (c->live_throughout, live_relevant_regs);
 
              /* Mark everything born in this instruction as live.  */
 
-             note_stores (PATTERN (first), reg_becomes_live, NULL);
+             note_stores (PATTERN (first), reg_becomes_live,
+                          c->dead_or_set);
            }
-
-         /* Remember which registers are live at the end of the insn, before
-            killing those with REG_UNUSED notes.  */
-         COPY_REG_SET (c->live_after, live_relevant_regs);
+         else
+           COPY_REG_SET (c->live_throughout, live_relevant_regs);
 
          if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
            {
@@ -1809,7 +1828,8 @@ build_insn_chain (first)
              for (link = REG_NOTES (first); link; link = XEXP (link, 1))
                if (REG_NOTE_KIND (link) == REG_UNUSED
                    && GET_CODE (XEXP (link, 0)) == REG)
-                 reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
+                 reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)),
+                           c);
            }
        }
 
index 52ede8dd9aea580347574533e28042c0b7adc5eb..391c047c882c0c6fae4f180063583ba56b1a4a15 100644 (file)
@@ -224,12 +224,9 @@ struct insn_chain
   /* The rtx of the insn.  */
   rtx insn;
   /* Register life information: record all live hard registers, and all
-     live pseudos that have a hard register.
-     This information is recorded for the point immediately before the insn
-     (in live_before), and for the point within the insn at which all
-     outputs have just been written to (in live_after).  */
-  regset live_before;
-  regset live_after;
+     live pseudos that have a hard register.  */
+  regset live_throughout;
+  regset dead_or_set;
 
   /* Copies of the global variables computed by find_reloads.  */
   struct reload *rld;
index bedcebb5d16221c76a8970c92861e6b6c57c0e16..dc690852a11dc1c84f2d93138c28f3bef6ae99d3 100644 (file)
@@ -514,8 +514,8 @@ new_insn_chain ()
     {
       c = (struct insn_chain *)
        obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
-      c->live_before = OBSTACK_ALLOC_REG_SET (&reload_obstack);
-      c->live_after = OBSTACK_ALLOC_REG_SET (&reload_obstack);
+      c->live_throughout = OBSTACK_ALLOC_REG_SET (&reload_obstack);
+      c->dead_or_set = OBSTACK_ALLOC_REG_SET (&reload_obstack);
     }
   else
     {
@@ -1295,8 +1295,8 @@ maybe_fix_stack_asms ()
       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
        if (TEST_HARD_REG_BIT (allowed, i))
          {
-           CLEAR_REGNO_REG_SET (chain->live_before, i);
-           CLEAR_REGNO_REG_SET (chain->live_after, i);
+           CLEAR_REGNO_REG_SET (chain->live_throughout, i);
+           CLEAR_REGNO_REG_SET (chain->dead_or_set, i);
          }
     }
 
@@ -1516,8 +1516,8 @@ order_regs_for_reload (chain)
       /* Test the various reasons why we can't use a register for
         spilling in this insn.  */
       if (fixed_regs[i]
-         || REGNO_REG_SET_P (chain->live_before, i)
-         || REGNO_REG_SET_P (chain->live_after, i))
+         || REGNO_REG_SET_P (chain->live_throughout, i)
+         || REGNO_REG_SET_P (chain->dead_or_set, i))
        SET_HARD_REG_BIT (bad_spill_regs, i);
     }
   /* Now find out which pseudos are allocated to it, and update
@@ -1525,12 +1525,12 @@ order_regs_for_reload (chain)
   CLEAR_REG_SET (&pseudos_counted);
 
   EXECUTE_IF_SET_IN_REG_SET
-    (chain->live_before, FIRST_PSEUDO_REGISTER, j,
+    (chain->live_throughout, FIRST_PSEUDO_REGISTER, j,
      {
        count_pseudo (j);
      });
   EXECUTE_IF_SET_IN_REG_SET
-    (chain->live_after, FIRST_PSEUDO_REGISTER, j,
+    (chain->dead_or_set, FIRST_PSEUDO_REGISTER, j,
      {
        count_pseudo (j);
      });
@@ -1645,12 +1645,12 @@ find_reg (chain, order, dumpfile)
   rl->regno = best_reg;
 
   EXECUTE_IF_SET_IN_REG_SET
-    (chain->live_before, FIRST_PSEUDO_REGISTER, j,
+    (chain->live_throughout, FIRST_PSEUDO_REGISTER, j,
      {
        count_spilled_pseudo (best_reg, rl->nregs, j);
      });
   EXECUTE_IF_SET_IN_REG_SET
-    (chain->live_after, FIRST_PSEUDO_REGISTER, j,
+    (chain->dead_or_set, FIRST_PSEUDO_REGISTER, j,
      {
        count_spilled_pseudo (best_reg, rl->nregs, j);
      });
@@ -3489,13 +3489,13 @@ finish_spills (global, dumpfile)
       for (chain = insns_need_reload; chain; chain = chain->next_need_reload)
        {
          EXECUTE_IF_SET_IN_REG_SET
-           (chain->live_before, FIRST_PSEUDO_REGISTER, i,
+           (chain->live_throughout, FIRST_PSEUDO_REGISTER, i,
             {
               ior_hard_reg_set (pseudo_forbidden_regs + i,
                                 &chain->used_spill_regs);
             });
          EXECUTE_IF_SET_IN_REG_SET
-           (chain->live_after, FIRST_PSEUDO_REGISTER, i,
+           (chain->dead_or_set, FIRST_PSEUDO_REGISTER, i,
             {
               ior_hard_reg_set (pseudo_forbidden_regs + i,
                                 &chain->used_spill_regs);
@@ -3528,22 +3528,22 @@ finish_spills (global, dumpfile)
       HARD_REG_SET used_by_pseudos;
       HARD_REG_SET used_by_pseudos2;
 
-      AND_COMPL_REG_SET (chain->live_before, &spilled_pseudos);
-      AND_COMPL_REG_SET (chain->live_after, &spilled_pseudos);
+      AND_COMPL_REG_SET (chain->live_throughout, &spilled_pseudos);
+      AND_COMPL_REG_SET (chain->dead_or_set, &spilled_pseudos);
 
       /* Mark any unallocated hard regs as available for spills.  That
         makes inheritance work somewhat better.  */
       if (chain->need_reload)
        {
-         REG_SET_TO_HARD_REG_SET (used_by_pseudos, chain->live_before);
-         REG_SET_TO_HARD_REG_SET (used_by_pseudos2, chain->live_after);
+         REG_SET_TO_HARD_REG_SET (used_by_pseudos, chain->live_throughout);
+         REG_SET_TO_HARD_REG_SET (used_by_pseudos2, chain->dead_or_set);
          IOR_HARD_REG_SET (used_by_pseudos, used_by_pseudos2);
 
          /* Save the old value for the sanity test below.  */
          COPY_HARD_REG_SET (used_by_pseudos2, chain->used_spill_regs);
 
-         compute_use_by_pseudos (&used_by_pseudos, chain->live_before);
-         compute_use_by_pseudos (&used_by_pseudos, chain->live_after);
+         compute_use_by_pseudos (&used_by_pseudos, chain->live_throughout);
+         compute_use_by_pseudos (&used_by_pseudos, chain->dead_or_set);
          COMPL_HARD_REG_SET (chain->used_spill_regs, used_by_pseudos);
          AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs);
 
@@ -5033,12 +5033,12 @@ choose_reload_regs_init (chain, save_reload_reg_rtx)
   CLEAR_HARD_REG_SET (reg_used_in_insn);
   {
     HARD_REG_SET tmp;
-    REG_SET_TO_HARD_REG_SET (tmp, chain->live_before);
+    REG_SET_TO_HARD_REG_SET (tmp, chain->live_throughout);
     IOR_HARD_REG_SET (reg_used_in_insn, tmp);
-    REG_SET_TO_HARD_REG_SET (tmp, chain->live_after);
+    REG_SET_TO_HARD_REG_SET (tmp, chain->dead_or_set);
     IOR_HARD_REG_SET (reg_used_in_insn, tmp);
-    compute_use_by_pseudos (&reg_used_in_insn, chain->live_before);
-    compute_use_by_pseudos (&reg_used_in_insn, chain->live_after);
+    compute_use_by_pseudos (&reg_used_in_insn, chain->live_throughout);
+    compute_use_by_pseudos (&reg_used_in_insn, chain->dead_or_set);
   }
   for (i = 0; i < reload_n_operands; i++)
     {
index 61bac12d597beab68b60be79dd8ca46c30a32774..a4392e4ab0fe05c92ee730eb144da26be885057d 100644 (file)
@@ -129,12 +129,13 @@ static int stupid_find_reg        PROTO((int, enum reg_class, enum machine_mode,
                                       int, int, int));
 static void stupid_mark_refs   PROTO((rtx, struct insn_chain *));
 static void find_clobbered_regs        PROTO((rtx, rtx, void *));
+static void mark_hard_ref      PROTO((rtx, int, struct insn_chain *));
 \f
 /* For communication between stupid_life_analysis and find_clobbered_regs.  */
 static struct insn_chain *current_chain;
 
 /* This function, called via note_stores, marks any hard registers that are
-   clobbered in an insn as being live in the live_after and live_before fields
+   clobbered in an insn as being live in the live_throughout field
    of the appropriate insn_chain structure.  */
 
 static void
@@ -161,8 +162,7 @@ find_clobbered_regs (reg, setter, data)
     nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
   while (nregs-- > 0)
     {
-      SET_REGNO_REG_SET (current_chain->live_after, regno);
-      SET_REGNO_REG_SET (current_chain->live_before, regno++);
+      SET_REGNO_REG_SET (current_chain->live_throughout, regno++);
     }
 }
 \f
@@ -285,7 +285,7 @@ stupid_life_analysis (f, nregs, file)
          chain->insn = insn;
          for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
            if (regs_live[i])
-             SET_REGNO_REG_SET (chain->live_before, i);
+             SET_REGNO_REG_SET (chain->live_throughout, i);
        }
 
       /* Update which hard regs are currently live
@@ -336,10 +336,6 @@ stupid_life_analysis (f, nregs, file)
 
       if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER)
        {         
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           if (regs_live[i])
-             SET_REGNO_REG_SET (chain->live_after, i);
-
          /* The regs_live array doesn't say anything about hard registers
             clobbered by this insn.  So we need an extra pass over the
             pattern.  */
@@ -407,21 +403,14 @@ stupid_life_analysis (f, nregs, file)
        continue;
 
       chain = reg_where_dead_chain[i];
-      if (reg_where_dead[i] > INSN_SUID (chain->insn))
-       SET_REGNO_REG_SET (chain->live_after, i);
+      SET_REGNO_REG_SET (chain->dead_or_set, i);
 
-      while (INSN_SUID (chain->insn) > reg_where_born_exact[i])
-       {
-         SET_REGNO_REG_SET (chain->live_before, i);
-         chain = chain->prev;
-         if (!chain)
-           break;
-         SET_REGNO_REG_SET (chain->live_after, i);
-       }
+      while ((chain = chain->prev)
+            && INSN_SUID (chain->insn) > reg_where_born_exact[i])
+       SET_REGNO_REG_SET (chain->live_throughout, i);
 
-      if (INSN_SUID (chain->insn) == reg_where_born_exact[i]
-         && reg_where_born_clobber[i])
-       SET_REGNO_REG_SET (chain->live_before, i);
+      if (chain)
+       SET_REGNO_REG_SET (chain->dead_or_set, i);
     }
 
   if (file)
@@ -568,6 +557,32 @@ stupid_find_reg (call_preserved, class, mode,
   return -1;
 }
 \f
+/* Note that REG is being set or referenced, and add the appropriate
+   REG_DEAD / REG_UNUSED note(s).  For sets, LIVE_BEFORE_P will be 0,
+   while for references, LIVE_BEFORE_P will be 1.
+   INSN is the instruction that the reg notes have to be added to.  */
+static void
+mark_hard_ref (reg, live_before_p, chain)
+     rtx reg;
+     int live_before_p;
+     struct insn_chain *chain;
+{
+  /* Hard reg: mark it live for continuing scan of previous insns.  */
+  int regno = REGNO (reg);
+  char *live = regs_live;
+  register int j;
+  int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+
+  for (j = nregs - 1; j >= 0; j--)
+    {
+      if (! fixed_regs[regno+j]
+         && (! live_before_p || ! live[regno+j]))
+       SET_REGNO_REG_SET (chain->dead_or_set, regno+j);
+      regs_ever_live[regno+j] = 1;
+      live[regno+j] = live_before_p;
+    }
+}
+
 /* Walk X, noting all assignments and references to registers
    and recording what they imply about life spans.
    INSN is the current insn, supplied so we can find its suid.  */
@@ -597,11 +612,13 @@ stupid_mark_refs (x, chain)
                      >= FIRST_PSEUDO_REGISTER))))
        {
          /* Register is being assigned.  */
+         rtx reg = SET_DEST (x);
+
          /* If setting a SUBREG, we treat the entire reg as being set.  */
          if (GET_CODE (SET_DEST (x)) == SUBREG)
-           regno = REGNO (SUBREG_REG (SET_DEST (x)));
-         else
-           regno = REGNO (SET_DEST (x));
+           reg = SUBREG_REG (reg);
+
+         regno = REGNO (reg);
 
          /* For hard regs, update the where-live info.  */
          if (regno < FIRST_PSEUDO_REGISTER)
@@ -609,15 +626,16 @@ stupid_mark_refs (x, chain)
              register int j
                = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (x)));
 
+             mark_hard_ref (reg, 0, chain);
+
              while (--j >= 0)
                {
-                 regs_ever_live[regno+j] = 1;
-                 regs_live[regno+j] = 0;
-
                  /* The following line is for unused outputs;
                     they do get stored even though never used again.  */
                  MARK_LIVE_AFTER (insn, regno+j);
 
+                 CLEAR_REGNO_REG_SET (chain->live_throughout, regno + j);
+
                  /* When a hard reg is clobbered, mark it in use
                     just before this insn, so it is live all through.  */
                  if (code == CLOBBER && INSN_SUID (insn) > 0)
@@ -706,15 +724,8 @@ stupid_mark_refs (x, chain)
     {
       regno = REGNO (x);
       if (regno < FIRST_PSEUDO_REGISTER)
-       {
-         /* Hard reg: mark it live for continuing scan of previous insns.  */
-         register int j = HARD_REGNO_NREGS (regno, GET_MODE (x));
-         while (--j >= 0)
-           {
-             regs_ever_live[regno+j] = 1;
-             regs_live[regno+j] = 1;
-           }
-       }
+       /* Hard reg: mark it live for continuing scan of previous insns.  */
+       mark_hard_ref (x, 1, chain);
       else
        {
          /* Pseudo reg: record first use, last use and number of uses.  */