1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 03:23:01 +02:00
llvm-mirror/lib/IR/PassManager.cpp
Chandler Carruth 5bbc7e8ce9 [PM] Add the preservation system to the new pass manager.
This adds a new set-like type which represents a set of preserved
analysis passes. The set is managed via the opaque PassT::ID() void*s.
The expected convenience templates for interacting with specific passes
are provided. It also supports a symbolic "all" state which is
represented by an invalid pointer in the set. This state is nicely
saturating as it comes up often. Finally, it supports intersection which
is used when finding the set of preserved passes after N different
transforms.

The pass API is then changed to return the preserved set rather than
a bool. This is much more self-documenting than the previous system.
Returning "none" is a conservatively correct solution just like
returning "true" from todays passes and not marking any passes as
preserved. Passes can also be dynamically preserved or not throughout
the run of the pass, and whatever gets returned is the binding state.
Finally, preserving "all" the passes is allowed for no-op transforms
that simply can't harm such things.

Finally, the analysis managers are changed to instead of blindly
invalidating all of the analyses, invalidate those which were not
preserved. This should rig up all of the basic preservation
functionality. This also correctly combines the preservation moving up
from one IR-layer to the another and the preservation aggregation across
N pass runs. Still to go is incrementally correct invalidation and
preservation across IR layers incrementally during N pass runs. That
will wait until we have a device for even exposing analyses across IR
layers.

While the core of this change is obvious, I'm not happy with the current
testing, so will improve it to cover at least some of the invalidation
that I can test easily in a subsequent commit.

llvm-svn: 195241
2013-11-20 11:31:50 +00:00

120 lines
4.3 KiB
C++

//===- PassManager.h - Infrastructure for managing & running IR passes ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/PassManager.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;
PreservedAnalyses ModulePassManager::run(Module *M) {
PreservedAnalyses PA = PreservedAnalyses::all();
for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
PreservedAnalyses PassPA = Passes[Idx]->run(M);
if (AM)
AM->invalidate(M, PassPA);
PA.intersect(llvm_move(PassPA));
}
return PA;
}
void ModuleAnalysisManager::invalidate(Module *M, const PreservedAnalyses &PA) {
// FIXME: This is a total hack based on the fact that erasure doesn't
// invalidate iteration for DenseMap.
for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(),
E = ModuleAnalysisResults.end();
I != E; ++I)
if (!PA.preserved(I->first) && I->second->invalidate(M))
ModuleAnalysisResults.erase(I);
}
const detail::AnalysisResultConcept<Module> &
ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) {
ModuleAnalysisResultMapT::iterator RI;
bool Inserted;
llvm::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair(
PassID, polymorphic_ptr<detail::AnalysisResultConcept<Module> >()));
if (Inserted) {
// We don't have a cached result for this result. Look up the pass and run
// it to produce a result, which we then add to the cache.
ModuleAnalysisPassMapT::const_iterator PI =
ModuleAnalysisPasses.find(PassID);
assert(PI != ModuleAnalysisPasses.end() &&
"Analysis passes must be registered prior to being queried!");
RI->second = PI->second->run(M);
}
return *RI->second;
}
void ModuleAnalysisManager::invalidateImpl(void *PassID, Module *M) {
ModuleAnalysisResults.erase(PassID);
}
PreservedAnalyses FunctionPassManager::run(Function *F) {
PreservedAnalyses PA = PreservedAnalyses::all();
for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
PreservedAnalyses PassPA = Passes[Idx]->run(F);
if (AM)
AM->invalidate(F, PassPA);
PA.intersect(llvm_move(PassPA));
}
return PA;
}
void FunctionAnalysisManager::invalidate(Function *F, const PreservedAnalyses &PA) {
// Clear all the invalidated results associated specifically with this
// function.
SmallVector<void *, 8> InvalidatedPassIDs;
FunctionAnalysisResultListT &ResultsList = FunctionAnalysisResultLists[F];
for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(),
E = ResultsList.end();
I != E;)
if (!PA.preserved(I->first) && I->second->invalidate(F)) {
InvalidatedPassIDs.push_back(I->first);
I = ResultsList.erase(I);
} else {
++I;
}
while (!InvalidatedPassIDs.empty())
FunctionAnalysisResults.erase(
std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
}
const detail::AnalysisResultConcept<Function> &
FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) {
FunctionAnalysisResultMapT::iterator RI;
bool Inserted;
llvm::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair(
std::make_pair(PassID, F), FunctionAnalysisResultListT::iterator()));
if (Inserted) {
// We don't have a cached result for this result. Look up the pass and run
// it to produce a result, which we then add to the cache.
FunctionAnalysisPassMapT::const_iterator PI =
FunctionAnalysisPasses.find(PassID);
assert(PI != FunctionAnalysisPasses.end() &&
"Analysis passes must be registered prior to being queried!");
FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F];
ResultList.push_back(std::make_pair(PassID, PI->second->run(F)));
RI->second = llvm::prior(ResultList.end());
}
return *RI->second->second;
}
void FunctionAnalysisManager::invalidateImpl(void *PassID, Function *F) {
FunctionAnalysisResultMapT::iterator RI =
FunctionAnalysisResults.find(std::make_pair(PassID, F));
if (RI == FunctionAnalysisResults.end())
return;
FunctionAnalysisResultLists[F].erase(RI->second);
}