OSDN Git Service

2000-07-21 Alexandre Petit-Bianco <apbianco@cygnus.com>
[pf3gnuchains/gcc-fork.git] / gcc / resource.c
index 9d58086..ae89d62 100644 (file)
@@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "output.h"
 #include "resource.h"
+#include "except.h"
 #include "insn-attr.h"
 
 /* This structure is used to record liveness information at the targets or
@@ -185,8 +186,9 @@ mark_referenced_resources (x, res, include_delayed_effects)
      register struct resources *res;
      register int include_delayed_effects;
 {
-  register enum rtx_code code = GET_CODE (x);
-  register int i, j;
+  enum rtx_code code = GET_CODE (x);
+  int i, j;
+  unsigned int r;
   register const char *format_ptr;
 
   /* Handle leaf items for which we set resource flags.  Also, special-case
@@ -206,16 +208,18 @@ mark_referenced_resources (x, res, include_delayed_effects)
        mark_referenced_resources (SUBREG_REG (x), res, 0);
       else
        {
-         int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
-         int last_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
-         for (i = regno; i < last_regno; i++)
-           SET_HARD_REG_BIT (res->regs, i);
+         unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+         unsigned int last_regno
+           = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+         for (r = regno; r < last_regno; r++)
+           SET_HARD_REG_BIT (res->regs, r);
        }
       return;
 
     case REG:
-      for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
-       SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
+      for (r = 0; r < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); r++)
+       SET_HARD_REG_BIT (res->regs, REGNO (x) + r);
       return;
 
     case MEM:
@@ -419,6 +423,14 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
       rtx this_jump_insn = insn;
 
       next = NEXT_INSN (insn);
+
+      /* If this instruction can throw an exception, then we don't
+        know where we might end up next.  That means that we have to
+        assume that whatever we have already marked as live really is
+        live.  */
+      if (can_throw (insn))
+       break;
+
       switch (GET_CODE (insn))
        {
        case CODE_LABEL:
@@ -441,7 +453,8 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
                 underlying insn.  Any registers set by the underlying insn
                 are live since the insn is being done somewhere else.  */
              if (GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
-               mark_set_resources (XEXP (PATTERN (insn), 0), res, 0, 1);
+               mark_set_resources (XEXP (PATTERN (insn), 0), res, 0,
+                                   MARK_SRC_DEST_CALL);
 
              /* All other USE insns are to be ignored.  */
              continue;
@@ -468,7 +481,7 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
        {
          if (jump_count++ < 10)
            {
-             if (simplejump_p (this_jump_insn)
+             if (any_uncondjump_p (this_jump_insn)
                  || GET_CODE (PATTERN (this_jump_insn)) == RETURN)
                {
                  next = JUMP_LABEL (this_jump_insn);
@@ -479,8 +492,7 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
                        *jump_target = JUMP_LABEL (this_jump_insn);
                    }
                }
-             else if (condjump_p (this_jump_insn)
-                      || condjump_in_parallel_p (this_jump_insn))
+             else if (any_condjump_p (this_jump_insn))
                {
                  struct resources target_set, target_res;
                  struct resources fallthrough_res;
@@ -515,17 +527,18 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
                          = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
 
                      target_set = set;
-                     mark_set_resources (insn, &target_set, 0, 1);
+                     mark_set_resources (insn, &target_set, 0,
+                                         MARK_SRC_DEST_CALL);
 
                      for (i = 1; i < XVECLEN (PATTERN (insn), 0); i++)
                        INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i))
                          = ! INSN_FROM_TARGET_P (XVECEXP (PATTERN (insn), 0, i));
 
-                     mark_set_resources (insn, &set, 0, 1);
+                     mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
                    }
                  else
                    {
-                     mark_set_resources (insn, &set, 0, 1);
+                     mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
                      target_set = set;
                    }
 
@@ -563,7 +576,7 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
        }
 
       mark_referenced_resources (insn, &needed, 1);
-      mark_set_resources (insn, &set, 0, 1);
+      mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
 
       COPY_HARD_REG_SET (scratch, set.regs);
       AND_COMPL_HARD_REG_SET (scratch, needed.regs);
@@ -575,8 +588,8 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
 \f
 /* Given X, a part of an insn, and a pointer to a `struct resource',
    RES, indicate which resources are modified by the insn. If
-   INCLUDE_DELAYED_EFFECTS is nonzero, also mark resources potentially
-   set by the called routine.
+   MARK_TYPE is MARK_SRC_DEST_CALL, also mark resources potentially
+   set by the called routine.  If MARK_TYPE is MARK_DEST, only mark SET_DESTs
 
    If IN_DEST is nonzero, it means we are inside a SET.  Otherwise,
    objects are being referenced instead of set.
@@ -588,15 +601,16 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
    our computation and thus may be placed in a delay slot.   */
 
 void
-mark_set_resources (x, res, in_dest, include_delayed_effects)
+mark_set_resources (x, res, in_dest, mark_type)
      register rtx x;
      register struct resources *res;
      int in_dest;
-     int include_delayed_effects;
+     enum mark_resource_type mark_type;
 {
-  register enum rtx_code code;
-  register int i, j;
-  register const char *format_ptr;
+  enum rtx_code code;
+  int i, j;
+  unsigned int r;
+  const char *format_ptr;
 
  restart:
 
@@ -627,16 +641,16 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
         that aren't saved across calls, global registers and anything
         explicitly CLOBBERed immediately after the CALL_INSN.  */
 
-      if (include_delayed_effects)
+      if (mark_type == MARK_SRC_DEST_CALL)
        {
          rtx next = NEXT_INSN (x);
          rtx prev = PREV_INSN (x);
          rtx link;
 
          res->cc = res->memory = 1;
-         for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-           if (call_used_regs[i] || global_regs[i])
-             SET_HARD_REG_BIT (res->regs, i);
+         for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
+           if (call_used_regs[r] || global_regs[r])
+             SET_HARD_REG_BIT (res->regs, r);
 
          /* If X is part of a delay slot sequence, then NEXT should be
             the first insn after the sequence.  */
@@ -646,7 +660,8 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
          for (link = CALL_INSN_FUNCTION_USAGE (x);
               link; link = XEXP (link, 1))
            if (GET_CODE (XEXP (link, 0)) == CLOBBER)
-             mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1, 0);
+             mark_set_resources (SET_DEST (XEXP (link, 0)), res, 1,
+                                 MARK_SRC_DEST);
 
          /* Check for a NOTE_INSN_SETJMP.  If it exists, then we must
             assume that this call can clobber any register.  */
@@ -664,7 +679,7 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
           and doesn't actually do anything, so we ignore it.  */
 
 #ifdef INSN_SETS_ARE_DELAYED
-      if (! include_delayed_effects
+      if (mark_type != MARK_SRC_DEST_CALL
          && INSN_SETS_ARE_DELAYED (x))
        return;
 #endif
@@ -680,36 +695,40 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
         effects of the calling routine.  */
 
       mark_set_resources (SET_DEST (x), res,
-                         (include_delayed_effects
+                         (mark_type == MARK_SRC_DEST_CALL
                           || GET_CODE (SET_SRC (x)) != CALL),
-                         0);
+                         mark_type);
 
-      mark_set_resources (SET_SRC (x), res, 0, 0);
+      if (mark_type != MARK_DEST)
+       mark_set_resources (SET_SRC (x), res, 0, MARK_SRC_DEST);
       return;
 
     case CLOBBER:
-      mark_set_resources (XEXP (x, 0), res, 1, 0);
+      mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
       return;
       
     case SEQUENCE:
       for (i = 0; i < XVECLEN (x, 0); i++)
        if (! (INSN_ANNULLED_BRANCH_P (XVECEXP (x, 0, 0))
               && INSN_FROM_TARGET_P (XVECEXP (x, 0, i))))
-         mark_set_resources (XVECEXP (x, 0, i), res, 0,
-                             include_delayed_effects);
+         mark_set_resources (XVECEXP (x, 0, i), res, 0, mark_type);
       return;
 
     case POST_INC:
     case PRE_INC:
     case POST_DEC:
     case PRE_DEC:
-      mark_set_resources (XEXP (x, 0), res, 1, 0);
+      mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
       return;
 
+    case SIGN_EXTRACT:
     case ZERO_EXTRACT:
-      mark_set_resources (XEXP (x, 0), res, in_dest, 0);
-      mark_set_resources (XEXP (x, 1), res, 0, 0);
-      mark_set_resources (XEXP (x, 2), res, 0, 0);
+      if (! (mark_type == MARK_DEST && in_dest))
+       {
+         mark_set_resources (XEXP (x, 0), res, in_dest, MARK_SRC_DEST);
+         mark_set_resources (XEXP (x, 1), res, 0, MARK_SRC_DEST);
+         mark_set_resources (XEXP (x, 2), res, 0, MARK_SRC_DEST);
+       }
       return;
 
     case MEM:
@@ -720,31 +739,39 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
          res->volatil |= MEM_VOLATILE_P (x);
        }
 
-      mark_set_resources (XEXP (x, 0), res, 0, 0);
+      mark_set_resources (XEXP (x, 0), res, 0, MARK_SRC_DEST);
       return;
 
     case SUBREG:
       if (in_dest)
        {
          if (GET_CODE (SUBREG_REG (x)) != REG)
-           mark_set_resources (SUBREG_REG (x), res,
-                               in_dest, include_delayed_effects);
+           mark_set_resources (SUBREG_REG (x), res, in_dest, mark_type);
          else
            {
-             int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
-             int last_regno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
-             for (i = regno; i < last_regno; i++)
-               SET_HARD_REG_BIT (res->regs, i);
+             unsigned int regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+             unsigned int last_regno
+               = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+             for (r = regno; r < last_regno; r++)
+               SET_HARD_REG_BIT (res->regs, r);
            }
        }
       return;
 
     case REG:
       if (in_dest)
-        for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
-         SET_HARD_REG_BIT (res->regs, REGNO (x) + i);
+        for (r = 0; r < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); r++)
+         SET_HARD_REG_BIT (res->regs, REGNO (x) + r);
       return;
 
+    case STRICT_LOW_PART:
+      if (! (mark_type == MARK_DEST && in_dest))
+       {
+         mark_set_resources (XEXP (x, 0), res, 0, MARK_SRC_DEST);
+         return;
+       }
+
     case UNSPEC_VOLATILE:
     case ASM_INPUT:
       /* Traditional asm's are always volatile.  */
@@ -764,7 +791,8 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
         traditional asms unlike their normal usage.  */
       
       for (i = 0; i < ASM_OPERANDS_INPUT_LENGTH (x); i++)
-       mark_set_resources (ASM_OPERANDS_INPUT (x, i), res, in_dest, 0);
+       mark_set_resources (ASM_OPERANDS_INPUT (x, i), res, in_dest,
+                           MARK_SRC_DEST);
       return;
 
     default:
@@ -777,13 +805,12 @@ mark_set_resources (x, res, in_dest, include_delayed_effects)
     switch (*format_ptr++)
       {
       case 'e':
-       mark_set_resources (XEXP (x, i), res, in_dest, include_delayed_effects);
+       mark_set_resources (XEXP (x, i), res, in_dest, mark_type);
        break;
 
       case 'E':
        for (j = 0; j < XVECLEN (x, i); j++)
-         mark_set_resources (XVECEXP (x, i, j), res, in_dest,
-                             include_delayed_effects);
+         mark_set_resources (XVECEXP (x, i, j), res, in_dest, mark_type);
        break;
       }
 }
