Message ID | 20111030.215542.1009225198168800058.davem@davemloft.net |
---|---|
State | New |
Headers | show |
On Sun, Oct 30, 2011 at 09:55:42PM -0400, David Miller wrote: > --- a/gcc/dwarf2out.c > +++ b/gcc/dwarf2out.c > @@ -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 I think for next_note being NOTE_INSN_VAR_LOCATION you want to set next_note to NULL_RTX if !DECL_P (NOTE_VAR_LOCATION_DECL (next_note)). Otherwise you risk that the above if (var_loc_p && !DECL_P (NOTE_VAR_LOCATION_DECL (loc_note))) return; will not clear the cache, you reach end of function and in the next function when dwarf2out_var_location is called for the first time, cached_next_real_insn will be non-NULL and if you have really bad luck it will be called on insn that has the same address as expected_next_loc_note (GC collection could happen in between). Or alternatively you could remove the whole if (! !next_note ...) next_note = NULL_RTX; stmt and move your cache to a global var and clear it when reaching end of function (like e.g. last_var_location_insn is cleared in dwarf2out_end_epilogue). Jakub
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 <davem@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 <ubizjak@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. */