diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-16 16:32:05 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-01-16 16:32:05 +0000 |
commit | a8587796a0c5e2006243ff081b3e1fc4ae73e10b (patch) | |
tree | e7a65553b87a99438635f0d5abcf71b9c8210b5c | |
parent | 2f22ee0fb0272e2013989fc41c09da385994f99e (diff) | |
download | gcc-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/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/cfg.c | 2 | ||||
-rw-r--r-- | gcc/global.c | 6 | ||||
-rw-r--r-- | gcc/local-alloc.c | 12 | ||||
-rw-r--r-- | gcc/ra.h | 3 | ||||
-rw-r--r-- | gcc/regmove.c | 26 | ||||
-rw-r--r-- | gcc/regs.h | 2 | ||||
-rw-r--r-- | gcc/regstat.c | 6 |
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) @@ -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 |