@@ -905,8 +932,8 @@ mark_target_live_regs (insns, target, res)
   if (b != -1)
     {
       regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
-      int j;
-      int regno;
+      unsigned int j;
+      unsigned int regno;
       rtx start_insn, stop_insn;
 
       /* Compute hard regs live at start of block -- this is the real hard regs
@@ -918,12 +945,15 @@ mark_target_live_regs (insns, target, res)
       EXECUTE_IF_SET_IN_REG_SET
        (regs_live, FIRST_PSEUDO_REGISTER, i,
         {
-          if ((regno = reg_renumber[i]) >= 0)
-            for (j = regno;
-                 j < regno + HARD_REGNO_NREGS (regno,
-                                               PSEUDO_REGNO_MODE (i));
-                 j++)
-              SET_HARD_REG_BIT (current_live_regs, j);
+          if (reg_renumber[i] >= 0)
+            {
+              regno = reg_renumber[i];
+              for (j = regno;
+                   j < regno + HARD_REGNO_NREGS (regno,
+                                                 PSEUDO_REGNO_MODE (i));
+                   j++)
+                SET_HARD_REG_BIT (current_live_regs, j);
+            }
         });
 
       /* Get starting and ending insn, handling the case where each might
@@ -1089,7 +1119,7 @@ mark_target_live_regs (insns, target, res)
          AND_COMPL_HARD_REG_SET (scratch, set.regs);
          IOR_HARD_REG_SET (new_resources.regs, scratch);
 
-         mark_set_resources (insn, &set, 0, 1);
+         mark_set_resources (insn, &set, 0, MARK_SRC_DEST_CALL);
        }
 
       IOR_HARD_REG_SET (res->regs, new_resources.regs);
@@ -1169,7 +1199,8 @@ init_resource_info (epilogue_insn)
   start_of_epilogue_needs = end_of_function_needs;
 
   while ((epilogue_insn = next_nonnote_insn (epilogue_insn)))
-    mark_set_resources (epilogue_insn, &end_of_function_needs, 0, 1);
+    mark_set_resources (epilogue_insn, &end_of_function_needs, 0,
+                       MARK_SRC_DEST_CALL);
 
   /* Allocate and initialize the tables used by mark_target_live_regs.  */
   target_hash_table = (struct target_info **)
@@ -1238,108 +1269,3 @@ mark_end_of_function_resources (trial, include_delayed_effects)
   mark_referenced_resources (trial, &end_of_function_needs,
                             include_delayed_effects);
 }
-\f
-/* Try to find a hard register of mode MODE, matching the register class in
-   CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
-   remains available until the end of LAST_INSN.  LAST_INSN may be NULL_RTX,
-   in which case the only condition is that the register must be available
-   before CURRENT_INSN.
-   Registers that already have bits set in REG_SET will not be considered.
-
-   If an appropriate register is available, it will be returned and the
-   corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
-   returned.  */
-
-rtx
-find_free_register (current_insn, last_insn, class_str, mode, reg_set)
-     rtx current_insn, last_insn;
-     const char *class_str;
-     int mode;
-     HARD_REG_SET *reg_set;
-{
-  int i, j;
-  struct resources used;
-  unsigned char clet = class_str[0];
-  enum reg_class class
-    = (clet == 'r' ? GENERAL_REGS :  REG_CLASS_FROM_LETTER (clet));
-
-  mark_target_live_regs (get_insns (), current_insn, &used);
-  if (last_insn)
-    while (current_insn != last_insn)
-      {
-       /* Exclude anything set in this insn.  */
-       mark_set_resources (PATTERN (current_insn), &used, 0, 1);
-       current_insn = next_nonnote_insn (current_insn);
-      }
-
-
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    {
-      int regno;
-      int success;
-
-#ifdef REG_ALLOC_ORDER
-      regno = reg_alloc_order [i];
-#else
-      regno = i;
-#endif
-
-      /* Don't allocate fixed registers.  */
-      if (fixed_regs[regno])
-       continue;
-      /* Make sure the register is of the right class.  */
-      if (! TEST_HARD_REG_BIT (reg_class_contents[class], regno))
-       continue;
-      /* And can support the mode we need.  */
-      if (! HARD_REGNO_MODE_OK (regno, mode))
-       continue;
-      /* And that we don't create an extra save/restore.  */
-      if (! call_used_regs[regno] && ! regs_ever_live[regno])
-       continue;
-      /* And we don't clobber traceback for noreturn functions.  */
-      if ((regno == FRAME_POINTER_REGNUM || regno == HARD_FRAME_POINTER_REGNUM)
-         && (! reload_completed || frame_pointer_needed))
-       continue;
-
-      success = 1;
-      for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
-       {
-         if (TEST_HARD_REG_BIT (*reg_set, regno + j)
-             || TEST_HARD_REG_BIT (used.regs, regno + j))
-           {
-             success = 0;
-             break;
-           }
-       }
-      if (success)
-       {
-         for (j = HARD_REGNO_NREGS (regno, mode) - 1; j >= 0; j--)
-           {
-             SET_HARD_REG_BIT (*reg_set, regno + j);
-           }
-         return gen_rtx_REG (mode, regno);
-       }
-    }
-  return NULL_RTX;
-}
-
-/* Return true if REG is dead at CURRENT_INSN.  */
-
-int
-reg_dead_p (current_insn, reg)
-     rtx current_insn, reg;
-{
-  struct resources used;
-  int regno, j;
-
-  mark_target_live_regs (get_insns (), current_insn, &used);
-  
-  regno = REGNO (reg);
-  for (j = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1; j >= 0; j--)
-    {
-      if (TEST_HARD_REG_BIT (used.regs, regno + j))
-       return 0;
-    }
-
-  return 1;
-}