[llvm-bugs] [Bug 52551] New: [LTO] Excessive memory usage with IPGO due to Metadata merging

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Nov 18 17:03:13 PST 2021


https://bugs.llvm.org/show_bug.cgi?id=52551

            Bug ID: 52551
           Summary: [LTO] Excessive memory usage with IPGO due to Metadata
                    merging
           Product: libraries
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: Linker
          Assignee: unassignedbugs at nondot.org
          Reporter: Wolfgang_Pieb at playstation.sony.com
                CC: llvm-bugs at lists.llvm.org

When regular LTO is used with IPGO, we're seeing excessive memory usage (4x) at
link (LTO) time compared to just using regular LTO without IPGO. We've traced
it to Metadata merging at the time when all modules are linked into a combined
module.

Specifically, it's module flags that are being merged in the following code
segments in IRLinker::linkModuleFlagsMetadata() in llvm/lib/Linker/IRMover.cpp:

   switch (SrcBehaviorValue) {
    ...
    case Module::Append: {
      MDNode *DstValue = cast<MDNode>(DstOp->getOperand(2));
      MDNode *SrcValue = cast<MDNode>(SrcOp->getOperand(2));
      SmallVector<Metadata *, 8> MDs;
      MDs.reserve(DstValue->getNumOperands() + SrcValue->getNumOperands());
      MDs.append(DstValue->op_begin(), DstValue->op_end());
      MDs.append(SrcValue->op_begin(), SrcValue->op_end());

      replaceDstValue(MDNode::get(DstM.getContext(), MDs));
      break;
     }
     ...

with replaceDstValue() a lambda that replaces an existing MD list node with the
newly created one.

The ModuleFlags in question are the "CG Profile" flags, which seems to be a
list of MD nodes representing all function declarations that have profile
information in the module. The end result is one long list of functions for the
entire combined module, but the list is created one module at a time, so that
each time we link a new module, a new list node is created by copying the
entries of the old one and adding the new ones to it. The old list node is not
deleted.
In one of our licensee's applications, after some time each new list node takes
several MB, and this adds up. Towards the end each new node takes 18MB.

I did some basic instrumentation (i.e. printing out the amount of allocated
memory during module flag linking) and used it with a simple example with just
3 modules, and I got

  Append module flag - before
  Allocating 88
  Allocating 48
  Append module flag - after
  Append module flag - before
  Allocating 112
  Allocating 48
  Append module flag - after
  Append module flag - before
  Allocating 184
  Allocating 48
  Append module flag - after

One can see the growing allocation from 88 to 184 with just 3 modules.

The question arises whether temporary MD nodes are could be used instead so
they can be deleted when a new list node replaces an old one.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20211119/022cc714/attachment.html>


More information about the llvm-bugs mailing list