https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58315
--- Comment #20 from rguenther at suse dot de <rguenther at suse dot de> --- On Mon, 23 Feb 2015, aldyh at gcc dot gnu.org wrote: > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58315 > > Aldy Hernandez <aldyh at gcc dot gnu.org> changed: > > What |Removed |Added > ---------------------------------------------------------------------------- > CC| |jason at gcc dot gnu.org, > | |rguenth at gcc dot gnu.org > > --- Comment #16 from Aldy Hernandez <aldyh at gcc dot gnu.org> --- > Among other things (because I'm not 100% sure this is the only thing wrong > here) we seem to be generating and awful lot of GIMPLE_DEBUG statements, even > for intermediate values we will throw away. > > I am not sure whether this is just a very inefficient testcase, a byproduct of > the way we expand expressions, or the myriad of DEBUG statements we create. > > For instance, in a snippet of the testcase: > > Variable A(0); > Variable B(1); > Variable C(2); > Variable D(3); > Constraint_System cs; > > cs.insert(Coefficient("2251799813685248")*A > >= Coefficient("-5895288448651847")); > cs.insert(Coefficient("5895288437392848")*A > + Coefficient("3643488632714799")*B > - Coefficient("2251799813685248")*C > >= Coefficient("-19077554137963492")); > ... > > ...we create a temporary instance for each Coefficient constructor call, as > well as a temporary instance for the result of the '*' and '>=' operators, and > a temporary instance for the conversion of [ABC] to a Linear_Expression. > Basically, we create temporary instances of every class we create along the > way > (expected), but unfortunately we then create DEBUG statements for each > destructor call in each temporary variable that was created, particularly for > the `this' pointer which is quite useless for debugging IMO. > > For instance, the result of the ">=" operator gets stored in D.166575, but as > you can see below, there are quite a few DEBUG statements for this temporary > which will never see the light of (debugging) day: > > D.166575 = Parma_Polyhedra_Library::operator>= (&D.166573, &D.166574); > > <bb 7>: > Parma_Polyhedra_Library::Constraint_System::insert (&cs, &D.166575); > > <bb 8>: > # DEBUG this => &D.166575 > # DEBUG D#21 => &D.166575.D.73843 > # DEBUG this => D#21 > # DEBUG D#19 => &D#21->D.67748 > # DEBUG this => D#19 > _1448 = &MEM[(struct Row *)&D.166575].D.66121; > Parma_Polyhedra_Library::Row_Impl_Handler::~Row_Impl_Handler (_1448); > > If you look at the "einline" tree dump, you can see numerous DEBUG statements > for each destructor call: > > MEM[(struct &)&D.166591] ={v} {CLOBBER}; > # DEBUG <L0> => NULL > MEM[(struct &)&D.166591] ={v} {CLOBBER}; > # DEBUG <L0> => NULL > MEM[(struct &)&D.166591] ={v} {CLOBBER}; > # DEBUG <L0> => NULL > D.166591 ={v} {CLOBBER}; > # DEBUG this => &D.166589 > # DEBUG D#20 => &D.166589.D.71066 > # DEBUG this => D#20 > # DEBUG D#19 => &D#20->D.67748 > # DEBUG this => D#19 > _1479 = &MEM[(struct Row *)&D.166589].D.66121; > Parma_Polyhedra_Library::Row_Impl_Handler::~Row_Impl_Handler (_1479); > > ad nauseum. > > These DEBUG statements eventually end up as a multitude of VAR_LOCATION rtl > notes that take an awful lot of memory to process. As I've said, I'm not 100% > this is the problem, but I'm quite suspect. It's true that the temporary object D.166591 cannot be accessed from the debugger (it has no name) but we still create debug stmts for its _address_ - to which the debugger can refer to via named 'this' (from some inline code). But yes, we have multiple such assignments to 'this' at the (possible assembler) location of a single statement which of course doesn't help. Thus we should DCE the debug stmt sequences between real stmts like > D.166591 ={v} {CLOBBER}; > # DEBUG this => &D.166589 > # DEBUG D#20 => &D.166589.D.71066 > # DEBUG this => D#20 > # DEBUG D#19 => &D#20->D.67748 > # DEBUG this => D#19 > _1479 = &MEM[(struct Row *)&D.166589].D.66121; to the following at least ("DSE" actually, based on the actual name of the LHS a debugger might use to refer to the variable) > D.166591 ={v} {CLOBBER}; > # DEBUG D#20 => &D.166589.D.71066 > # DEBUG D#19 => &D#20->D.67748 > # DEBUG this => D#19 > _1479 = &MEM[(struct Row *)&D.166589].D.66121; As to "between stmts" that is because after each 'stepi' in the debugger you reach a new state computed by var-tracking. Intermediate state-transitions are not interesting as long as you preserve the "last" state before the next instruction. Thus in reality you'd want to perform this DCE/DSE right before var-tracking (or during the var-tracking insn scan phase) > Also, it may not be the DEBUG statements at fault, but the inefficiency > of the testcase itself (creating all these objects), in which case, > perhaps we could notice this behavior at var-tracking time, and bail? > Though this sounds like a kludge. Of course the issue is very large and repetitive functions. Thus another idea is to simply split up such functions. If just by making var-tracking work on SESE (or SEME) regions and dealing with the boundaries conservatively. Eventually this can be "hacked" by fake splitting/restoring the CFG around vt_initialize/vt_find_locations/vt_finalize. Maybe easier than to make them work on a CFG region.