Tests such as limits-fndefn.c spend %97 of their time in next_real_insn() when -g is on the command line.
It's the invocation from dwarf2out_var_location(). These test cases are basically 100,000 consecutive var location notes, followed by a real instruction. This is similar to the reorg issue I dealt with yesterday, we basically scan the entire function over and over again. How I handle this here is if we see that the next insn is yet another var location note we cache the next_real_insn() result. Now limits-fndefn.c with "-O3 -g" takes about 20 seconds instead of several minutes on my Niagara-T3 box. Committed to trunk. gcc/ * dwarf2out.c (dwarf2out_var_location): When processing several consecutive location notes, cache the result of next_real_insn(). git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180695 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 5 +++++ gcc/dwarf2out.c | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 26bb1a9..037138a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2011-10-30 David S. Miller <da...@davemloft.net> + + * dwarf2out.c (dwarf2out_var_location): When processing several + consecutive location notes, cache the result of next_real_insn(). + 2011-10-30 Uros Bizjak <ubiz...@gmail.com> * config/i386/i386.md (avx2_vec_dup<mode>): Macroize insn from diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 8d5a9f0..478952f 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -20127,10 +20127,12 @@ dwarf2out_var_location (rtx loc_note) { char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2]; struct var_loc_node *newloc; - rtx next_real; + rtx next_real, next_note; static const char *last_label; static const char *last_postcall_label; static bool last_in_cold_section_p; + static rtx expected_next_loc_note; + static rtx cached_next_real_insn; tree decl; bool var_loc_p; @@ -20149,7 +20151,35 @@ dwarf2out_var_location (rtx loc_note) if (var_loc_p && !DECL_P (NOTE_VAR_LOCATION_DECL (loc_note))) return; - next_real = next_real_insn (loc_note); + /* Optimize processing a large consecutive sequence of location + notes so we don't spend too much time in next_real_insn. If the + next insn is another location note, remember the next_real_insn + calculation for next time. */ + next_real = cached_next_real_insn; + if (next_real) + { + if (expected_next_loc_note != loc_note) + next_real = NULL_RTX; + } + + next_note = NEXT_INSN (loc_note); + if (! next_note + || INSN_DELETED_P (next_note) + || GET_CODE (next_note) != NOTE + || (NOTE_KIND (next_note) != NOTE_INSN_VAR_LOCATION + && NOTE_KIND (next_note) != NOTE_INSN_CALL_ARG_LOCATION)) + next_note = NULL_RTX; + + if (! next_real) + next_real = next_real_insn (loc_note); + + if (next_note) + { + expected_next_loc_note = next_note; + cached_next_real_insn = next_real; + } + else + cached_next_real_insn = NULL_RTX; /* If there are no instructions which would be affected by this note, don't do anything. */ -- 1.7.6.401.g6a319