re PR rtl-optimization/31396 (Inline code performance much worse than out-of-line)
PR rtl-optimization/31396 * regstat.c (regstat_bb_compute_ri): Compute FREQ_CALLS_CROSSED. * cfg.c (dump_reg_info): Print it. * regs.h (struct reg_info_t): add freq_calls_crossed. (REG_FREQ_CALLS_CROSSED): New macro. * global.c (global_alloc): Compute freq_calls_crossed for allocno. (find_reg): Update call of CALLER_SAVE_PROFITABLE. * regmove.c (optimize_reg_copy_1, optimize_reg_copy_2, fixup_match_2, regmove_optimize): Update call crossed frequencies. * local-alloc.c (struct qty): Add freq_calls_crossed. (alloc_qty): Copute freq_calls_crossed. (update_equiv_regs, combine_regs): Update REG_FREQ_CALLS_CROSSED. (find_free_reg): Update call of CALLER_SAVE_PROFITABLE. * ra.h (struct allocno): Add freq_calls_crossed. From-SVN: r131576
This commit is contained in:
parent
58c0b65244
commit
a03c6d64f4
8 changed files with 65 additions and 9 deletions
|
@ -1,3 +1,20 @@
|
|||
2008-01-16 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
PR rtl-optimization/31396
|
||||
* regstat.c (regstat_bb_compute_ri): Compute FREQ_CALLS_CROSSED.
|
||||
* cfg.c (dump_reg_info): Print it.
|
||||
* regs.h (struct reg_info_t): add freq_calls_crossed.
|
||||
(REG_FREQ_CALLS_CROSSED): New macro.
|
||||
* global.c (global_alloc): Compute freq_calls_crossed for allocno.
|
||||
(find_reg): Update call of CALLER_SAVE_PROFITABLE.
|
||||
* regmove.c (optimize_reg_copy_1, optimize_reg_copy_2, fixup_match_2,
|
||||
regmove_optimize): Update call crossed frequencies.
|
||||
* local-alloc.c (struct qty): Add freq_calls_crossed.
|
||||
(alloc_qty): Copute freq_calls_crossed.
|
||||
(update_equiv_regs, combine_regs): Update REG_FREQ_CALLS_CROSSED.
|
||||
(find_free_reg): Update call of CALLER_SAVE_PROFITABLE.
|
||||
* ra.h (struct allocno): Add freq_calls_crossed.
|
||||
|
||||
2008-01-16 Sebastian Pop <sebastian.pop@amd.com>
|
||||
|
||||
* gcc.c (LINK_COMMAND_SPEC): Add includes and link options for
|
||||
|
|
|
@ -613,6 +613,8 @@ dump_reg_info (FILE *file)
|
|||
fprintf (file, "; crosses 1 call");
|
||||
else if (REG_N_CALLS_CROSSED (i))
|
||||
fprintf (file, "; crosses %d calls", REG_N_CALLS_CROSSED (i));
|
||||
if (REG_FREQ_CALLS_CROSSED (i))
|
||||
fprintf (file, "; crosses call with %d frequency", REG_FREQ_CALLS_CROSSED (i));
|
||||
if (regno_reg_rtx[i] != NULL
|
||||
&& PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
|
||||
fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
|
||||
|
|
|
@ -404,6 +404,7 @@ global_alloc (void)
|
|||
allocno[i].reg = regno;
|
||||
allocno[i].size = PSEUDO_REGNO_SIZE (regno);
|
||||
allocno[i].calls_crossed += REG_N_CALLS_CROSSED (regno);
|
||||
allocno[i].freq_calls_crossed += REG_FREQ_CALLS_CROSSED (regno);
|
||||
allocno[i].throwing_calls_crossed
|
||||
+= REG_N_THROWING_CALLS_CROSSED (regno);
|
||||
allocno[i].n_refs += REG_N_REFS (regno);
|
||||
|
@ -1164,8 +1165,9 @@ find_reg (int num, HARD_REG_SET losers, int alt_regs_p, int accept_call_clobbere
|
|||
if (! accept_call_clobbered
|
||||
&& allocno[num].calls_crossed != 0
|
||||
&& allocno[num].throwing_calls_crossed == 0
|
||||
&& CALLER_SAVE_PROFITABLE (allocno[num].n_refs,
|
||||
allocno[num].calls_crossed))
|
||||
&& CALLER_SAVE_PROFITABLE (optimize_size ? allocno[num].n_refs : allocno[num].freq,
|
||||
optimize_size ? allocno[num].calls_crossed
|
||||
: allocno[num].freq_calls_crossed))
|
||||
{
|
||||
HARD_REG_SET new_losers;
|
||||
if (! losers)
|
||||
|
|
|
@ -126,6 +126,10 @@ struct qty
|
|||
|
||||
int n_calls_crossed;
|
||||
|
||||
/* Number of times a reg tied to given qty lives across a CALL_INSN. */
|
||||
|
||||
int freq_calls_crossed;
|
||||
|
||||
/* Number of times a reg tied to given qty lives across a CALL_INSN
|
||||
that might throw. */
|
||||
|
||||
|
@ -332,6 +336,7 @@ alloc_qty (int regno, enum machine_mode mode, int size, int birth)
|
|||
qty[qtyno].mode = mode;
|
||||
qty[qtyno].birth = birth;
|
||||
qty[qtyno].n_calls_crossed = REG_N_CALLS_CROSSED (regno);
|
||||
qty[qtyno].freq_calls_crossed = REG_FREQ_CALLS_CROSSED (regno);
|
||||
qty[qtyno].n_throwing_calls_crossed = REG_N_THROWING_CALLS_CROSSED (regno);
|
||||
qty[qtyno].min_class = reg_preferred_class (regno);
|
||||
qty[qtyno].alternate_class = reg_alternate_class (regno);
|
||||
|
@ -1193,6 +1198,7 @@ update_equiv_regs (void)
|
|||
|
||||
REG_BASIC_BLOCK (regno) = bb->index;
|
||||
REG_N_CALLS_CROSSED (regno) = 0;
|
||||
REG_FREQ_CALLS_CROSSED (regno) = 0;
|
||||
REG_N_THROWING_CALLS_CROSSED (regno) = 0;
|
||||
REG_LIVE_LENGTH (regno) = 2;
|
||||
|
||||
|
@ -2026,6 +2032,7 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
|
|||
|
||||
/* Update info about quantity SQTY. */
|
||||
qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg);
|
||||
qty[sqty].freq_calls_crossed += REG_FREQ_CALLS_CROSSED (sreg);
|
||||
qty[sqty].n_throwing_calls_crossed
|
||||
+= REG_N_THROWING_CALLS_CROSSED (sreg);
|
||||
qty[sqty].n_refs += REG_N_REFS (sreg);
|
||||
|
@ -2338,8 +2345,9 @@ find_free_reg (enum reg_class class, enum machine_mode mode, int qtyno,
|
|||
&& ! just_try_suggested
|
||||
&& qty[qtyno].n_calls_crossed != 0
|
||||
&& qty[qtyno].n_throwing_calls_crossed == 0
|
||||
&& CALLER_SAVE_PROFITABLE (qty[qtyno].n_refs,
|
||||
qty[qtyno].n_calls_crossed))
|
||||
&& CALLER_SAVE_PROFITABLE (optimize_size ? qty[qtyno].n_refs : qty[qtyno].freq,
|
||||
optimize_size ? qty[qtyno].n_calls_crossed
|
||||
: qty[qtyno].freq_calls_crossed))
|
||||
{
|
||||
i = find_free_reg (class, mode, qtyno, 1, 0, born_index, dead_index);
|
||||
if (i >= 0)
|
||||
|
|
3
gcc/ra.h
3
gcc/ra.h
|
@ -32,6 +32,9 @@ struct allocno
|
|||
/* Number of calls crossed by each allocno. */
|
||||
int calls_crossed;
|
||||
|
||||
/* Estimated frequency of crossing call by each allocno. */
|
||||
int freq_calls_crossed;
|
||||
|
||||
/* Number of calls that might throw crossed by each allocno. */
|
||||
int throwing_calls_crossed;
|
||||
|
||||
|
|
|
@ -506,6 +506,8 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
|
|||
int s_length = 0;
|
||||
int d_n_calls = 0;
|
||||
int s_n_calls = 0;
|
||||
int s_freq_calls = 0;
|
||||
int d_freq_calls = 0;
|
||||
|
||||
/* We can do the optimization. Scan forward from INSN again,
|
||||
replacing regs as we go. Set FAILED if a replacement can't
|
||||
|
@ -556,8 +558,12 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
|
|||
/* Similarly, total calls for SREGNO, total calls beyond
|
||||
the death note for DREGNO. */
|
||||
s_n_calls++;
|
||||
s_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
|
||||
if (dest_death)
|
||||
d_n_calls++;
|
||||
{
|
||||
d_n_calls++;
|
||||
d_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
|
||||
}
|
||||
}
|
||||
|
||||
/* If DEST dies here, remove the death note and save it for
|
||||
|
@ -590,6 +596,7 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
|
|||
}
|
||||
|
||||
REG_N_CALLS_CROSSED (sregno) -= s_n_calls;
|
||||
REG_FREQ_CALLS_CROSSED (sregno) -= s_freq_calls;
|
||||
}
|
||||
|
||||
/* Move death note of SRC from P to INSN. */
|
||||
|
@ -619,6 +626,7 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
|
|||
if (REG_LIVE_LENGTH (dregno) >= 0)
|
||||
REG_LIVE_LENGTH (dregno) += d_length;
|
||||
REG_N_CALLS_CROSSED (dregno) += d_n_calls;
|
||||
REG_FREQ_CALLS_CROSSED (dregno) += d_freq_calls;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -684,8 +692,11 @@ optimize_reg_copy_2 (rtx insn, rtx dest, rtx src)
|
|||
|
||||
if (CALL_P (q))
|
||||
{
|
||||
int freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
|
||||
REG_N_CALLS_CROSSED (dregno)--;
|
||||
REG_N_CALLS_CROSSED (sregno)++;
|
||||
REG_FREQ_CALLS_CROSSED (dregno) -= freq;
|
||||
REG_FREQ_CALLS_CROSSED (sregno) += freq;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -953,7 +964,7 @@ static int
|
|||
fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
|
||||
{
|
||||
rtx p, dst_death = 0;
|
||||
int length, num_calls = 0;
|
||||
int length, num_calls = 0, freq_calls = 0;
|
||||
|
||||
/* If SRC dies in INSN, we'd have to move the death note. This is
|
||||
considered to be very unlikely, so we just skip the optimization
|
||||
|
@ -997,6 +1008,7 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
|
|||
remove_death (REGNO (dst), dst_death);
|
||||
REG_LIVE_LENGTH (REGNO (dst)) += length;
|
||||
REG_N_CALLS_CROSSED (REGNO (dst)) += num_calls;
|
||||
REG_FREQ_CALLS_CROSSED (REGNO (dst)) += freq_calls;
|
||||
}
|
||||
|
||||
if (dump_file)
|
||||
|
@ -1049,7 +1061,10 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
|
|||
if (CALL_P (p))
|
||||
{
|
||||
if (! dst_death)
|
||||
num_calls++;
|
||||
{
|
||||
num_calls++;
|
||||
freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
|
||||
}
|
||||
|
||||
if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
|
||||
break;
|
||||
|
@ -1276,7 +1291,7 @@ regmove_optimize (rtx f, int nregs)
|
|||
{
|
||||
rtx set, p, src, dst;
|
||||
rtx src_note, dst_note;
|
||||
int num_calls = 0;
|
||||
int num_calls = 0, freq_calls = 0;
|
||||
enum reg_class src_class, dst_class;
|
||||
int length;
|
||||
|
||||
|
@ -1465,6 +1480,7 @@ regmove_optimize (rtx f, int nregs)
|
|||
if (CALL_P (p))
|
||||
{
|
||||
num_calls++;
|
||||
freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
|
||||
|
||||
if (REG_N_CALLS_CROSSED (REGNO (dst)) == 0)
|
||||
break;
|
||||
|
@ -1497,6 +1513,8 @@ regmove_optimize (rtx f, int nregs)
|
|||
|
||||
REG_N_CALLS_CROSSED (dstno) += num_calls;
|
||||
REG_N_CALLS_CROSSED (srcno) -= num_calls;
|
||||
REG_FREQ_CALLS_CROSSED (dstno) += freq_calls;
|
||||
REG_FREQ_CALLS_CROSSED (srcno) -= freq_calls;
|
||||
|
||||
REG_LIVE_LENGTH (dstno) += length;
|
||||
if (REG_LIVE_LENGTH (srcno) >= 0)
|
||||
|
|
|
@ -115,6 +115,7 @@ struct reg_info_t
|
|||
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 */
|
||||
int basic_block; /* # of basic blocks (REG n) is used in */
|
||||
};
|
||||
|
@ -172,6 +173,7 @@ extern size_t reg_info_p_size;
|
|||
/* Indexed by N, gives number of CALL_INSNS across which (REG n) is live. */
|
||||
|
||||
#define REG_N_CALLS_CROSSED(N) (reg_info_p[N].calls_crossed)
|
||||
#define REG_FREQ_CALLS_CROSSED(N) (reg_info_p[N].freq_calls_crossed)
|
||||
|
||||
/* Indexed by N, gives number of CALL_INSNS that may throw, across which
|
||||
(REG n) is live. */
|
||||
|
|
|
@ -180,6 +180,7 @@ regstat_bb_compute_ri (unsigned int bb_index,
|
|||
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
|
||||
{
|
||||
REG_N_CALLS_CROSSED (regno)++;
|
||||
REG_FREQ_CALLS_CROSSED (regno) += REG_FREQ_FROM_BB (bb);
|
||||
if (can_throw)
|
||||
REG_N_THROWING_CALLS_CROSSED (regno)++;
|
||||
|
||||
|
@ -445,7 +446,10 @@ regstat_bb_compute_calls_crossed (unsigned int bb_index, bitmap live)
|
|||
{
|
||||
bitmap_iterator bi;
|
||||
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, bi)
|
||||
REG_N_CALLS_CROSSED (regno)++;
|
||||
{
|
||||
REG_N_CALLS_CROSSED (regno)++;
|
||||
REG_FREQ_CALLS_CROSSED (regno) += REG_FREQ_FROM_BB (bb);
|
||||
}
|
||||
}
|
||||
|
||||
/* All of the defs except the return value are some sort of
|
||||
|
|
Loading…
Add table
Reference in a new issue