Commit a03c6d64 by Jan Hubicka Committed by Jan Hubicka

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
parent 58c0b652
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> 2008-01-16 Sebastian Pop <sebastian.pop@amd.com>
* gcc.c (LINK_COMMAND_SPEC): Add includes and link options for * gcc.c (LINK_COMMAND_SPEC): Add includes and link options for
......
...@@ -613,6 +613,8 @@ dump_reg_info (FILE *file) ...@@ -613,6 +613,8 @@ dump_reg_info (FILE *file)
fprintf (file, "; crosses 1 call"); fprintf (file, "; crosses 1 call");
else if (REG_N_CALLS_CROSSED (i)) else if (REG_N_CALLS_CROSSED (i))
fprintf (file, "; crosses %d calls", 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 if (regno_reg_rtx[i] != NULL
&& PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD) && PSEUDO_REGNO_BYTES (i) != UNITS_PER_WORD)
fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i)); fprintf (file, "; %d bytes", PSEUDO_REGNO_BYTES (i));
......
...@@ -404,6 +404,7 @@ global_alloc (void) ...@@ -404,6 +404,7 @@ global_alloc (void)
allocno[i].reg = regno; allocno[i].reg = regno;
allocno[i].size = PSEUDO_REGNO_SIZE (regno); allocno[i].size = PSEUDO_REGNO_SIZE (regno);
allocno[i].calls_crossed += REG_N_CALLS_CROSSED (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 allocno[i].throwing_calls_crossed
+= REG_N_THROWING_CALLS_CROSSED (regno); += REG_N_THROWING_CALLS_CROSSED (regno);
allocno[i].n_refs += REG_N_REFS (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 ...@@ -1164,8 +1165,9 @@ find_reg (int num, HARD_REG_SET losers, int alt_regs_p, int accept_call_clobbere
if (! accept_call_clobbered if (! accept_call_clobbered
&& allocno[num].calls_crossed != 0 && allocno[num].calls_crossed != 0
&& allocno[num].throwing_calls_crossed == 0 && allocno[num].throwing_calls_crossed == 0
&& CALLER_SAVE_PROFITABLE (allocno[num].n_refs, && CALLER_SAVE_PROFITABLE (optimize_size ? allocno[num].n_refs : allocno[num].freq,
allocno[num].calls_crossed)) optimize_size ? allocno[num].calls_crossed
: allocno[num].freq_calls_crossed))
{ {
HARD_REG_SET new_losers; HARD_REG_SET new_losers;
if (! losers) if (! losers)
......
...@@ -126,6 +126,10 @@ struct qty ...@@ -126,6 +126,10 @@ struct qty
int n_calls_crossed; 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 /* Number of times a reg tied to given qty lives across a CALL_INSN
that might throw. */ that might throw. */
...@@ -332,6 +336,7 @@ alloc_qty (int regno, enum machine_mode mode, int size, int birth) ...@@ -332,6 +336,7 @@ alloc_qty (int regno, enum machine_mode mode, int size, int birth)
qty[qtyno].mode = mode; qty[qtyno].mode = mode;
qty[qtyno].birth = birth; qty[qtyno].birth = birth;
qty[qtyno].n_calls_crossed = REG_N_CALLS_CROSSED (regno); 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].n_throwing_calls_crossed = REG_N_THROWING_CALLS_CROSSED (regno);
qty[qtyno].min_class = reg_preferred_class (regno); qty[qtyno].min_class = reg_preferred_class (regno);
qty[qtyno].alternate_class = reg_alternate_class (regno); qty[qtyno].alternate_class = reg_alternate_class (regno);
...@@ -1193,6 +1198,7 @@ update_equiv_regs (void) ...@@ -1193,6 +1198,7 @@ update_equiv_regs (void)
REG_BASIC_BLOCK (regno) = bb->index; REG_BASIC_BLOCK (regno) = bb->index;
REG_N_CALLS_CROSSED (regno) = 0; REG_N_CALLS_CROSSED (regno) = 0;
REG_FREQ_CALLS_CROSSED (regno) = 0;
REG_N_THROWING_CALLS_CROSSED (regno) = 0; REG_N_THROWING_CALLS_CROSSED (regno) = 0;
REG_LIVE_LENGTH (regno) = 2; REG_LIVE_LENGTH (regno) = 2;
...@@ -2026,6 +2032,7 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number, ...@@ -2026,6 +2032,7 @@ combine_regs (rtx usedreg, rtx setreg, int may_save_copy, int insn_number,
/* Update info about quantity SQTY. */ /* Update info about quantity SQTY. */
qty[sqty].n_calls_crossed += REG_N_CALLS_CROSSED (sreg); 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 qty[sqty].n_throwing_calls_crossed
+= REG_N_THROWING_CALLS_CROSSED (sreg); += REG_N_THROWING_CALLS_CROSSED (sreg);
qty[sqty].n_refs += REG_N_REFS (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, ...@@ -2338,8 +2345,9 @@ find_free_reg (enum reg_class class, enum machine_mode mode, int qtyno,
&& ! just_try_suggested && ! just_try_suggested
&& qty[qtyno].n_calls_crossed != 0 && qty[qtyno].n_calls_crossed != 0
&& qty[qtyno].n_throwing_calls_crossed == 0 && qty[qtyno].n_throwing_calls_crossed == 0
&& CALLER_SAVE_PROFITABLE (qty[qtyno].n_refs, && CALLER_SAVE_PROFITABLE (optimize_size ? qty[qtyno].n_refs : qty[qtyno].freq,
qty[qtyno].n_calls_crossed)) 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); i = find_free_reg (class, mode, qtyno, 1, 0, born_index, dead_index);
if (i >= 0) if (i >= 0)
......
...@@ -32,6 +32,9 @@ struct allocno ...@@ -32,6 +32,9 @@ struct allocno
/* Number of calls crossed by each allocno. */ /* Number of calls crossed by each allocno. */
int calls_crossed; 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. */ /* Number of calls that might throw crossed by each allocno. */
int throwing_calls_crossed; int throwing_calls_crossed;
......
...@@ -506,6 +506,8 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src) ...@@ -506,6 +506,8 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
int s_length = 0; int s_length = 0;
int d_n_calls = 0; int d_n_calls = 0;
int s_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, /* We can do the optimization. Scan forward from INSN again,
replacing regs as we go. Set FAILED if a replacement can't 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) ...@@ -556,8 +558,12 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
/* Similarly, total calls for SREGNO, total calls beyond /* Similarly, total calls for SREGNO, total calls beyond
the death note for DREGNO. */ the death note for DREGNO. */
s_n_calls++; s_n_calls++;
s_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
if (dest_death) 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 /* 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) ...@@ -590,6 +596,7 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
} }
REG_N_CALLS_CROSSED (sregno) -= s_n_calls; 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. */ /* Move death note of SRC from P to INSN. */
...@@ -619,6 +626,7 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src) ...@@ -619,6 +626,7 @@ optimize_reg_copy_1 (rtx insn, rtx dest, rtx src)
if (REG_LIVE_LENGTH (dregno) >= 0) if (REG_LIVE_LENGTH (dregno) >= 0)
REG_LIVE_LENGTH (dregno) += d_length; REG_LIVE_LENGTH (dregno) += d_length;
REG_N_CALLS_CROSSED (dregno) += d_n_calls; 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) ...@@ -684,8 +692,11 @@ optimize_reg_copy_2 (rtx insn, rtx dest, rtx src)
if (CALL_P (q)) if (CALL_P (q))
{ {
int freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q));
REG_N_CALLS_CROSSED (dregno)--; REG_N_CALLS_CROSSED (dregno)--;
REG_N_CALLS_CROSSED (sregno)++; REG_N_CALLS_CROSSED (sregno)++;
REG_FREQ_CALLS_CROSSED (dregno) -= freq;
REG_FREQ_CALLS_CROSSED (sregno) += freq;
} }
} }
...@@ -953,7 +964,7 @@ static int ...@@ -953,7 +964,7 @@ static int
fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset) fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
{ {
rtx p, dst_death = 0; 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 /* 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 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) ...@@ -997,6 +1008,7 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
remove_death (REGNO (dst), dst_death); remove_death (REGNO (dst), dst_death);
REG_LIVE_LENGTH (REGNO (dst)) += length; REG_LIVE_LENGTH (REGNO (dst)) += length;
REG_N_CALLS_CROSSED (REGNO (dst)) += num_calls; REG_N_CALLS_CROSSED (REGNO (dst)) += num_calls;
REG_FREQ_CALLS_CROSSED (REGNO (dst)) += freq_calls;
} }
if (dump_file) if (dump_file)
...@@ -1049,7 +1061,10 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset) ...@@ -1049,7 +1061,10 @@ fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset)
if (CALL_P (p)) if (CALL_P (p))
{ {
if (! dst_death) 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) if (REG_N_CALLS_CROSSED (REGNO (src)) == 0)
break; break;
...@@ -1276,7 +1291,7 @@ regmove_optimize (rtx f, int nregs) ...@@ -1276,7 +1291,7 @@ regmove_optimize (rtx f, int nregs)
{ {
rtx set, p, src, dst; rtx set, p, src, dst;
rtx src_note, dst_note; rtx src_note, dst_note;
int num_calls = 0; int num_calls = 0, freq_calls = 0;
enum reg_class src_class, dst_class; enum reg_class src_class, dst_class;
int length; int length;
...@@ -1465,6 +1480,7 @@ regmove_optimize (rtx f, int nregs) ...@@ -1465,6 +1480,7 @@ regmove_optimize (rtx f, int nregs)
if (CALL_P (p)) if (CALL_P (p))
{ {
num_calls++; num_calls++;
freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p));
if (REG_N_CALLS_CROSSED (REGNO (dst)) == 0) if (REG_N_CALLS_CROSSED (REGNO (dst)) == 0)
break; break;
...@@ -1497,6 +1513,8 @@ regmove_optimize (rtx f, int nregs) ...@@ -1497,6 +1513,8 @@ regmove_optimize (rtx f, int nregs)
REG_N_CALLS_CROSSED (dstno) += num_calls; REG_N_CALLS_CROSSED (dstno) += num_calls;
REG_N_CALLS_CROSSED (srcno) -= 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; REG_LIVE_LENGTH (dstno) += length;
if (REG_LIVE_LENGTH (srcno) >= 0) if (REG_LIVE_LENGTH (srcno) >= 0)
......
...@@ -115,6 +115,7 @@ struct reg_info_t ...@@ -115,6 +115,7 @@ struct reg_info_t
int deaths; /* # of times (REG n) dies */ int deaths; /* # of times (REG n) dies */
int live_length; /* # of instructions (REG n) is live */ int live_length; /* # of instructions (REG n) is live */
int calls_crossed; /* # of calls (REG n) is live across */ 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 throw_calls_crossed; /* # of calls that may throw (REG n) is live across */
int basic_block; /* # of basic blocks (REG n) is used in */ int basic_block; /* # of basic blocks (REG n) is used in */
}; };
...@@ -172,6 +173,7 @@ extern size_t reg_info_p_size; ...@@ -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. */ /* 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_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 /* Indexed by N, gives number of CALL_INSNS that may throw, across which
(REG n) is live. */ (REG n) is live. */
......
...@@ -180,6 +180,7 @@ regstat_bb_compute_ri (unsigned int bb_index, ...@@ -180,6 +180,7 @@ regstat_bb_compute_ri (unsigned int bb_index,
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, 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);
if (can_throw) if (can_throw)
REG_N_THROWING_CALLS_CROSSED (regno)++; REG_N_THROWING_CALLS_CROSSED (regno)++;
...@@ -445,7 +446,10 @@ regstat_bb_compute_calls_crossed (unsigned int bb_index, bitmap live) ...@@ -445,7 +446,10 @@ regstat_bb_compute_calls_crossed (unsigned int bb_index, bitmap live)
{ {
bitmap_iterator bi; bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (live, 0, regno, 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 /* All of the defs except the return value are some sort of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment