<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Feb 5, 2016 at 5:04 PM, Peter Collingbourne <span dir="ltr"><<a href="mailto:peter@pcc.me.uk" target="_blank">peter@pcc.me.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thanks, I'll look into that. (Though earlier you told me that debug info<br>
for types could be extended while walking the IR, so I wouldn't have thought<br>
that would have worked.)<br>
<br></blockquote><div><br></div><div>Yeah, had to think about it more - and as I think about it - I'm moderately sure type units (which don't include these latent extensions) will be pretty close to static. With just the stmt_list relocation in non-fission type units which /should/ still be knowable up-front.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Peter<br>
<div><div><br>
On Fri, Feb 05, 2016 at 03:52:19PM -0800, David Blaikie wrote:<br>
> Will look more closely soon - but I'd really try just writing out type<br>
> units to MC as soon as they're done. It should be relatively non-intrusive<br>
> (we build type units once, there's no ambiguity about when they're done) -<br>
> for non-fission+type units it might be a bit tricky, because the type units<br>
> still need a relocation for the stmt_list* (I'm trying to find where that's<br>
> added now... I seem to have lost it), but fission+type units should produce<br>
> entirely static type units that are knowable the moment the type is being<br>
> emitted so far as I can tell (including the type hash and everything - you<br>
> can write the bytes out to the AsmStreamer, etc and forget about them<br>
> entirely except to keep the hash to know that you don't need to emit it<br>
> again.<br>
><br>
> I imagine this would provide all the memory savings we would need for much<br>
> of anything (since types are most of the debug info), and, if not, would be<br>
> a good start.<br>
><br>
> *I think we might know what the stmt_list relocation is up-front, though -<br>
> if that's the case we'd be able to be as aggressive as I described is the<br>
> case for fission<br>
><br>
> On Fri, Feb 5, 2016 at 3:17 PM, Peter Collingbourne <<a href="mailto:peter@pcc.me.uk" target="_blank">peter@pcc.me.uk</a>> wrote:<br>
><br>
> > Hi all,<br>
> ><br>
> > We have profiled [1] the memory usage in LLVM when LTO'ing Chromium, and<br>
> > we've found that one of the top consumers of memory is the DWARF emitter in<br>
> > lib/CodeGen/AsmPrinter/Dwarf*. I've been reading the DWARF emitter code and<br>
> > I have a few ideas in mind for how to reduce its memory consumption. One<br>
> > idea I've had is to restructure the emitter so that (for the most part) it<br>
> > directly produces the bytes and relocations that need to go into the DWARF<br>
> > sections without going through other data structures such as DIE and<br>
> > DIEValue.<br>
> ><br>
> > I understand that the DWARF emitter needs to accommodate incomplete<br>
> > entities<br>
> > that may be completed elsewhere during tree construction (e.g. abstract<br>
> > origins<br>
> > for inlined functions, special members for types), so here's a quick<br>
> > high-level<br>
> > sketch of the data structures that I believe could support this design:<br>
> ><br>
> > struct DIEBlock {<br>
> >   SmallVector<char, 1> Data;<br>
> >   std::vector<InternalReloc> IntRelocs;<br>
> >   std::vector<ExternalReloc> ExtRelocs;<br>
> >   DIEBlock *Next;<br>
> > };<br>
> ><br>
> > // This would be used to represent things like DW_AT_type references to<br>
> > types<br>
> > struct InternalReloc {<br>
> >   size_t Offset; // offset within DIEBlock::Data<br>
> >   DIEBlock *Target; // the offset within Target is at<br>
> > Data[Offset...Offset+Size]<br>
> > };<br>
> ><br>
> > // This would be used to represent things like pointers to<br>
> > .debug_loc/.debug_str or to functions/globals<br>
> > struct ExternalReloc {<br>
> >   size_t Offset; // offset within DIEBlock::Data<br>
> >   MCSymbol *Target; // the offset within Target is at<br>
> > Data[Offset...Offset+Size]<br>
> > };<br>
> ><br>
> > struct DwarfBuilder {<br>
> >   DIEBlock *First;<br>
> >   DIEBlock *Cur;<br>
> >   DenseMap<DISubprogram *, DIEBlock *> Subprograms;<br>
> >   DenseMap<DIType *, DIEBlock *> Types;<br>
> >   DwarfBuilder() : First(new DIEBlock), Cur(First) {}<br>
> >   // builder implementation goes here...<br>
> > };<br>
> ><br>
> > Normally, the DwarfBuilder will just emit bytes to Cur->Data (with possibly<br>
> > internal or external relocations to IntRelocs/ExtRelocs), but if it ever<br>
> > needs to create a "gap" for an incomplete data structure (e.g. at the end<br>
> > of a<br>
> > subprogram or a struct type), it will create a new DIEBlock New, store it<br>
> > to<br>
> > Cur->Next, store Cur in a DenseMap associated with the subprogram/type/etc<br>
> > and store New to Cur. To fill a gap later, the DwarfBuilder can pull the<br>
> > DIEBlock out of the DenseMap and start appending there. Once the IR is<br>
> > fully<br>
> > visited, the debug info writer will walk the linked list starting at First,<br>
> > calculate a byte offset for each DIEBlock, apply any internal relocations<br>
> > and write Data using the AsmPrinter (e.g. using EmitBytes, or maybe some<br>
> > other new interface that also supports relocations and avoids copying).<br>
> ><br>
> > Does that sound reasonable? Is there anything I haven't accounted for?<br>
> ><br>
> > Thanks,<br>
> > --<br>
> > Peter<br>
> ><br>
> > [1] <a href="https://code.google.com/p/chromium/issues/detail?id=583551#c15" rel="noreferrer" target="_blank">https://code.google.com/p/chromium/issues/detail?id=583551#c15</a><br>
> ><br>
<br>
</div></div><span><font color="#888888">--<br>
Peter<br>
</font></span></blockquote></div><br></div></div>