* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131576
138bc75d-0d04-0410-961f-
82ee72b054a4
+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
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));
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);
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)
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. */
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);
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;
/* 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);
&& ! 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)
/* 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;
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
/* 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
}
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. */
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;
}
}
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;
}
}
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
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)
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;
{
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;
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;
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)
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 */
};
/* 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. */
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)++;
{
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