Index: llvm/trunk/include/llvm/IR/LegacyPassManagers.h =================================================================== --- llvm/trunk/include/llvm/IR/LegacyPassManagers.h +++ llvm/trunk/include/llvm/IR/LegacyPassManagers.h @@ -16,6 +16,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Pass.h" @@ -250,7 +251,40 @@ /// Map from ID to immutable passes. SmallDenseMap ImmutablePassMap; - DenseMap AnUsageMap; + + /// A wrapper around AnalysisUsage for the purpose of uniqueing. The wrapper + /// is used to avoid needing to make AnalysisUsage itself a folding set node. + struct AUFoldingSetNode : public FoldingSetNode { + AnalysisUsage AU; + AUFoldingSetNode(const AnalysisUsage &AU) : AU(AU) {} + void Profile(FoldingSetNodeID &ID) const { + Profile(ID, AU); + } + static void Profile(FoldingSetNodeID &ID, const AnalysisUsage &AU) { + // TODO: We could consider sorting the dependency arrays within the + // AnalysisUsage (since they are conceptually unordered). + ID.AddBoolean(AU.getPreservesAll()); + for (auto &Vec : {AU.getRequiredSet(), AU.getRequiredTransitiveSet(), + AU.getPreservedSet(), AU.getUsedSet()}) { + ID.AddInteger(Vec.size()); + for(AnalysisID AID : Vec) + ID.AddPointer(AID); + } + } + }; + + // Contains all of the unique combinations of AnalysisUsage. This is helpful + // when we have multiple instances of the same pass since they'll usually + // have the same analysis usage and can share storage. + FoldingSet UniqueAnalysisUsages; + + // Allocator used for allocating UAFoldingSetNodes. This handles deletion of + // all allocated nodes in one fell swoop. + BumpPtrAllocator AUFoldingSetNodeAllocator; + + // Maps from a pass to it's associated entry in UniqueAnalysisUsages. Does + // not own the storage associated with either key or value.. + DenseMap AnUsageMap; /// Collection of PassInfo objects found via analysis IDs and in this top /// level manager. This is used to memoize queries to the pass registry. Index: llvm/trunk/lib/IR/LegacyPassManager.cpp =================================================================== --- llvm/trunk/lib/IR/LegacyPassManager.cpp +++ llvm/trunk/lib/IR/LegacyPassManager.cpp @@ -569,13 +569,33 @@ AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) { AnalysisUsage *AnUsage = nullptr; - DenseMap::iterator DMI = AnUsageMap.find(P); + auto DMI = AnUsageMap.find(P); if (DMI != AnUsageMap.end()) AnUsage = DMI->second; else { - AnUsage = new AnalysisUsage(); - P->getAnalysisUsage(*AnUsage); - AnUsageMap[P] = AnUsage; + // Look up the analysis usage from the pass instance (different instances + // of the same pass can produce different results), but unique the + // resulting object to reduce memory usage. This helps to greatly reduce + // memory usage when we have many instances of only a few pass types + // (e.g. instcombine, simplifycfg, etc...) which tend to share a fixed set + // of dependencies. + AnalysisUsage AU; + P->getAnalysisUsage(AU); + + AUFoldingSetNode* Node = nullptr; + FoldingSetNodeID ID; + AUFoldingSetNode::Profile(ID, AU); + void *IP = nullptr; + if (auto *N = UniqueAnalysisUsages.FindNodeOrInsertPos(ID, IP)) + Node = N; + else { + Node = new (AUFoldingSetNodeAllocator) AUFoldingSetNode(AU); + UniqueAnalysisUsages.InsertNode(Node, IP); + } + assert(Node && "cached analysis usage must be non null"); + + AnUsageMap[P] = &Node->AU; + AnUsage = &Node->AU;; } return AnUsage; } @@ -798,10 +818,6 @@ for (SmallVectorImpl::iterator I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I) delete *I; - - for (DenseMap::iterator DMI = AnUsageMap.begin(), - DME = AnUsageMap.end(); DMI != DME; ++DMI) - delete DMI->second; } //===----------------------------------------------------------------------===//