<div dir="ltr">The code seems to have a memory leak. Reported by asan build:<div><br></div><div><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/8348/steps/check-clang%20asan/logs/stdio">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/8348/steps/check-clang%20asan/logs/stdio</a><br></div><div><br></div><div><pre style="font-family:'Courier New',courier,monotype,monospace;color:rgb(0,0,0);font-size:medium;line-height:normal"><span class="stdout">=================================================================
==17198==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 520 byte(s) in 1 object(s) allocated from:
    #0 0x8514a8 in __interceptor_malloc /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/projects/compiler-rt/lib/asan/asan_malloc_linux.cc:40
    #1 0x3c428fd in llvm::SmallVectorBase::grow_pod(void*, unsigned long, unsigned long) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/Support/SmallVector.cpp:28:15
    #2 0x32771b2 in grow_pod /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/SmallVector.h:81:5
    #3 0x32771b2 in grow /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/SmallVector.h:334
    #4 0x32771b2 in operator= /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/SmallVector.h:771
    #5 0x32771b2 in SmallVector /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/ADT/SmallVector.h:897
    #6 0x32771b2 in AnalysisUsage /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/PassAnalysisSupport.h:37
    #7 0x32771b2 in AUFoldingSetNode /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/include/llvm/IR/LegacyPassManagers.h:259
    #8 0x32771b2 in llvm::PMTopLevelManager::findAnalysisUsage(llvm::Pass*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/IR/LegacyPassManager.cpp:592
    #9 0x3278ed8 in llvm::PMTopLevelManager::schedulePass(llvm::Pass*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/IR/LegacyPassManager.cpp:623:28
    #10 0x2ba9b0f in llvm::TargetPassConfig::addPass(llvm::Pass*, bool, bool) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/CodeGen/Passes.cpp:327:5
    #11 0x2bad50a in llvm::TargetPassConfig::addOptimizedRegAlloc(llvm::FunctionPass*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/CodeGen/Passes.cpp:759:5
    #12 0x2babdd0 in llvm::TargetPassConfig::addMachinePasses() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/CodeGen/Passes.cpp:553:5
    #13 0x298e905 in addPassesToGenerateCode(llvm::LLVMTargetMachine*, llvm::legacy::PassManagerBase&, bool, void const*, void const*, void const*, llvm::MachineFunctionInitializer*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/CodeGen/LLVMTargetMachine.cpp:138:3
    #14 0x298d12e in llvm::LLVMTargetMachine::addPassesToEmitFile(llvm::legacy::PassManagerBase&, llvm::raw_pwrite_stream&, llvm::TargetMachine::CodeGenFileType, bool, void const*, void const*, void const*, llvm::MachineFunctionInitializer*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/lib/CodeGen/LLVMTargetMachine.cpp:151:7
    #15 0x4082655 in AddEmitPasses /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp:587:7
    #16 0x4082655 in EmitAssembly /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp:627
    #17 0x4082655 in clang::EmitBackendOutput(clang::DiagnosticsEngine&, clang::CodeGenOptions const&, clang::TargetOptions const&, clang::LangOptions const&, llvm::StringRef, llvm::Module*, clang::BackendAction, llvm::raw_pwrite_stream*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/BackendUtil.cpp:666
    #18 0x5329076 in clang::BackendConsumer::HandleTranslationUnit(clang::ASTContext&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp:189:7
    #19 0x5de04f4 in clang::ParseAST(clang::Sema&, bool, bool) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseAST.cpp:168:3
    #20 0x532541c in clang::CodeGenAction::ExecuteAction() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/CodeGen/CodeGenAction.cpp:797:3
    #21 0x4a2949b in clang::FrontendAction::Execute() /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:439:8
    #22 0x498c2d4 in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:841:7
    #23 0x4bd55ee in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:222:18
    #24 0x89019a in cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/cc1_main.cpp:116:13
    #25 0x88a5b2 in ExecuteCC1Tool /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:301:12
    #26 0x88a5b2 in main /mnt/b/sanitizer-buildbot3/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:366
    #27 0x7fdd62e94ec4 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21ec4)

SUMMARY: AddressSanitizer: 520 byte(s) leaked in 1 allocation(s).
</span></pre></div><div><span class="stdout"><br></span></div></div><br><div class="gmail_quote"><div dir="ltr">On Fri, Dec 4, 2015 at 12:08 PM Philip Reames via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: reames<br>
Date: Fri Dec  4 14:05:04 2015<br>
New Revision: 254760<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=254760&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=254760&view=rev</a><br>
Log:<br>
[LegacyPassManager] Reduce memory usage for AnalysisUsage<br>
<br>
The LegacyPassManager was storing an instance of AnalysisUsage for each instance of each pass. In practice, most instances of a single pass class share the same dependencies. We can't rely on this because passes can (and some do) have dynamic dependencies based on instance options.<br>
<br>
We can exploit the likely commonality by uniqueing the usage information after querying the pass, but before storing it into the pass manager. This greatly reduces memory consumption by the AnalysisUsage objects. For a long pass pipeline, I measured a decrease in memory consumption for this storage of about 50%. I have not measured on the default O3 pipeline, but I suspect it will see some benefit as well since many passes are repeated (e.g. InstCombine).<br>
<br>
Differential Revision: <a href="http://reviews.llvm.org/D14677" rel="noreferrer" target="_blank">http://reviews.llvm.org/D14677</a><br>
<br>
<br>
Modified:<br>
    llvm/trunk/include/llvm/IR/LegacyPassManagers.h<br>
    llvm/trunk/lib/IR/LegacyPassManager.cpp<br>
<br>
Modified: llvm/trunk/include/llvm/IR/LegacyPassManagers.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/LegacyPassManagers.h?rev=254760&r1=254759&r2=254760&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/LegacyPassManagers.h?rev=254760&r1=254759&r2=254760&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/LegacyPassManagers.h (original)<br>
+++ llvm/trunk/include/llvm/IR/LegacyPassManagers.h Fri Dec  4 14:05:04 2015<br>
@@ -16,6 +16,7 @@<br>
<br>
 #include "llvm/ADT/ArrayRef.h"<br>
 #include "llvm/ADT/DenseMap.h"<br>
+#include "llvm/ADT/FoldingSet.h"<br>
 #include "llvm/ADT/SmallPtrSet.h"<br>
 #include "llvm/ADT/SmallVector.h"<br>
 #include "llvm/Pass.h"<br>
@@ -250,7 +251,40 @@ private:<br>
   /// Map from ID to immutable passes.<br>
   SmallDenseMap<AnalysisID, ImmutablePass *, 8> ImmutablePassMap;<br>
<br>
-  DenseMap<Pass *, AnalysisUsage *> AnUsageMap;<br>
+<br>
+  /// A wrapper around AnalysisUsage for the purpose of uniqueing.  The wrapper<br>
+  /// is used to avoid needing to make AnalysisUsage itself a folding set node.<br>
+  struct AUFoldingSetNode : public FoldingSetNode {<br>
+    AnalysisUsage AU;<br>
+    AUFoldingSetNode(const AnalysisUsage &AU) : AU(AU) {}<br>
+    void Profile(FoldingSetNodeID &ID) const {<br>
+      Profile(ID, AU);<br>
+    }<br>
+    static void Profile(FoldingSetNodeID &ID, const AnalysisUsage &AU) {<br>
+      // TODO: We could consider sorting the dependency arrays within the<br>
+      // AnalysisUsage (since they are conceptually unordered).<br>
+      ID.AddBoolean(AU.getPreservesAll());<br>
+      for (auto &Vec : {AU.getRequiredSet(), AU.getRequiredTransitiveSet(),<br>
+            AU.getPreservedSet(), AU.getUsedSet()}) {<br>
+        ID.AddInteger(Vec.size());<br>
+        for(AnalysisID AID : Vec)<br>
+          ID.AddPointer(AID);<br>
+      }<br>
+    }<br>
+  };<br>
+<br>
+  // Contains all of the unique combinations of AnalysisUsage.  This is helpful<br>
+  // when we have multiple instances of the same pass since they'll usually<br>
+  // have the same analysis usage and can share storage.<br>
+  FoldingSet<AUFoldingSetNode> UniqueAnalysisUsages;<br>
+<br>
+  // Allocator used for allocating UAFoldingSetNodes.  This handles deletion of<br>
+  // all allocated nodes in one fell swoop.<br>
+  BumpPtrAllocator AUFoldingSetNodeAllocator;<br>
+<br>
+  // Maps from a pass to it's associated entry in UniqueAnalysisUsages.  Does<br>
+  // not own the storage associated with either key or value..<br>
+  DenseMap<Pass *, AnalysisUsage*> AnUsageMap;<br>
<br>
   /// Collection of PassInfo objects found via analysis IDs and in this top<br>
   /// level manager. This is used to memoize queries to the pass registry.<br>
<br>
Modified: llvm/trunk/lib/IR/LegacyPassManager.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LegacyPassManager.cpp?rev=254760&r1=254759&r2=254760&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LegacyPassManager.cpp?rev=254760&r1=254759&r2=254760&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/LegacyPassManager.cpp (original)<br>
+++ llvm/trunk/lib/IR/LegacyPassManager.cpp Fri Dec  4 14:05:04 2015<br>
@@ -569,13 +569,33 @@ void PMTopLevelManager::collectLastUses(<br>
<br>
 AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) {<br>
   AnalysisUsage *AnUsage = nullptr;<br>
-  DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.find(P);<br>
+  auto DMI = AnUsageMap.find(P);<br>
   if (DMI != AnUsageMap.end())<br>
     AnUsage = DMI->second;<br>
   else {<br>
-    AnUsage = new AnalysisUsage();<br>
-    P->getAnalysisUsage(*AnUsage);<br>
-    AnUsageMap[P] = AnUsage;<br>
+    // Look up the analysis usage from the pass instance (different instances<br>
+    // of the same pass can produce different results), but unique the<br>
+    // resulting object to reduce memory usage.  This helps to greatly reduce<br>
+    // memory usage when we have many instances of only a few pass types<br>
+    // (e.g. instcombine, simplifycfg, etc...) which tend to share a fixed set<br>
+    // of dependencies.<br>
+    AnalysisUsage AU;<br>
+    P->getAnalysisUsage(AU);<br>
+<br>
+    AUFoldingSetNode* Node = nullptr;<br>
+    FoldingSetNodeID ID;<br>
+    AUFoldingSetNode::Profile(ID, AU);<br>
+    void *IP = nullptr;<br>
+    if (auto *N = UniqueAnalysisUsages.FindNodeOrInsertPos(ID, IP))<br>
+      Node = N;<br>
+    else {<br>
+      Node = new (AUFoldingSetNodeAllocator) AUFoldingSetNode(AU);<br>
+      UniqueAnalysisUsages.InsertNode(Node, IP);<br>
+    }<br>
+    assert(Node && "cached analysis usage must be non null");<br>
+<br>
+    AnUsageMap[P] = &Node->AU;<br>
+    AnUsage = &Node->AU;;<br>
   }<br>
   return AnUsage;<br>
 }<br>
@@ -798,10 +818,6 @@ PMTopLevelManager::~PMTopLevelManager()<br>
   for (SmallVectorImpl<ImmutablePass *>::iterator<br>
          I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)<br>
     delete *I;<br>
-<br>
-  for (DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.begin(),<br>
-         DME = AnUsageMap.end(); DMI != DME; ++DMI)<br>
-    delete DMI->second;<br>
 }<br>
<br>
 //===----------------------------------------------------------------------===//<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>