OSDN Git Service

* decl.c (init_decl_processing): Remove duplicate decl of
[pf3gnuchains/gcc-fork.git] / gcc / resource.c
index 335b14e..274cb23 100644 (file)
@@ -1,5 +1,5 @@
 /* Definitions for computing resource usage of specific insns.
-   Copyright (C) 1999 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -30,6 +30,7 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "output.h"
 #include "resource.h"
+#include "insn-attr.h"
 
 /* This structure is used to record liveness information at the targets or
    fallthrough insns of branches.  We will most likely need the information
@@ -73,9 +74,10 @@ static HARD_REG_SET current_live_regs;
 
 static HARD_REG_SET pending_dead_regs;
 \f
-static void update_live_status         PROTO ((rtx, rtx, void *));
-static rtx next_insn_no_annul          PROTO ((rtx));
-static rtx find_dead_or_set_registers  PROTO ((rtx, struct resources*,
+static void update_live_status         PARAMS ((rtx, rtx, void *));
+static int find_basic_block            PARAMS ((rtx));
+static rtx next_insn_no_annul          PARAMS ((rtx));
+static rtx find_dead_or_set_registers  PARAMS ((rtx, struct resources*,
                                                rtx*, int, struct resources,
                                                struct resources));
 \f
@@ -112,6 +114,40 @@ 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.  */
+
+static int
+find_basic_block (insn)
+     rtx insn;
+{
+  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))
+    ;
+
+  /* The start of the function is basic block zero.  */
+  if (insn == 0)
+    return 0;
+
+  /* See if any of the upcoming CODE_LABELs start a basic block.  If we reach
+     anything other than a CODE_LABEL or note, we can't find this code.  */
+  for (insn = next_nonnote_insn (insn);
+       insn && GET_CODE (insn) == CODE_LABEL;
+       insn = next_nonnote_insn (insn))
+    {
+      for (i = 0; i < n_basic_blocks; i++)
+       if (insn == BLOCK_HEAD (i))
+         return i;
+    }
+
+  return -1;
+}
 \f
 /* Similar to next_insn, but ignores insns in the delay slots of
    an annulled branch.  */
@@ -236,7 +272,9 @@ mark_referenced_resources (x, res, include_delayed_effects)
       mark_referenced_resources (SET_SRC (x), res, 0);
 
       x = SET_DEST (x);
-      if (GET_CODE (x) == SIGN_EXTRACT || GET_CODE (x) == ZERO_EXTRACT)
+      if (GET_CODE (x) == SIGN_EXTRACT
+         || GET_CODE (x) == ZERO_EXTRACT
+         || GET_CODE (x) == STRICT_LOW_PART)
        mark_referenced_resources (x, res, 0);
       else if (GET_CODE (x) == SUBREG)
        x = SUBREG_REG (x);
@@ -832,9 +870,8 @@ mark_target_live_regs (insns, target, res)
        b = tinfo->block;
     }
 
-  if (b == -1
-      && INSN_UID (target) < (int) VARRAY_SIZE (basic_block_for_insn))
-    b = BLOCK_NUM (target);
+  if (b == -1)
+    b = find_basic_block (target);
 
   if (target_hash_table != NULL)
     {
@@ -1030,8 +1067,8 @@ mark_target_live_regs (insns, target, res)
 
   /* If we hit an unconditional branch, we have another way of finding out
      what is live: we can see what is live at the branch target and include
-     anything used but not set before the branch.  The only things that are
-     live are those that are live using the above test and the test below.  */
+     anything used but not set before the branch.  We add the live
+     resources found using the test below to those found until now. */
 
   if (jump_insn)
     {
@@ -1055,7 +1092,7 @@ mark_target_live_regs (insns, target, res)
          mark_set_resources (insn, &set, 0, 1);
        }
 
-      AND_HARD_REG_SET (res->regs, new_resources.regs);
+      IOR_HARD_REG_SET (res->regs, new_resources.regs);
     }
 
   if (tinfo != NULL)
@@ -1138,8 +1175,6 @@ init_resource_info (epilogue_insn)
   target_hash_table = (struct target_info **)
     xcalloc (TARGET_HASH_PRIME, sizeof (struct target_info *));
   bb_ticks = (int *) xcalloc (n_basic_blocks, sizeof (int));
-
-  compute_bb_for_insn (get_max_uid ());
 }
 \f
 /* Free up the resources allcated to mark_target_live_regs ().  This
@@ -1187,7 +1222,7 @@ void
 incr_ticks_for_insn (insn)
      rtx insn;
 {
-  int b = BLOCK_NUM (insn);
+  int b = find_basic_block (insn);
 
   if (b != -1)
     bb_ticks[b]++;
@@ -1261,6 +1296,10 @@ find_free_register (current_insn, last_insn, class_str, mode, reg_set)
       /* 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--)