flow.c (make_edge): Early out, if no flags to set.

* 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
This commit is contained in:
Michael Matz 2000-11-30 21:40:33 +00:00 committed by Richard Henderson
parent 41c3953302
commit 25e4379fe5
4 changed files with 99 additions and 29 deletions

View 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

View 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);

View 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);
}

View 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);
}