flow.c (make_edge): Early out, if no flags to set.
authorMichael Matz <matzmich@cs.tu-berlin.de>
Thu, 30 Nov 2000 21:40:33 +0000 (21:40 +0000)
committerRichard Henderson <rth@gcc.gnu.org>
Thu, 30 Nov 2000 21:40:33 +0000 (13:40 -0800)
        * flow.c (make_edge): Early out, if no flags to set.
        (calculate_global_regs_live): Clear out garbage only when necessary.

        * simplify-rtx.c (varray_type used_regs): New.
        (clear_table): Use it to only clear necessary items.
        (cselib_lookup, cselib_record_set): Remember newly set items.
        (cselib_update_varray_sizes, cselib_init): Initialize and grow
        used_regs.

        * local-alloc.c (update_equiv_regs): New local `cleared_regs'.
        Move clearing of dead regs out of insn-loop.

From-SVN: r37899

gcc/ChangeLog
gcc/flow.c
gcc/local-alloc.c
gcc/simplify-rtx.c

index 3b384483790f4db0e7d33cd65fd8183a5d700570..dbb46a562185cbabef4686579686f59cd538166a 100644 (file)
@@ -1,3 +1,17 @@
+2000-11-30  Michael Matz  <matzmich@cs.tu-berlin.de>
+
+       * flow.c (make_edge): Early out, if no flags to set.
+       (calculate_global_regs_live): Clear out garbage only when necessary.
+
+       * simplify-rtx.c (varray_type used_regs): New.
+       (clear_table): Use it to only clear necessary items.
+       (cselib_lookup, cselib_record_set): Remember newly set items.
+       (cselib_update_varray_sizes, cselib_init): Initialize and grow
+       used_regs.
+
+       * local-alloc.c (update_equiv_regs): New local `cleared_regs'.
+       Move clearing of dead regs out of insn-loop.
+
 2000-11-30  Richard Henderson  <rth@redhat.com>
 
        * calls.c (expand_call): Emit queued insns before creating
index 1e3708274868d6045ba6e8627c2e9022eb444781..4aacbf8413e2a41a4f7fef241965d6d2e87c6e44 100644 (file)
@@ -1262,13 +1262,27 @@ make_edge (edge_cache, src, dst, flags)
                    && dst != EXIT_BLOCK_PTR);
 
   /* 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;
-       }
+  switch (use_edge_cache)
+    {
+    default:
+      /* Quick test for non-existance of the edge.  */
+      if (! TEST_BIT (edge_cache[src->index], dst->index))
+       break;
+
+      /* The edge exists; early exit if no work to do.  */
+      if (flags == 0)
+       return;
+
+      /* FALLTHRU */
+    case 0:
+      for (e = src->succ; e; e = e->succ_next)
+       if (e->dest == dst)
+         {
+           e->flags |= flags;
+           return;
+         }
+      break;
+    }
 
   e = (edge) xcalloc (1, sizeof (*e));
   n_edges++;
@@ -3306,15 +3320,15 @@ calculate_global_regs_live (blocks_in, blocks_out, flags)
   qtail = queue;
   qhead = qend = queue + n_basic_blocks + 2;
 
-  /* Clear out the garbage that might be hanging out in bb->aux.  */
-  for (i = n_basic_blocks - 1; i >= 0; --i)
-    BASIC_BLOCK (i)->aux = NULL;
-
   /* Queue the blocks set in the initial mask.  Do this in reverse block
      number order so that we are more likely for the first round to do
      useful work.  We use AUX non-null to flag that the block is queued.  */
   if (blocks_in)
     {
+      /* Clear out the garbage that might be hanging out in bb->aux.  */
+      for (i = n_basic_blocks - 1; i >= 0; --i)
+       BASIC_BLOCK (i)->aux = NULL;
+
       EXECUTE_IF_SET_IN_SBITMAP (blocks_in, 0, i,
        {
          basic_block bb = BASIC_BLOCK (i);
index ac2183e02f46a77df36c25569406fe99c9846411..62142f04c38085ccc2abde51afc23a0940d9e9fe 100644 (file)
@@ -804,8 +804,11 @@ update_equiv_regs ()
   rtx insn;
   int block;
   int loop_depth;
+  regset_head cleared_regs;
+  int clear_regnos = 0;
 
   reg_equiv = (struct equivalence *) xcalloc (max_regno, sizeof *reg_equiv);
+  INIT_REG_SET (&cleared_regs);
 
   init_alias_analysis ();
 
@@ -1135,7 +1138,6 @@ update_equiv_regs ()
                 INSN.  Update the flow information.  */
              else if (PREV_INSN (insn) != equiv_insn)
                {
-                 int l;
                  rtx new_insn;
 
                  new_insn = emit_insn_before (copy_rtx (PATTERN (equiv_insn)),
@@ -1156,22 +1158,43 @@ update_equiv_regs ()
                  if (block >= 0 && insn == BLOCK_HEAD (block))
                    BLOCK_HEAD (block) = PREV_INSN (insn);
 
-                 for (l = 0; l < n_basic_blocks; l++)
-                   {
-                     CLEAR_REGNO_REG_SET (
-                                       BASIC_BLOCK (l)->global_live_at_start,
-                                          regno);
-                     CLEAR_REGNO_REG_SET (
-                                       BASIC_BLOCK (l)->global_live_at_end,
-                                          regno);
-                   }
+                 /* Remember to clear REGNO from all basic block's live
+                    info.  */
+                 SET_REGNO_REG_SET (&cleared_regs, regno);
+                 clear_regnos++;
                }
            }
        }
     }
 
+  /* Clear all dead REGNOs from all basic block's live info.  */
+  if (clear_regnos)
+    {
+      int j, l;
+      if (clear_regnos > 8)
+        {
+         for (l = 0; l < n_basic_blocks; l++)
+           {
+             AND_COMPL_REG_SET (BASIC_BLOCK (l)->global_live_at_start,
+                                &cleared_regs);
+             AND_COMPL_REG_SET (BASIC_BLOCK (l)->global_live_at_end,
+                                &cleared_regs);
+           }
+       }
+      else
+        EXECUTE_IF_SET_IN_REG_SET (&cleared_regs, 0, j,
+          {
+           for (l = 0; l < n_basic_blocks; l++)
+             {
+               CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_start, j);
+               CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_end, j);
+             }
+         });
+    }
+
   /* Clean up.  */
   end_alias_analysis ();
