Goodbye REG_LIVE_LENGTH
* regs.h (struct reg_info_t): Delete live_length. (REG_LIVE_LENGTH): Delete macro. * regstat.c (regstat_bb_compute_ri): Delete artificial_uses, local_live, local_processed and local_live_last_luid params. Replace bb_index param with bb. Don't set REG_LIVE_LENGTH. Formatting fixes. (regstat_compute_ri): Adjust for above. Don't set REG_LIVE_LENGTH. (dump_reg_info): Don't print live length. * ira.c (update_equiv_regs): Replace test of REG_LIVE_LENGTH with test of setjmp_crosses. Don't set REG_LIVE_LENGTH. Localize loop_depth var. From-SVN: r235663
This commit is contained in:
parent
411e5c675d
commit
91dabbb2c7
4 changed files with 38 additions and 153 deletions
|
@ -1,3 +1,18 @@
|
|||
2016-04-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* regs.h (struct reg_info_t): Delete live_length.
|
||||
(REG_LIVE_LENGTH): Delete macro.
|
||||
* regstat.c (regstat_bb_compute_ri): Delete artificial_uses,
|
||||
local_live, local_processed and local_live_last_luid params.
|
||||
Replace bb_index param with bb. Don't set REG_LIVE_LENGTH.
|
||||
Formatting fixes.
|
||||
(regstat_compute_ri): Adjust for above. Don't set
|
||||
REG_LIVE_LENGTH.
|
||||
(dump_reg_info): Don't print live length.
|
||||
* ira.c (update_equiv_regs): Replace test of REG_LIVE_LENGTH
|
||||
with test of setjmp_crosses. Don't set REG_LIVE_LENGTH.
|
||||
Localize loop_depth var.
|
||||
|
||||
2016-04-30 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* ira.c (enum valid_equiv): New.
|
||||
|
|
11
gcc/ira.c
11
gcc/ira.c
|
@ -3315,7 +3315,6 @@ update_equiv_regs (void)
|
|||
{
|
||||
rtx_insn *insn;
|
||||
basic_block bb;
|
||||
int loop_depth;
|
||||
|
||||
/* Scan insns and set pdx_subregs if the reg is used in a
|
||||
paradoxical subreg. Don't set such reg equivalent to a mem,
|
||||
|
@ -3329,9 +3328,10 @@ update_equiv_regs (void)
|
|||
/* Scan the insns and find which registers have equivalences. Do this
|
||||
in a separate scan of the insns because (due to -fcse-follow-jumps)
|
||||
a register can be set below its use. */
|
||||
bitmap setjmp_crosses = regstat_get_setjmp_crosses ();
|
||||
FOR_EACH_BB_FN (bb, cfun)
|
||||
{
|
||||
loop_depth = bb_loop_depth (bb);
|
||||
int loop_depth = bb_loop_depth (bb);
|
||||
|
||||
for (insn = BB_HEAD (bb);
|
||||
insn != NEXT_INSN (BB_END (bb));
|
||||
|
@ -3553,12 +3553,8 @@ update_equiv_regs (void)
|
|||
reg_equiv[regno].loop_depth = (short) loop_depth;
|
||||
|
||||
/* Don't mess with things live during setjmp. */
|
||||
if (REG_LIVE_LENGTH (regno) >= 0 && optimize)
|
||||
if (optimize && !bitmap_bit_p (setjmp_crosses, regno))
|
||||
{
|
||||
/* Note that the statement below does not affect the priority
|
||||
in local-alloc! */
|
||||
REG_LIVE_LENGTH (regno) *= 2;
|
||||
|
||||
/* If the register is referenced exactly twice, meaning it is
|
||||
set once and used once, indicate that the reference may be
|
||||
replaced by the equivalence we computed above. Do this
|
||||
|
@ -3744,7 +3740,6 @@ combine_and_move_insns (void)
|
|||
REG_N_CALLS_CROSSED (regno) = 0;
|
||||
REG_FREQ_CALLS_CROSSED (regno) = 0;
|
||||
REG_N_THROWING_CALLS_CROSSED (regno) = 0;
|
||||
REG_LIVE_LENGTH (regno) = 2;
|
||||
|
||||
if (use_insn == BB_HEAD (use_bb))
|
||||
BB_HEAD (use_bb) = new_insn;
|
||||
|
|
15
gcc/regs.h
15
gcc/regs.h
|
@ -105,7 +105,6 @@ struct reg_info_t
|
|||
{
|
||||
int freq; /* # estimated frequency (REG n) is used or set */
|
||||
int deaths; /* # of times (REG n) dies */
|
||||
int live_length; /* # of instructions (REG n) is live */
|
||||
int calls_crossed; /* # of calls (REG n) is live across */
|
||||
int freq_calls_crossed; /* # estimated frequency (REG n) crosses call */
|
||||
int throw_calls_crossed; /* # of calls that may throw (REG n) is live across */
|
||||
|
@ -170,20 +169,6 @@ extern size_t reg_info_p_size;
|
|||
|
||||
#define REG_N_THROWING_CALLS_CROSSED(N) (reg_info_p[N].throw_calls_crossed)
|
||||
|
||||
/* Total number of instructions at which (REG n) is live.
|
||||
|
||||
This is set in regstat.c whenever register info is requested and
|
||||
remains valid for the rest of the compilation of the function; it is
|
||||
used to control register allocation. The larger this is, the less
|
||||
priority (REG n) gets for allocation in a hard register (in IRA in
|
||||
priority-coloring mode).
|
||||
|
||||
Negative values are special: -1 is used to mark a pseudo reg that
|
||||
should not be allocated to a hard register, because it crosses a
|
||||
setjmp call. */
|
||||
|
||||
#define REG_LIVE_LENGTH(N) (reg_info_p[N].live_length)
|
||||
|
||||
/* Indexed by n, gives number of basic block that (REG n) is used in.
|
||||
If the value is REG_BLOCK_GLOBAL (-1),
|
||||
it means (REG n) is used in more than one basic block.
|
||||
|
|
150
gcc/regstat.c
150
gcc/regstat.c
|
@ -94,7 +94,7 @@ regstat_free_n_sets_and_refs (void)
|
|||
/*----------------------------------------------------------------------------
|
||||
REGISTER INFORMATION
|
||||
|
||||
Process REG_N_DEATHS, REG_LIVE_LENGTH, REG_N_CALLS_CROSSED,
|
||||
Process REG_N_DEATHS, REG_N_CALLS_CROSSED,
|
||||
REG_N_THROWING_CALLS_CROSSED and REG_BASIC_BLOCK.
|
||||
|
||||
----------------------------------------------------------------------------*/
|
||||
|
@ -106,24 +106,17 @@ struct reg_info_t *reg_info_p;
|
|||
size_t reg_info_p_size;
|
||||
|
||||
/* Compute register info: lifetime, bb, and number of defs and uses
|
||||
for basic block BB. The three bitvectors are scratch regs used
|
||||
here. */
|
||||
for basic block BB. LIVE is a scratch bitvector used here. */
|
||||
|
||||
static void
|
||||
regstat_bb_compute_ri (unsigned int bb_index,
|
||||
bitmap live, bitmap artificial_uses,
|
||||
bitmap local_live, bitmap local_processed,
|
||||
int *local_live_last_luid)
|
||||
regstat_bb_compute_ri (basic_block bb, bitmap live)
|
||||
{
|
||||
basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
|
||||
rtx_insn *insn;
|
||||
df_ref def, use;
|
||||
int luid = 0;
|
||||
bitmap_iterator bi;
|
||||
unsigned int regno;
|
||||
|
||||
bitmap_copy (live, df_get_live_out (bb));
|
||||
bitmap_clear (artificial_uses);
|
||||
|
||||
/* Process the regs live at the end of the block. Mark them as
|
||||
not local to any one basic block. */
|
||||
|
@ -132,30 +125,26 @@ regstat_bb_compute_ri (unsigned int bb_index,
|
|||
|
||||
/* Process the artificial defs and uses at the bottom of the block
|
||||
to begin processing. */
|
||||
FOR_EACH_ARTIFICIAL_DEF (def, bb_index)
|
||||
FOR_EACH_ARTIFICIAL_DEF (def, bb->index)
|
||||
if ((DF_REF_FLAGS (def) & DF_REF_AT_TOP) == 0)
|
||||
bitmap_clear_bit (live, DF_REF_REGNO (def));
|
||||
|
||||
FOR_EACH_ARTIFICIAL_USE (use, bb_index)
|
||||
FOR_EACH_ARTIFICIAL_USE (use, bb->index)
|
||||
if ((DF_REF_FLAGS (use) & DF_REF_AT_TOP) == 0)
|
||||
{
|
||||
regno = DF_REF_REGNO (use);
|
||||
bitmap_set_bit (live, regno);
|
||||
bitmap_set_bit (artificial_uses, regno);
|
||||
}
|
||||
|
||||
FOR_BB_INSNS_REVERSE (bb, insn)
|
||||
{
|
||||
struct df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
|
||||
bitmap_iterator bi;
|
||||
df_mw_hardreg *mw;
|
||||
rtx link;
|
||||
|
||||
if (!NONDEBUG_INSN_P (insn))
|
||||
continue;
|
||||
|
||||
luid++;
|
||||
|
||||
link = REG_NOTES (insn);
|
||||
while (link)
|
||||
{
|
||||
|
@ -194,82 +183,24 @@ regstat_bb_compute_ri (unsigned int bb_index,
|
|||
}
|
||||
}
|
||||
|
||||
/* We only care about real sets for calls. Clobbers cannot
|
||||
be depended on.
|
||||
Only do this if the value is totally dead. */
|
||||
FOR_EACH_INSN_INFO_MW (mw, insn_info)
|
||||
if (DF_MWS_REG_DEF_P (mw))
|
||||
{
|
||||
bool all_dead = true;
|
||||
unsigned int r;
|
||||
|
||||
for (r = mw->start_regno; r <= mw->end_regno; r++)
|
||||
if (bitmap_bit_p (artificial_uses, r)
|
||||
|| bitmap_bit_p (live, r))
|
||||
{
|
||||
all_dead = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (all_dead)
|
||||
{
|
||||
regno = mw->start_regno;
|
||||
REG_LIVE_LENGTH (regno)++;
|
||||
}
|
||||
}
|
||||
|
||||
/* All of the defs except the return value are some sort of
|
||||
clobber. This code is for the return. */
|
||||
FOR_EACH_INSN_INFO_DEF (def, insn_info)
|
||||
{
|
||||
if ((!CALL_P (insn))
|
||||
|| (!(DF_REF_FLAGS (def) & (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
|
||||
|| (!(DF_REF_FLAGS (def)
|
||||
& (DF_REF_MUST_CLOBBER | DF_REF_MAY_CLOBBER))))
|
||||
{
|
||||
unsigned int dregno = DF_REF_REGNO (def);
|
||||
|
||||
if (bitmap_bit_p (live, dregno))
|
||||
{
|
||||
/* If we have seen a use of DREGNO somewhere before (i.e.
|
||||
later in this basic block), and DEF is not a subreg
|
||||
store or conditional store, then kill the register
|
||||
here and add the proper length to its REG_LIVE_LENGTH.
|
||||
|
||||
If we have not seen a use of DREGNO later in this basic
|
||||
block, then we need to add the length from here to the
|
||||
end of the block to the live length. */
|
||||
if (bitmap_bit_p (local_live, dregno))
|
||||
{
|
||||
/* Note that LOCAL_LIVE implies LOCAL_PROCESSED, so
|
||||
we don't have to set LOCAL_PROCESSED in this clause. */
|
||||
if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
|
||||
{
|
||||
REG_LIVE_LENGTH (dregno) +=
|
||||
(luid - local_live_last_luid[dregno]);
|
||||
local_live_last_luid[dregno] = luid;
|
||||
bitmap_clear_bit (local_live, dregno);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bitmap_set_bit (local_processed, dregno);
|
||||
REG_LIVE_LENGTH (dregno) += luid;
|
||||
local_live_last_luid[dregno] = luid;
|
||||
}
|
||||
|
||||
/* Kill this register if it is not a subreg store or
|
||||
conditional store.
|
||||
??? This means that any partial store is live from
|
||||
the last use in a basic block to the start of this
|
||||
basic block. This results in poor calculations of
|
||||
REG_LIVE_LENGTH in large basic blocks. */
|
||||
if (!(DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
|
||||
bitmap_clear_bit (live, dregno);
|
||||
}
|
||||
else if ((!(DF_REF_FLAGS (def) & DF_REF_MW_HARDREG))
|
||||
&& (!bitmap_bit_p (artificial_uses, dregno)))
|
||||
{
|
||||
REG_LIVE_LENGTH (dregno)++;
|
||||
}
|
||||
/* Kill this register if it is not a subreg store or
|
||||
conditional store.
|
||||
??? This means that any partial store is live from
|
||||
the last use in a basic block to the start of this
|
||||
basic block. */
|
||||
if (!(DF_REF_FLAGS (def)
|
||||
& (DF_REF_PARTIAL | DF_REF_CONDITIONAL)))
|
||||
bitmap_clear_bit (live, dregno);
|
||||
|
||||
if (dregno >= FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
|
@ -300,37 +231,8 @@ regstat_bb_compute_ri (unsigned int bb_index,
|
|||
else if (REG_BASIC_BLOCK (uregno) != bb->index)
|
||||
REG_BASIC_BLOCK (uregno) = REG_BLOCK_GLOBAL;
|
||||
}
|
||||
|
||||
if (bitmap_set_bit (live, uregno))
|
||||
{
|
||||
/* This register is now live. Begin to process it locally.
|
||||
|
||||
Note that we don't even get here if the variable was live
|
||||
at the end of the block since just a ref inside the block
|
||||
does not effect the calculations. */
|
||||
REG_LIVE_LENGTH (uregno) ++;
|
||||
local_live_last_luid[uregno] = luid;
|
||||
bitmap_set_bit (local_live, uregno);
|
||||
bitmap_set_bit (local_processed, uregno);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the liveness length to all registers that were used somewhere
|
||||
in this bock, but not between that use and the head of this block. */
|
||||
EXECUTE_IF_SET_IN_BITMAP (local_live, 0, regno, bi)
|
||||
{
|
||||
REG_LIVE_LENGTH (regno) += (luid - local_live_last_luid[regno]);
|
||||
}
|
||||
|
||||
/* Add the length of the block to all of the registers that were not
|
||||
referenced, but still live in this block. */
|
||||
bitmap_and_compl_into (live, local_processed);
|
||||
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
|
||||
REG_LIVE_LENGTH (regno) += luid;
|
||||
|
||||
bitmap_clear (local_processed);
|
||||
bitmap_clear (local_live);
|
||||
}
|
||||
|
||||
|
||||
|
@ -340,12 +242,8 @@ regstat_compute_ri (void)
|
|||
{
|
||||
basic_block bb;
|
||||
bitmap live = BITMAP_ALLOC (&df_bitmap_obstack);
|
||||
bitmap artificial_uses = BITMAP_ALLOC (&df_bitmap_obstack);
|
||||
bitmap local_live = BITMAP_ALLOC (&df_bitmap_obstack);
|
||||
bitmap local_processed = BITMAP_ALLOC (&df_bitmap_obstack);
|
||||
unsigned int regno;
|
||||
bitmap_iterator bi;
|
||||
int *local_live_last_luid;
|
||||
|
||||
/* Initialize everything. */
|
||||
|
||||
|
@ -356,26 +254,18 @@ regstat_compute_ri (void)
|
|||
max_regno = max_reg_num ();
|
||||
reg_info_p_size = max_regno;
|
||||
reg_info_p = XCNEWVEC (struct reg_info_t, max_regno);
|
||||
local_live_last_luid = XNEWVEC (int, max_regno);
|
||||
|
||||
FOR_EACH_BB_FN (bb, cfun)
|
||||
{
|
||||
regstat_bb_compute_ri (bb->index, live, artificial_uses,
|
||||
local_live, local_processed,
|
||||
local_live_last_luid);
|
||||
regstat_bb_compute_ri (bb, live);
|
||||
}
|
||||
|
||||
BITMAP_FREE (live);
|
||||
BITMAP_FREE (artificial_uses);
|
||||
BITMAP_FREE (local_live);
|
||||
BITMAP_FREE (local_processed);
|
||||
free (local_live_last_luid);
|
||||
|
||||
/* See the setjmp comment in regstat_bb_compute_ri. */
|
||||
EXECUTE_IF_SET_IN_BITMAP (setjmp_crosses, FIRST_PSEUDO_REGISTER, regno, bi)
|
||||
{
|
||||
REG_BASIC_BLOCK (regno) = REG_BLOCK_UNKNOWN;
|
||||
REG_LIVE_LENGTH (regno) = -1;
|
||||
}
|
||||
|
||||
timevar_pop (TV_REG_STATS);
|
||||
|
@ -533,11 +423,11 @@ dump_reg_info (FILE *file)
|
|||
enum reg_class rclass, altclass;
|
||||
|
||||
if (regstat_n_sets_and_refs)
|
||||
fprintf (file, "\nRegister %d used %d times across %d insns",
|
||||
i, REG_N_REFS (i), REG_LIVE_LENGTH (i));
|
||||
fprintf (file, "\nRegister %d used %d times",
|
||||
i, REG_N_REFS (i));
|
||||
else if (df)
|
||||
fprintf (file, "\nRegister %d used %d times across %d insns",
|
||||
i, DF_REG_USE_COUNT (i) + DF_REG_DEF_COUNT (i), REG_LIVE_LENGTH (i));
|
||||
fprintf (file, "\nRegister %d used %d times",
|
||||
i, DF_REG_USE_COUNT (i) + DF_REG_DEF_COUNT (i));
|
||||
|
||||
if (REG_BASIC_BLOCK (i) >= NUM_FIXED_BLOCKS)
|
||||
fprintf (file, " in block %d", REG_BASIC_BLOCK (i));
|
||||
|
|
Loading…
Add table
Reference in a new issue