summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2008-01-16 16:32:05 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2008-01-16 16:32:05 +0000
commita8587796a0c5e2006243ff081b3e1fc4ae73e10b (patch)
treee7a65553b87a99438635f0d5abcf71b9c8210b5c
parent2f22ee0fb0272e2013989fc41c09da385994f99e (diff)
downloadgcc-a8587796a0c5e2006243ff081b3e1fc4ae73e10b.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@131576 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/cfg.c2
-rw-r--r--gcc/global.c6
-rw-r--r--gcc/local-alloc.c12
-rw-r--r--gcc/ra.h3
-rw-r--r--gcc/regmove.c26
-rw-r--r--gcc/regs.h2
-rw-r--r--gcc/regstat.c6
8 files changed, 65 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 37a6f4ec35c..8e2caec9b16 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 0b0e9503b2b..8a83137aaa5 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -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));
diff --git a/gcc/global.c b/gcc/global.c
index de6beb91fb4..8be113df60a 100644
--- a/gcc/global.c
+++ b/gcc/global.c
@@ -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)
diff --git a/gcc/local-alloc.c b/gcc/local-alloc.c
index 4ef1f021f03..9569a36e707 100644
--- a/gcc/local-alloc.c
+++ b/gcc/local-alloc.c
@@ -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)
diff --git a/gcc/ra.h b/gcc/ra.h
index d35d2013d6c..4081df347ca 100644
--- a/gcc/ra.h
+++ b/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;
diff --git a/gcc/regmove.c b/gcc/regmove.c
index 4cb083cbd48..9a071876937 100644
--- a/gcc/regmove.c
+++ b/gcc/regmove.c
@@ -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)
diff --git a/gcc/regs.h b/gcc/regs.h
index 192883be486..f0679f753e9 100644
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -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. */
diff --git a/gcc/regstat.c b/gcc/regstat.c
index 9f8e41f35af..26f96070472 100644
--- a/gcc/regstat.c
+++ b/gcc/regstat.c
@@ -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