+  CLEAR_REG_SET (&cleared_regs);
   free (reg_equiv);
 }
 
index 08ceaf7fc106984e77f9d3e2413db20198b3baa4..ae15b087d4df505b73d6411cf14bb5ab2bec625e 100644 (file)
@@ -111,7 +111,7 @@ static struct elt_loc_list *new_elt_loc_list PARAMS ((struct elt_loc_list *,
 static void unchain_one_value          PARAMS ((cselib_val *));
 static void unchain_one_elt_list       PARAMS ((struct elt_list **));
 static void unchain_one_elt_loc_list   PARAMS ((struct elt_loc_list **));
-static void clear_table                        PARAMS ((void));
+static void clear_table                        PARAMS ((int));
 static int discard_useless_locs                PARAMS ((void **, void *));
 static int discard_useless_values      PARAMS ((void **, void *));
 static void remove_useless_values      PARAMS ((void));
@@ -168,6 +168,10 @@ static int n_useless_values;
 static varray_type reg_values;
 #define REG_VALUES(I) VARRAY_ELT_LIST (reg_values, (I))
 
+/* Here the set of indices I with REG_VALUES(I) != 0 is saved.  This is used
+   in clear_table() for fast emptying.  */
+static varray_type used_regs;
+
 /* We pass this to cselib_invalidate_mem to invalidate all of
    memory for a non-const call instruction.  */
 static rtx callmem;
@@ -2200,15 +2204,23 @@ unchain_one_value (v)
 }
 
 /* Remove all entries from the hash table.  Also used during
-   initialization.  */
+   initialization.  If CLEAR_ALL isn't set, then only clear the entries
+   which are known to have been used.  */
 
 static void
-clear_table ()
+clear_table (clear_all)
+     int clear_all;
 {
   unsigned int i;
 
-  for (i = 0; i < cselib_nregs; i++)
-    REG_VALUES (i) = 0;
+  if (clear_all)
+    for (i = 0; i < cselib_nregs; i++)
+      REG_VALUES (i) = 0;
+  else
+    for (i = 0; i < VARRAY_ACTIVE_SIZE (used_regs); i++)
+      REG_VALUES (VARRAY_UINT (used_regs, i)) = 0;
+
+  VARRAY_POP_ALL (used_regs);
 
   htab_empty (hash_table);
   obstack_free (&cselib_obstack, cselib_startobj);
@@ -2867,6 +2879,8 @@ cselib_lookup (x, mode, create)
 
       e = new_cselib_val (++next_unknown_value, GET_MODE (x));
       e->locs = new_elt_loc_list (e->locs, x);
+      if (REG_VALUES (i) == 0)
+        VARRAY_PUSH_UINT (used_regs, i);
       REG_VALUES (i) = new_elt_list (REG_VALUES (i), e);
       slot = htab_find_slot_with_hash (hash_table, x, e->value, INSERT);
       *slot = e;
@@ -3133,6 +3147,9 @@ cselib_record_set (dest, src_elt, dest_addr_elt)
 
   if (dreg >= 0)
     {
+      if (REG_VALUES (dreg) == 0)
+        VARRAY_PUSH_UINT (used_regs, dreg);
+
       REG_VALUES (dreg) = new_elt_list (REG_VALUES (dreg), src_elt);
       if (src_elt->locs == 0)
        n_useless_values--;
@@ -3249,7 +3266,7 @@ cselib_process_insn (insn)
          && GET_CODE (PATTERN (insn)) == ASM_OPERANDS
          && MEM_VOLATILE_P (PATTERN (insn))))
     {
-      clear_table ();
+      clear_table (0);
       return;
     }
 
@@ -3309,6 +3326,7 @@ cselib_update_varray_sizes ()
 
   cselib_nregs = nregs;
   VARRAY_GROW (reg_values, nregs);
+  VARRAY_GROW (used_regs, nregs);
 }
 
 /* Initialize cselib for one pass.  The caller must also call
@@ -3329,8 +3347,9 @@ cselib_init ()
 
   cselib_nregs = max_reg_num ();
   VARRAY_ELT_LIST_INIT (reg_values, cselib_nregs, "reg_values");
+  VARRAY_UINT_INIT (used_regs, cselib_nregs, "used_regs");
   hash_table = htab_create (31, get_value_hash, entry_and_rtx_equal_p, NULL);
-  clear_table ();
+  clear_table (1);
 }
 
 /* Called when the current user is done with cselib.  */
@@ -3338,6 +3357,6 @@ cselib_init ()
 void
 cselib_finish ()
 {
-  clear_table ();
+  clear_table (0);
   htab_delete (hash_table);
 }