* resource.c (find_basic_block): Use BLOCK_FOR_INSN to look up
authorebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Apr 2009 10:42:09 +0000 (10:42 +0000)
committerebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 27 Apr 2009 10:42:09 +0000 (10:42 +0000)
a label's basic block.
(mark_target_live_regs): Tidy and rework obsolete comments.
Change back DF problem to LIVE.  If a label starts a basic block,
assume that all registers that used to be live then still are.
(init_resource_info): If a label starts a basic block, set its
BLOCK_FOR_INSN accordingly.
(fini_resource_info): Undo the setting of BLOCK_FOR_INSN.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146829 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/resource.c
gcc/testsuite/ChangeLog
gcc/testsuite/gnat.dg/opt2.adb [new file with mode: 0644]

index 849123e..e39039a 100644 (file)
@@ -1,3 +1,15 @@
+2009-04-27  Richard Sandiford  <rdsandiford@googlemail.com>
+            Eric Botcazou  <ebotcazou@adacore.com>
+
+       * resource.c (find_basic_block): Use BLOCK_FOR_INSN to look up
+       a label's basic block.
+       (mark_target_live_regs): Tidy and rework obsolete comments.
+       Change back DF problem to LIVE.  If a label starts a basic block,
+       assume that all registers that used to be live then still are.
+       (init_resource_info): If a label starts a basic block, set its
+       BLOCK_FOR_INSN accordingly.
+       (fini_resource_info): Undo the setting of BLOCK_FOR_INSN.
+
 2009-04-27  Richard Guenther  <rguenther@suse.de>
 
        * tree-flow-inline.h (function_ann): Remove.
