* flow.c (find_basic_blocks): Remove do_cleanup argument.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 Jan 2000 22:22:50 +0000 (22:22 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 28 Jan 2000 22:22:50 +0000 (22:22 +0000)
        Break out that code ...
        (cleanup_cfg): ... here.
        (commit_one_edge_insertion): Detect a return instruction being
        emitted to an edge.  Emit a barrier following; clear fallthru.
        (commit_edge_insertions): Verify CFG consistency.
        * function.c (expand_function_start): Kill unused variable.
        (expand_function_end): Likewise.
        (thread_prologue_and_epilogue_insns): Use insert_insn_on_edge
        to insert the epilogue.

        * gcse.c (gcse_main): Adjust for find_basic_blocks change.
        (delete_null_pointer_checks): Likewise.
        * output.h: Likewise.
        * reg-stack.c (reg_to_stack): Likewise.
        * toplev.c (rest_of_compilation): Likewise.  Run
        thread_prologue_and_epilogue_insns after rebuilding the CFG.

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

gcc/ChangeLog
gcc/flow.c
gcc/function.c
gcc/gcse.c
gcc/output.h
gcc/reg-stack.c
gcc/toplev.c

index c1e8282..8f43f07 100644 (file)
@@ -1,5 +1,25 @@
 2000-01-28  Richard Henderson  <rth@cygnus.com>
 
+       * flow.c (find_basic_blocks): Remove do_cleanup argument.
+       Break out that code ...
+       (cleanup_cfg): ... here.
+       (commit_one_edge_insertion): Detect a return instruction being
+       emitted to an edge.  Emit a barrier following; clear fallthru.
+       (commit_edge_insertions): Verify CFG consistency.
+       * function.c (expand_function_start): Kill unused variable.
+       (expand_function_end): Likewise.
+       (thread_prologue_and_epilogue_insns): Use insert_insn_on_edge
+       to insert the epilogue.
+
+       * gcse.c (gcse_main): Adjust for find_basic_blocks change.
+       (delete_null_pointer_checks): Likewise.
+       * output.h: Likewise.
+       * reg-stack.c (reg_to_stack): Likewise.
+       * toplev.c (rest_of_compilation): Likewise.  Run
+       thread_prologue_and_epilogue_insns after rebuilding the CFG.
+
+2000-01-28  Richard Henderson  <rth@cygnus.com>
+
        * Makefile.in (flow.o): Revert 24 Jan change.
        * flow.c (mark_regs_live_at_end): Likewise.  Force BLKmode
        FUNCTION_VALUE result to DECL_RESULT's mode.
index 008f0c2..0578bef 100644 (file)
@@ -372,11 +372,10 @@ int flow_loop_outside_edge_p              PARAMS ((const struct loop *, edge));
    numbers in use.  */
 
 void
-find_basic_blocks (f, nregs, file, do_cleanup)
+find_basic_blocks (f, nregs, file)
      rtx f;
      int nregs ATTRIBUTE_UNUSED;
      FILE *file ATTRIBUTE_UNUSED;
-     int do_cleanup;
 {
   int max_uid;
 
@@ -425,23 +424,8 @@ find_basic_blocks (f, nregs, file, do_cleanup)
   compute_bb_for_insn (max_uid);
 
   /* Discover the edges of our cfg.  */
-
   record_active_eh_regions (f);
   make_edges (label_value_list);
-
-  /* Delete unreachable blocks, then merge blocks when possible.  */
-
-  if (do_cleanup)
-    {
-      delete_unreachable_blocks ();
-      move_stray_eh_region_notes ();
-      record_active_eh_regions (f);
-      if (optimize)
-       try_merge_blocks ();
-    }
-
-  /* Mark critical edges.  */
-
   mark_critical_edges ();
 
   /* Kill the data we won't maintain.  */
@@ -740,6 +724,19 @@ find_basic_blocks_1 (f)
   return label_value_list;
 }
 
+/* Tidy the CFG by deleting unreachable code and whatnot.  */
+
+void
+cleanup_cfg (f)
+     rtx f;
+{
+  delete_unreachable_blocks ();
+  move_stray_eh_region_notes ();
+  record_active_eh_regions (f);
+  try_merge_blocks ();
+  mark_critical_edges ();
+}
+
 /* Create a new basic block consisting of the instructions between
    HEAD and END inclusive.  Reuses the note and basic block struct
    in BB_NOTE, if any.  */
@@ -1552,9 +1549,13 @@ static void
 commit_one_edge_insertion (e)
      edge e;
 {
-  rtx before = NULL_RTX, after = NULL_RTX, tmp;
+  rtx before = NULL_RTX, after = NULL_RTX, insns, tmp;
   basic_block bb;
 
+  /* Pull the insns off the edge now since the edge might go away.  */
+  insns = e->insns;
+  e->insns = NULL_RTX;
+
   /* Figure out where to put these things.  If the destination has
      one predecessor, insert there.  Except for the exit block.  */
   if (e->dest->pred->pred_next == NULL
@@ -1611,28 +1612,50 @@ commit_one_edge_insertion (e)
     }
 
   /* Now that we've found the spot, do the insertion.  */
-  tmp = e->insns;
-  e->insns = NULL_RTX;
 
   /* Set the new block number for these insns, if structure is allocated.  */
   if (basic_block_for_insn)
     {
       rtx i;
-      for (i = tmp; i != NULL_RTX; i = NEXT_INSN (i))
+      for (i = insns; i != NULL_RTX; i = NEXT_INSN (i))
        set_block_for_insn (i, bb);
     }
 
   if (before)
     {
-      emit_insns_before (tmp, before);
+      emit_insns_before (insns, before);
       if (before == bb->head)
-       bb->head = tmp;
+       bb->head = insns;
     }
   else
     {
-      tmp = emit_insns_after (tmp, after);
+      rtx last = emit_insns_after (insns, after);
       if (after == bb->end)
-       bb->end = tmp;
+       {
+         bb->end = last;
+
+         if (GET_CODE (last) == JUMP_INSN)
+           {
+             if (returnjump_p (last))
+               {
+                 /* ??? Remove all outgoing edges from BB and add one
+                    for EXIT.  This is not currently a problem because
+                    this only happens for the (single) epilogue, which
+                    already has a fallthru edge to EXIT.  */
+
+                 e = bb->succ;
+                 if (e->dest != EXIT_BLOCK_PTR
+                     || e->succ_next != NULL
+                     || (e->flags & EDGE_FALLTHRU) == 0)
+                   abort ();
+                 e->flags &= ~EDGE_FALLTHRU;
+
+                 emit_barrier_after (last);
+               }
+             else
+               abort ();
+           }
+       }
     }
 }
 
@@ -1644,6 +1667,10 @@ commit_edge_insertions ()
   int i;
   basic_block bb;
 
+#ifdef ENABLE_CHECKING
+  verify_flow_info ();
+#endif
   i = -1;
   bb = ENTRY_BLOCK_PTR;
   while (1)
index 8339208..960fd1c 100644 (file)
@@ -5867,7 +5867,6 @@ expand_function_start (subr, parms_have_cleanups)
      tree subr;
      int parms_have_cleanups;
 {
-  register int i;
   tree tem;
   rtx last_ptr = NULL_RTX;
 
@@ -6171,7 +6170,6 @@ expand_function_end (filename, line, end_bindings)
      int line;
      int end_bindings;
 {
-  register int i;
   tree link;
 
 #ifdef TRAMPOLINE_TEMPLATE
@@ -6546,12 +6544,12 @@ thread_prologue_and_epilogue_insns (f)
      rtx f ATTRIBUTE_UNUSED;
 {
   int insertted = 0;
+  edge e;
+  rtx seq;
 
 #ifdef HAVE_prologue
   if (HAVE_prologue)
     {
-      rtx seq;
-
       start_sequence ();
       seq = gen_prologue();
       emit_insn (seq);
@@ -6581,129 +6579,47 @@ thread_prologue_and_epilogue_insns (f)
     }
 #endif
 
+  /* If the exit block has no non-fake predecessors, we don't need
+     an epilogue.  */
+  for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+    if ((e->flags & EDGE_FAKE) == 0)
+      break;
+  if (e == NULL)
+    goto epilogue_done;
+
 #ifdef HAVE_epilogue
   if (HAVE_epilogue)
     {
-      edge e;
-      basic_block bb = 0;
-      rtx tail = get_last_insn ();
-
-      /* ??? This is gastly.  If function returns were not done via uses,
-        but via mark_regs_live_at_end, we could use insert_insn_on_edge
-        and all of this uglyness would go away.  */
-
-      switch (optimize)
-       {
-       default:
-         /* If the exit block has no non-fake predecessors, we don't
-            need an epilogue.  Furthermore, only pay attention to the
-            fallthru predecessors; if (conditional) return insns were
-            generated, by definition we do not need to emit epilogue
-            insns.  */
-
-         for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
-           if ((e->flags & EDGE_FAKE) == 0
-               && (e->flags & EDGE_FALLTHRU) != 0)
-             break;
-         if (e == NULL)
-           break;
-
-         /* We can't handle multiple epilogues -- if one is needed,
-            we won't be able to place it multiple times.
-
-            ??? Fix epilogue expanders to not assume they are the
-            last thing done compiling the function.  Either that
-            or copy_rtx each insn.
-
-            ??? Blah, it's not a simple expression to assert that
-            we've exactly one fallthru exit edge.  */
+      /* Find the edge that falls through to EXIT.  Other edges may exist
+        due to RETURN instructions, but those don't need epilogues.
+        There really shouldn't be a mixture -- either all should have
+        been converted or none, however...  */
 
-         bb = e->src;
-         tail = bb->end;
-
-         /* ??? If the last insn of the basic block is a jump, then we
-            are creating a new basic block.  Wimp out and leave these
-            insns outside any block.  */
-         if (GET_CODE (tail) == JUMP_INSN)
-           bb = 0;
-
-         /* FALLTHRU */
-       case 0:
-         {
-           rtx prev, seq, first_use;
-
-           /* Move the USE insns at the end of a function onto a list.  */
-           prev = tail;
-           if (GET_CODE (prev) == BARRIER
-               || GET_CODE (prev) == NOTE)
-             prev = prev_nonnote_insn (prev);
-
-           first_use = 0;
-           if (prev
-               && GET_CODE (prev) == INSN
-               && GET_CODE (PATTERN (prev)) == USE)
-             {
-               /* If the end of the block is the use, grab hold of something
-                  else so that we emit barriers etc in the right place.  */
-               if (prev == tail)
-                 {
-                   do 
-                     tail = PREV_INSN (tail);
-                   while (GET_CODE (tail) == INSN
-                          && GET_CODE (PATTERN (tail)) == USE);
-                 }
-
-               do
-                 {
-                   rtx use = prev;
-                   prev = prev_nonnote_insn (prev);
-
-                   remove_insn (use);
-                   if (first_use)
-                     {
-                       NEXT_INSN (use) = first_use;
-                       PREV_INSN (first_use) = use;
-                     }
-                   else
-                     NEXT_INSN (use) = NULL_RTX;
-                   first_use = use;
-                 }
-               while (prev
-                      && GET_CODE (prev) == INSN
-                      && GET_CODE (PATTERN (prev)) == USE);
-             }
-
-           /* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
-              epilogue insns, the USE insns at the end of a function,
-              the jump insn that returns, and then a BARRIER.  */
+      for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+       if (e->flags & EDGE_FALLTHRU)
+         break;
+      if (e == NULL)
+       goto epilogue_done;
 
-           if (GET_CODE (tail) != BARRIER)
-             {
-               prev = next_nonnote_insn (tail);
-               if (!prev || GET_CODE (prev) != BARRIER)
-                 emit_barrier_after (tail);
-             }
+      start_sequence ();
+      emit_note (NULL, NOTE_INSN_EPILOGUE_BEG);
 
-           seq = gen_epilogue ();
-           prev = tail;
-           tail = emit_jump_insn_after (seq, tail);
+      seq = gen_epilogue ();
+      emit_jump_insn (seq);
 
-           /* Insert the USE insns immediately before the return insn, which
-              must be the last instruction emitted in the sequence.  */
-           if (first_use)
-             emit_insns_before (first_use, tail);
-           emit_note_after (NOTE_INSN_EPILOGUE_BEG, prev);
+      /* Retain a map of the epilogue insns.  */
+      if (GET_CODE (seq) != SEQUENCE)
+       seq = get_insns ();
+      epilogue = record_insns (seq);
 
-           /* Update the tail of the basic block.  */
-           if (bb)
-             bb->end = tail;
+      seq = gen_sequence ();
+      end_sequence();
 
-           /* Retain a map of the epilogue insns.  */
-           epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
-         }
-       }
+      insert_insn_on_edge (seq, e);
+      insertted = 1;
     }
 #endif
+epilogue_done:
 
   if (insertted)
     commit_edge_insertions ();
index a61463d..482a590 100644 (file)
@@ -673,7 +673,8 @@ gcse_main (f, file)
   /* Identify the basic block information for this function, including
      successors and predecessors.  */
   max_gcse_regno = max_reg_num ();
-  find_basic_blocks (f, max_gcse_regno, file, 1);
+  find_basic_blocks (f, max_gcse_regno, file);
+  cleanup_cfg (f);
 
   if (file)
     dump_flow_info (file);
@@ -5201,7 +5202,8 @@ delete_null_pointer_checks (f)
   struct null_pointer_info npi;
 
   /* First break the program into basic blocks.  */
-  find_basic_blocks (f, max_reg_num (), NULL, 1);
+  find_basic_blocks (f, max_reg_num (), NULL);
+  cleanup_cfg (f);
 
   /* If we have only a single block, then there's nothing to do.  */
   if (n_basic_blocks <= 1)
index dbc373d..ecd3253 100644 (file)
@@ -131,7 +131,8 @@ extern void allocate_for_life_analysis      PARAMS ((void));
 extern int regno_uninitialized         PARAMS ((int));
 extern int regno_clobbered_at_setjmp   PARAMS ((int));
 extern void dump_flow_info             PARAMS ((FILE *));
-extern void find_basic_blocks         PARAMS ((rtx, int, FILE *, int));
+extern void find_basic_blocks          PARAMS ((rtx, int, FILE *));
+extern void cleanup_cfg                        PARAMS ((rtx));
 extern void calculate_loop_depth      PARAMS ((FILE *));
 extern void free_basic_block_vars     PARAMS ((int));
 extern void set_block_num             PARAMS ((rtx, int));
index 2edd579..ab27407 100644 (file)
@@ -430,7 +430,7 @@ reg_to_stack (first, file)
 
   /* Ok, floating point instructions exist.  If not optimizing, 
      build the CFG and run life analysis.  */
-  find_basic_blocks (first, max_reg_num (), file, 0);
+  find_basic_blocks (first, max_reg_num (), file);
   count_or_remove_death_notes (NULL, 1);
   life_analysis (first, max_reg_num (), file, 0);
 
index 189c3e7..136d966 100644 (file)
@@ -3216,7 +3216,8 @@ rest_of_compilation (decl)
   TIMEVAR
     (flow_time,
      {
-       find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
+       find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+       cleanup_cfg (insns);
        if (optimize)
         calculate_loop_depth (rtl_dump_file);
        life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
@@ -3384,13 +3385,6 @@ rest_of_compilation (decl)
   if (rebuild_label_notes_after_reload)
     TIMEVAR (jump_time, rebuild_jump_labels (insns));
 
-  /* On some machines, the prologue and epilogue code, or parts thereof,
-     can be represented as RTL.  Doing so lets us schedule insns between
-     it and the rest of the code and also allows delayed branch
-     scheduling to operate in the epilogue.  */
-
-  thread_prologue_and_epilogue_insns (insns);
-
   /* If optimizing and we are performing instruction scheduling after
      reload, then go ahead and split insns now since we are about to
      recompute flow information anyway.
@@ -3412,12 +3406,23 @@ rest_of_compilation (decl)
   if (flow2_dump)
     open_dump_file (".14.flow2", decl_printable_name (decl, 2));
   
+  TIMEVAR (flow2_time,
+          {
+            find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
+          });
+
+  /* On some machines, the prologue and epilogue code, or parts thereof,
+     can be represented as RTL.  Doing so lets us schedule insns between
+     it and the rest of the code and also allows delayed branch
+     scheduling to operate in the epilogue.  */
+  thread_prologue_and_epilogue_insns (insns);
+
   if (optimize)
     {
       TIMEVAR
        (flow2_time,
         {
-          find_basic_blocks (insns, max_reg_num (), rtl_dump_file, 1);
+          cleanup_cfg (insns);
           life_analysis (insns, max_reg_num (), rtl_dump_file, 1);
         });