summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Reames <listmail@philipreames.com>2015-12-04 20:05:04 +0000
committerPhilip Reames <listmail@philipreames.com>2015-12-04 20:05:04 +0000
commite8aeaeb7125fd31ed368d2793fe28a34117bd7f7 (patch)
tree20a8c6094445aad8bdaa50efeb95f95d180ce2d9
parentb17e8b1c1d13edbcb8fa13b8cf1b164a32f025fe (diff)
downloadbcm5719-llvm-e8aeaeb7125fd31ed368d2793fe28a34117bd7f7.tar.gz
bcm5719-llvm-e8aeaeb7125fd31ed368d2793fe28a34117bd7f7.zip
[LegacyPassManager] Reduce memory usage for AnalysisUsage
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. 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). Differential Revision: http://reviews.llvm.org/D14677 llvm-svn: 254760
-rw-r--r--llvm/include/llvm/IR/LegacyPassManagers.h36
-rw-r--r--llvm/lib/IR/LegacyPassManager.cpp32
2 files changed, 59 insertions, 9 deletions
diff --git a/llvm/include/llvm/IR/LegacyPassManagers.h b/llvm/include/llvm/IR/LegacyPassManagers.h
index 3a038558150..af045585691 100644
--- a/llvm/include/llvm/IR/LegacyPassManagers.h
+++ b/llvm/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 @@ private:
/// Map from ID to immutable passes.
SmallDenseMap<AnalysisID, ImmutablePass *, 8> ImmutablePassMap;
- DenseMap<Pass *, AnalysisUsage *> 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<AUFoldingSetNode> 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<Pass *, AnalysisUsage*> 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.
diff --git a/llvm/lib/IR/LegacyPassManager.cpp b/llvm/lib/IR/LegacyPassManager.cpp
index 69f402029c8..08e8906e88d 100644
--- a/llvm/lib/IR/LegacyPassManager.cpp
+++ b/llvm/lib/IR/LegacyPassManager.cpp
@@ -569,13 +569,33 @@ void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses,
AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) {
AnalysisUsage *AnUsage = nullptr;
- DenseMap<Pass *, AnalysisUsage *>::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 @@ PMTopLevelManager::~PMTopLevelManager() {
for (SmallVectorImpl<ImmutablePass *>::iterator
I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
delete *I;
-
- for (DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.begin(),
- DME = AnUsageMap.end(); DMI != DME; ++DMI)
- delete DMI->second;
}
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud