OSDN Git Service

* mkconfig.sh: Include insn-flags.h.
[pf3gnuchains/gcc-fork.git] / gcc / resource.c
index af1b4ed..de1189d 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions for computing resource usage of specific insns.
-   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -30,7 +30,9 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "output.h"
 #include "resource.h"
+#include "except.h"
 #include "insn-attr.h"
+#include "params.h"
 
 /* This structure is used to record liveness information at the targets or
    fallthrough insns of branches.  We will most likely need the information
@@ -65,7 +67,7 @@ static struct target_info **target_hash_table = NULL;
 static int *bb_ticks;
 
 /* Marks registers possibly live at the current place being scanned by
-   mark_target_live_regs.  Used only by next two function.    */
+   mark_target_live_regs.  Also used by update_live_status.  */
 
 static HARD_REG_SET current_live_regs;
 
@@ -75,7 +77,7 @@ static HARD_REG_SET current_live_regs;
 static HARD_REG_SET pending_dead_regs;
 \f
 static void update_live_status         PARAMS ((rtx, rtx, void *));
-static int find_basic_block            PARAMS ((rtx));
+static int find_basic_block            PARAMS ((rtx, int));
 static rtx next_insn_no_annul          PARAMS ((rtx));
 static rtx find_dead_or_set_registers  PARAMS ((rtx, struct resources*,
                                                rtx*, int, struct resources,
@@ -114,25 +116,38 @@ update_live_status (dest, x, data)
        CLEAR_HARD_REG_BIT (pending_dead_regs, i);
       }
 }
-/* Find the number of the basic block that starts closest to INSN.  Return -1
-   if we couldn't find such a basic block.  */
+
+/* Find the number of the basic block with correct live register
+   information that starts closest to INSN.  Return -1 if we couldn't
+   find such a basic block or the beginning is more than
+   SEARCH_LIMIT instructions before INSN.  Use SEARCH_LIMIT = -1 for
+   an unlimited search.
+
+   The delay slot filling code destroys the control-flow graph so,
+   instead of finding the basic block containing INSN, we search
+   backwards toward a BARRIER where the live register information is
+   correct.  */
 
 static int
-find_basic_block (insn)
+find_basic_block (insn, search_limit)
      rtx insn;
+     int search_limit;
 {
   int i;
 
   /* Scan backwards to the previous BARRIER.  Then see if we can find a
      label that starts a basic block.  Return the basic block number.  */
-
   for (insn = prev_nonnote_insn (insn);
-       insn && GET_CODE (insn) != BARRIER;
-       insn = prev_nonnote_insn (insn))
+       insn && GET_CODE (insn) != BARRIER && search_limit != 0;
+       insn = prev_nonnote_insn (insn), --search_limit)
     ;
 
+  /* The closest BARRIER is too far away.  */
+  if (search_limit == 0)
+    return -1;
+
   /* The start of the function is basic block zero.  */
-  if (insn == 0)
+  else if (insn == 0)
     return 0;
 
   /* See if any of the upcoming CODE_LABELs start a basic block.  If we reach
@@ -175,7 +190,7 @@ next_insn_no_annul (insn)
 }
 \f
 /* Given X, some rtl, and RES, a pointer to a `struct resource', mark
-   which resources are references by the insn.  If INCLUDE_DELAYED_EFFECTS
+   which resources are referenced by the insn.  If INCLUDE_DELAYED_EFFECTS
    is TRUE, resources used by the called routine will be included for
    CALL_INSNs.  */
 
@@ -211,14 +226,24 @@ mark_referenced_resources (x, res, include_delayed_effects)
          unsigned int last_regno
            = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
 
+         if (last_regno > FIRST_PSEUDO_REGISTER)
+           abort ();
          for (r = regno; r < last_regno; r++)
            SET_HARD_REG_BIT (res->regs, r);
        }
       return;
 
     case REG:
-      for (r = 0; r < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); r++)
-       SET_HARD_REG_BIT (res->regs, REGNO (x) + r);
+       {
+         unsigned int regno = REGNO (x);
+         unsigned int last_regno
+           = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+         if (last_regno > FIRST_PSEUDO_REGISTER)
+           abort ();
+         for (r = regno; r < last_regno; r++)
+           SET_HARD_REG_BIT (res->regs, r);
+       }
       return;
 
     case MEM:
@@ -451,7 +476,7 @@ find_dead_or_set_registers (target, res, jump_target, jump_count, set, needed)
              /* If INSN is a USE made by update_block, we care about the
                 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')
+             if (INSN_P (XEXP (PATTERN (insn), 0)))
                mark_set_resources (XEXP (PATTERN (insn), 0), res, 0,
                                    MARK_SRC_DEST_CALL);
 
@@ -720,6 +745,13 @@ mark_set_resources (x, res, in_dest, mark_type)
       mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
       return;
 
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      mark_set_resources (XEXP (x, 0), res, 1, MARK_SRC_DEST);
+      mark_set_resources (XEXP (XEXP (x, 1), 0), res, 0, MARK_SRC_DEST);
+      mark_set_resources (XEXP (XEXP (x, 1), 1), res, 0, MARK_SRC_DEST);
+      return;
+
     case SIGN_EXTRACT:
     case ZERO_EXTRACT:
       if (! (mark_type == MARK_DEST && in_dest))
@@ -752,6 +784,8 @@ mark_set_resources (x, res, in_dest, mark_type)
              unsigned int last_regno
                = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
 
+             if (last_regno > FIRST_PSEUDO_REGISTER)
+               abort ();
              for (r = regno; r < last_regno; r++)
                SET_HARD_REG_BIT (res->regs, r);
            }
@@ -760,8 +794,16 @@ mark_set_resources (x, res, in_dest, mark_type)
 
     case REG:
       if (in_dest)
-        for (r = 0; r < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); r++)
-         SET_HARD_REG_BIT (res->regs, REGNO (x) + r);
+       {
+         unsigned int regno = REGNO (x);
+         unsigned int last_regno
+           = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+
+         if (last_regno > FIRST_PSEUDO_REGISTER)
+           abort ();
+         for (r = regno; r < last_regno; r++)
+           SET_HARD_REG_BIT (res->regs, r);
+       }
       return;
 
     case STRICT_LOW_PART:
@@ -897,7 +939,7 @@ mark_target_live_regs (insns, target, res)
     }
 
   if (b == -1)
-    b = find_basic_block (target);
+    b = find_basic_block (target, MAX_DELAY_SLOT_LIVE_SEARCH);
 
   if (target_hash_table != NULL)
     {
@@ -915,7 +957,7 @@ mark_target_live_regs (insns, target, res)
        {
          /* Allocate a place to put our results and chain it into the 
             hash table.  */
-         tinfo = (struct target_info *) oballoc (sizeof (struct target_info));
+         tinfo = (struct target_info *) xmalloc (sizeof (struct target_info));
          tinfo->uid = INSN_UID (target);
          tinfo->block = b;
          tinfo->next = target_hash_table[INSN_UID (target) % TARGET_HASH_PRIME];
@@ -983,7 +1025,7 @@ mark_target_live_regs (insns, target, res)
          /* If this insn is a USE made by update_block, we care about the
             underlying insn.  */
          if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == USE
-             && GET_RTX_CLASS (GET_CODE (XEXP (PATTERN (insn), 0))) == 'i')
+             && INSN_P (XEXP (PATTERN (insn), 0)))
              real_insn = XEXP (PATTERN (insn), 0);
 
          if (GET_CODE (real_insn) == CALL_INSN)
@@ -1001,7 +1043,7 @@ mark_target_live_regs (insns, target, res)
 #if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM
                    && ! (i == ARG_POINTER_REGNUM && fixed_regs[i])
 #endif
-#if defined (PIC_OFFSET_TABLE_REGNUM) && !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
+#if !defined (PIC_OFFSET_TABLE_REG_CALL_CLOBBERED)
                    && ! (i == PIC_OFFSET_TABLE_REGNUM && flag_pic)
 #endif
                    )
@@ -1215,6 +1257,20 @@ free_resource_info ()
 {
   if (target_hash_table != NULL)
     {
+      int i;
+      
+      for (i = 0; i < TARGET_HASH_PRIME; ++i) 
+       {
+         struct target_info *ti = target_hash_table[i];
+
+         while (ti) 
+           {
+             struct target_info *next = ti->next;
+             free (ti);
+             ti = next;
+           }
+       }
+
       free (target_hash_table);
       target_hash_table = NULL;
     }
@@ -1252,7 +1308,7 @@ void
 incr_ticks_for_insn (insn)
      rtx insn;
 {
-  int b = find_basic_block (insn);
+  int b = find_basic_block (insn, MAX_DELAY_SLOT_LIVE_SEARCH);
 
   if (b != -1)
     bb_ticks[b]++;