index 2f9a71b..91b86c9 100644 (file)
@@ -135,8 +135,6 @@ update_live_status (rtx dest, const_rtx x, void *data ATTRIBUTE_UNUSED)
 static int
 find_basic_block (rtx insn, int search_limit)
 {
-  basic_block bb;
-
   /* 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);
@@ -157,11 +155,8 @@ find_basic_block (rtx insn, int search_limit)
   for (insn = next_nonnote_insn (insn);
        insn && LABEL_P (insn);
        insn = next_nonnote_insn (insn))
-    {
-      FOR_EACH_BB (bb)
-       if (insn == BB_HEAD (bb))
-         return bb->index;
-    }
+    if (BLOCK_FOR_INSN (insn))
+      return BLOCK_FOR_INSN (insn)->index;
 
   return -1;
 }
@@ -848,13 +843,12 @@ return_insn_p (const_rtx insn)
    (with no intervening active insns) to see if any of them start a basic
    block.  If we hit the start of the function first, we use block 0.
 
-   Once we have found a basic block and a corresponding first insns, we can
-   accurately compute the live status from basic_block_live_regs and
-   reg_renumber.  (By starting at a label following a BARRIER, we are immune
-   to actions taken by reload and jump.)  Then we scan all insns between
-   that point and our target.  For each CLOBBER (or for call-clobbered regs
-   when we pass a CALL_INSN), mark the appropriate registers are dead.  For
-   a SET, mark them as live.
+   Once we have found a basic block and a corresponding first insn, we can
+   accurately compute the live status (by starting at a label following a
+   BARRIER, we are immune to actions taken by reload and jump.)  Then we
+   scan all insns between that point and our target.  For each CLOBBER (or
+   for call-clobbered regs when we pass a CALL_INSN), mark the appropriate
+   registers are dead.  For a SET, mark them as live.
 
    We have to be careful when using REG_DEAD notes because they are not
    updated by such things as find_equiv_reg.  So keep track of registers
@@ -954,13 +948,10 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
      TARGET.  Otherwise, we must assume everything is live.  */
   if (b != -1)
     {
-      regset regs_live = DF_LR_IN (BASIC_BLOCK (b));
+      regset regs_live = df_get_live_in (BASIC_BLOCK (b));
       rtx start_insn, stop_insn;
 
-      /* Compute hard regs live at start of block -- this is the real hard regs
-        marked live, plus live pseudo regs that have been renumbered to
-        hard regs.  */
-
+      /* Compute hard regs live at start of block.  */
       REG_SET_TO_HARD_REG_SET (current_live_regs, regs_live);
 
       /* Get starting and ending insn, handling the case where each might
@@ -1046,10 +1037,24 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
 
          else if (LABEL_P (real_insn))
            {
+             basic_block bb;
+
              /* A label clobbers the pending dead registers since neither
                 reload nor jump will propagate a value across a label.  */
              AND_COMPL_HARD_REG_SET (current_live_regs, pending_dead_regs);
              CLEAR_HARD_REG_SET (pending_dead_regs);
+
+             /* We must conservatively assume that all registers that used
+                to be live here still are.  The fallthrough edge may have
+                left a live register uninitialized.  */
+             bb = BLOCK_FOR_INSN (real_insn);
+             if (bb)
+               {
+                 HARD_REG_SET extra_live;
+
+                 REG_SET_TO_HARD_REG_SET (extra_live, df_get_live_in (bb));
+                 IOR_HARD_REG_SET (current_live_regs, extra_live);
+               }
            }
 
          /* The beginning of the epilogue corresponds to the end of the
@@ -1121,6 +1126,7 @@ void
 init_resource_info (rtx epilogue_insn)
 {
   int i;
+  basic_block bb;
 
   /* Indicate what resources are required to be valid at the end of the current
      function.  The condition code never is and memory always is.  If the
@@ -1189,6 +1195,11 @@ init_resource_info (rtx epilogue_insn)
   /* Allocate and initialize the tables used by mark_target_live_regs.  */
   target_hash_table = XCNEWVEC (struct target_info *, TARGET_HASH_PRIME);
   bb_ticks = XCNEWVEC (int, last_basic_block);
+
+  /* Set the BLOCK_FOR_INSN of each label that starts a basic block.  */
+  FOR_EACH_BB (bb)
+    if (LABEL_P (BB_HEAD (bb)))
+      BLOCK_FOR_INSN (BB_HEAD (bb)) = bb;
 }
 \f
 /* Free up the resources allocated to mark_target_live_regs ().  This
@@ -1197,6 +1208,8 @@ init_resource_info (rtx epilogue_insn)
 void
 free_resource_info (void)
 {
+  basic_block bb;
+
   if (target_hash_table != NULL)
     {
       int i;
@@ -1222,6 +1235,10 @@ free_resource_info (void)
       free (bb_ticks);
       bb_ticks = NULL;
     }
+
+  FOR_EACH_BB (bb)
+    if (LABEL_P (BB_HEAD (bb)))
+      BLOCK_FOR_INSN (BB_HEAD (bb)) = NULL;
 }
 \f
 /* Clear any hashed information that we have stored for INSN.  */
index b5beac2..d959bb4 100644 (file)
@@ -1,3 +1,7 @@
+2009-04-27  Eric Botcazou  <ebotcazou@adacore.com>
+
+       * gnat.dg/opt2.adb: New test.
+
 2009-04-27  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/39875
diff --git a/gcc/testsuite/gnat.dg/opt2.adb b/gcc/testsuite/gnat.dg/opt2.adb
new file mode 100644 (file)
index 0000000..a6c247f
--- /dev/null
@@ -0,0 +1,31 @@
+-- { dg-do run }
+-- { dg-options "-O2 -fno-inline" }
+
+procedure Opt2 is
+   function Get return String is
+   begin
+      return "[]";
+   end Get;
+
+   Message : String := Get;
+
+   F, L : Integer;
+begin
+   for J in Message'Range loop
+      if Message (J) = '[' then
+         F := J;
+      elsif Message (J) = ']' then
+         L := J;
+         exit;
+      end if;
+   end loop;
+
+   declare
+      M : String :=
+         Message (Message'First .. F) & Message (L .. Message'Last);
+   begin
+      if M /= "[]" then
+        raise Program_Error;
+      end if;
+   end;
+end;