<div dir="ltr">Will look more closely soon - but I'd really try just writing out type units to MC as soon as they're done. It should be relatively non-intrusive (we build type units once, there's no ambiguity about when they're done) - for non-fission+type units it might be a bit tricky, because the type units still need a relocation for the stmt_list* (I'm trying to find where that's added now... I seem to have lost it), but fission+type units should produce entirely static type units that are knowable the moment the type is being emitted so far as I can tell (including the type hash and everything - you can write the bytes out to the AsmStreamer, etc and forget about them entirely except to keep the hash to know that you don't need to emit it again.<br><br>I imagine this would provide all the memory savings we would need for much of anything (since types are most of the debug info), and, if not, would be a good start.<br><br>*I think we might know what the stmt_list relocation is up-front, though - if that's the case we'd be able to be as aggressive as I described is the case for fission</div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Feb 5, 2016 at 3:17 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">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 DIEValue.<br>
<br>
I understand that the DWARF emitter needs to accommodate incomplete entities<br>
that may be completed elsewhere during tree construction (e.g. abstract origins<br>
for inlined functions, special members for types), so here's a quick 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 types<br>
struct InternalReloc {<br>
  size_t Offset; // offset within DIEBlock::Data<br>
  DIEBlock *Target; // the offset within Target is at Data[Offset...Offset+Size]<br>
};<br>
<br>
// This would be used to represent things like pointers to .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 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 of a<br>
subprogram or a struct type), it will create a new DIEBlock New, store it 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 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>
<span class="HOEnZb"><font color="#888888">--<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>
</font></span></blockquote></div><br></div>