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:
Jan Hubicka 2008-01-16 17:32:05 +01:00 committed by Jan Hubicka
parent 58c0b65244
commit a03c6d64f4
8 changed files with 65 additions and 9 deletions

View file

@ -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

View file

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

View file

@ -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)

View file

@ -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)

View file

@ -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;

View file

@ -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)

View file

@ -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. */

View file

@ -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