* flow.c (make_edge): Accept an optional 2D bitmap in which
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Oct 1999 19:01:01 +0000 (19:01 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 5 Oct 1999 19:01:01 +0000 (19:01 +0000)
        to cache edge existence.  Update all callers.
        (make_label_edge, make_eh_edge): Pass through the edge cache.
        (make_edges): Provide the cache.

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

gcc/ChangeLog
gcc/flow.c

index f91f855..0da5b3a 100644 (file)
@@ -1,3 +1,10 @@
+Tue Oct  5 12:00:32 1999  Richard Henderson  <rth@cygnus.com>
+
+       * flow.c (make_edge): Accept an optional 2D bitmap in which
+       to cache edge existence.  Update all callers.
+       (make_label_edge, make_eh_edge): Pass through the edge cache.
+       (make_edges): Provide the cache.
+
 Tue Oct  5 12:16:49 1999  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * mbchar.c (literal_codeset, local_mbtowc, local_mblen): Constify
index f883d80..5e2ec61 100644 (file)
@@ -280,10 +280,12 @@ static rtx find_basic_blocks_1            PROTO((rtx));
 static void create_basic_block         PROTO((int, rtx, rtx, rtx));
 static void clear_edges                        PROTO((void));
 static void make_edges                 PROTO((rtx));
-static void make_edge                  PROTO((basic_block, basic_block, int));
-static void make_label_edge            PROTO((basic_block, rtx, int));
-static void make_eh_edge               PROTO((eh_nesting_info *, basic_block,
+static void make_edge                  PROTO((sbitmap *, basic_block,
+                                              basic_block, int));
+static void make_label_edge            PROTO((sbitmap *, basic_block,
                                               rtx, int));
+static void make_eh_edge               PROTO((sbitmap *, eh_nesting_info *,
+                                              basic_block, rtx, int));
 static void mark_critical_edges                PROTO((void));
 static void move_stray_eh_region_notes PROTO((void));
 static void record_active_eh_regions   PROTO((rtx));
@@ -879,12 +881,22 @@ make_edges (label_value_list)
 {
   int i;
   eh_nesting_info *eh_nest_info = init_eh_nesting_info ();
+  sbitmap *edge_cache = NULL;
 
   /* Assume no computed jump; revise as we create edges.  */
   current_function_has_computed_jump = 0;
 
+  /* Heavy use of computed goto in machine-generated code can lead to
+     nearly fully-connected CFGs.  In that case we spend a significant
+     amount of time searching the edge lists for duplicates.  */
+  if (forced_labels || label_value_list)
+    {
+      edge_cache = sbitmap_vector_alloc (n_basic_blocks, n_basic_blocks);
+      sbitmap_vector_zero (edge_cache, n_basic_blocks);
+    }
+
   /* By nature of the way these get numbered, block 0 is always the entry.  */
-  make_edge (ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
+  make_edge (edge_cache, ENTRY_BLOCK_PTR, BASIC_BLOCK (0), EDGE_FALLTHRU);
 
   for (i = 0; i < n_basic_blocks; ++i)
     {
@@ -920,7 +932,8 @@ make_edges (label_value_list)
                vec = XVEC (PATTERN (tmp), 1);
 
              for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
-               make_label_edge (bb, XEXP (RTVEC_ELT (vec, j), 0), 0);
+               make_label_edge (edge_cache, bb,
+                                XEXP (RTVEC_ELT (vec, j), 0), 0);
 
              /* Some targets (eg, ARM) emit a conditional jump that also
                 contains the out-of-range target.  Scan for these and
@@ -929,7 +942,8 @@ make_edges (label_value_list)
                  && SET_DEST (tmp) == pc_rtx
                  && GET_CODE (SET_SRC (tmp)) == IF_THEN_ELSE
                  && GET_CODE (XEXP (SET_SRC (tmp), 2)) == LABEL_REF)
-               make_label_edge (bb, XEXP (XEXP (SET_SRC (tmp), 2), 0), 0);
+               make_label_edge (edge_cache, bb,
+                                XEXP (XEXP (SET_SRC (tmp), 2), 0), 0);
 
 #ifdef CASE_DROPS_THROUGH
              /* Silly VAXen.  The ADDR_VEC is going to be in the way of
@@ -945,22 +959,22 @@ make_edges (label_value_list)
              current_function_has_computed_jump = 1;
 
              for (x = label_value_list; x; x = XEXP (x, 1))
-               make_label_edge (bb, XEXP (x, 0), EDGE_ABNORMAL);
+               make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
              
              for (x = forced_labels; x; x = XEXP (x, 1))
-               make_label_edge (bb, XEXP (x, 0), EDGE_ABNORMAL);
+               make_label_edge (edge_cache, bb, XEXP (x, 0), EDGE_ABNORMAL);
            }
 
          /* Returns create an exit out.  */
          else if (returnjump_p (insn))
-           make_edge (bb, EXIT_BLOCK_PTR, 0);
+           make_edge (edge_cache, bb, EXIT_BLOCK_PTR, 0);
 
          /* Otherwise, we have a plain conditional or unconditional jump.  */
          else
            {
              if (! JUMP_LABEL (insn))
                abort ();
-             make_label_edge (bb, JUMP_LABEL (insn), 0);
+             make_label_edge (edge_cache, bb, JUMP_LABEL (insn), 0);
            }
        }
 
@@ -975,7 +989,7 @@ make_edges (label_value_list)
          /* If there's an EH region active at the end of a block,
             add the appropriate edges.  */
          if (bb->eh_end >= 0)
-           make_eh_edge (eh_nest_info, bb, insn, bb->eh_end);
+           make_eh_edge (edge_cache, eh_nest_info, bb, insn, bb->eh_end);
 
          /* If we have asynchronous exceptions, do the same for *all*
             exception regions active in the block.  */
@@ -983,7 +997,8 @@ make_edges (label_value_list)
              && bb->eh_beg != bb->eh_end)
            {
              if (bb->eh_beg >= 0)
-               make_eh_edge (eh_nest_info, bb, NULL_RTX, bb->eh_beg);
+               make_eh_edge (edge_cache, eh_nest_info, bb,
+                             NULL_RTX, bb->eh_beg);
 
              for (x = bb->head; x != bb->end; x = NEXT_INSN (x))
                if (GET_CODE (x) == NOTE
@@ -991,7 +1006,8 @@ make_edges (label_value_list)
                        || NOTE_LINE_NUMBER (x) == NOTE_INSN_EH_REGION_END))
                  {
                    int region = NOTE_EH_HANDLER (x);
-                   make_eh_edge (eh_nest_info, bb, NULL_RTX, region);
+                   make_eh_edge (edge_cache, eh_nest_info, bb,
+                                 NULL_RTX, region);
                  }
            }
 
@@ -1009,7 +1025,7 @@ make_edges (label_value_list)
              rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
              if (!note || XINT (XEXP (note, 0), 0) >=  0)
                for (x = nonlocal_goto_handler_labels; x ; x = XEXP (x, 1))
-                 make_label_edge (bb, XEXP (x, 0),
+                 make_label_edge (edge_cache, bb, XEXP (x, 0),
                                   EDGE_ABNORMAL | EDGE_ABNORMAL_CALL);
            }
        }
@@ -1020,42 +1036,53 @@ make_edges (label_value_list)
         returns to one of the eh_stub labels within it.  So we have to
         make additional edges in the flow graph.  */
       if (i + 1 == n_basic_blocks && eh_return_stub_label != 0)
-       make_label_edge (bb, eh_return_stub_label, EDGE_EH);
+       make_label_edge (edge_cache, bb, eh_return_stub_label, EDGE_EH);
 
       /* Find out if we can drop through to the next block.  */
       insn = next_nonnote_insn (insn);
       if (!insn || (i + 1 == n_basic_blocks && force_fallthru))
-       make_edge (bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
+       make_edge (edge_cache, bb, EXIT_BLOCK_PTR, EDGE_FALLTHRU);
       else if (i + 1 < n_basic_blocks)
        {
          rtx tmp = BLOCK_HEAD (i + 1);
          if (GET_CODE (tmp) == NOTE)
            tmp = next_nonnote_insn (tmp);
          if (force_fallthru || insn == tmp)
-           make_edge (bb, BASIC_BLOCK (i + 1), EDGE_FALLTHRU);
+           make_edge (edge_cache, bb, BASIC_BLOCK (i + 1), EDGE_FALLTHRU);
        }
     }
+
   free_eh_nesting_info (eh_nest_info);
+  if (edge_cache)
+    sbitmap_vector_free (edge_cache);
 }
 
 /* Create an edge between two basic blocks.  FLAGS are auxiliary information
    about the edge that is accumulated between calls.  */
 
 static void
-make_edge (src, dst, flags)
+make_edge (edge_cache, src, dst, flags)
+     sbitmap *edge_cache;
      basic_block src, dst;
      int flags;
 {
+  int use_edge_cache;
   edge e;
 
-  /* Make sure we don't add duplicate edges.  */
+  /* Don't bother with edge cache for ENTRY or EXIT; there aren't that
+     many edges to them, and we didn't allocate memory for it.  */
+  use_edge_cache = (edge_cache
+                   && src != ENTRY_BLOCK_PTR
+                   && dst != EXIT_BLOCK_PTR);
 
-  for (e = src->succ; e ; e = e->succ_next)
-    if (e->dest == dst)
-      {
-       e->flags |= flags;
-       return;
-      }
+  /* Make sure we don't add duplicate edges.  */
+  if (! use_edge_cache || TEST_BIT (edge_cache[src->index], dst->index))
+    for (e = src->succ; e ; e = e->succ_next)
+      if (e->dest == dst)
+       {
+         e->flags |= flags;
+         return;
+       }
 
   e = (edge) xcalloc (1, sizeof (*e));
 
@@ -1067,12 +1094,16 @@ make_edge (src, dst, flags)
 
   src->succ = e;
   dst->pred = e;
+
+  if (use_edge_cache)
+    SET_BIT (edge_cache[src->index], dst->index);
 }
 
 /* Create an edge from a basic block to a label.  */
 
 static void
-make_label_edge (src, label, flags)
+make_label_edge (edge_cache, src, label, flags)
+     sbitmap *edge_cache;
      basic_block src;
      rtx label;
      int flags;
@@ -1088,13 +1119,14 @@ make_label_edge (src, label, flags)
   if (INSN_UID (label) == 0)
     return;
 
-  make_edge (src, BLOCK_FOR_INSN (label), flags);
+  make_edge (edge_cache, src, BLOCK_FOR_INSN (label), flags);
 }
 
 /* Create the edges generated by INSN in REGION.  */
 
 static void
-make_eh_edge (eh_nest_info, src, insn, region)
+make_eh_edge (edge_cache, eh_nest_info, src, insn, region)
+     sbitmap *edge_cache;
      eh_nesting_info *eh_nest_info;
      basic_block src;
      rtx insn;
@@ -1107,7 +1139,7 @@ make_eh_edge (eh_nest_info, src, insn, region)
   num = reachable_handlers (region, eh_nest_info, insn, &handler_list);
   while (--num >= 0)
     {
-      make_label_edge (src, handler_list[num]->handler_label,
+      make_label_edge (edge_cache, src, handler_list[num]->handler_label,
                       EDGE_ABNORMAL | EDGE_EH | is_call);
     }
 }
@@ -6989,5 +7021,5 @@ add_noreturn_fake_exit_edges ()
 
   for (x = 0; x < n_basic_blocks; x++)
     if (BASIC_BLOCK (x)->succ == NULL)
-      make_edge (BASIC_BLOCK (x), EXIT_BLOCK_PTR, EDGE_FAKE);
+      make_edge (NULL, BASIC_BLOCK (x), EXIT_BLOCK_PTR, EDGE_FAKE);
 }