2019-02-20 09:17:46 +08:00
|
|
|
//===- Pass.cpp - Pass infrastructure implementation ----------------------===//
|
|
|
|
//
|
|
|
|
// Copyright 2019 The MLIR Authors.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
// =============================================================================
|
|
|
|
//
|
|
|
|
// This file implements common pass infrastructure.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "mlir/Pass/Pass.h"
|
2019-03-11 06:44:47 +08:00
|
|
|
#include "PassDetail.h"
|
2019-02-20 09:17:46 +08:00
|
|
|
#include "mlir/IR/Module.h"
|
2019-02-28 02:57:59 +08:00
|
|
|
#include "mlir/Pass/PassManager.h"
|
2019-03-19 02:56:18 +08:00
|
|
|
#include "llvm/Support/Mutex.h"
|
2019-02-20 09:17:46 +08:00
|
|
|
|
|
|
|
using namespace mlir;
|
2019-02-28 09:49:51 +08:00
|
|
|
using namespace mlir::detail;
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Pass
|
|
|
|
//===----------------------------------------------------------------------===//
|
2019-02-20 09:17:46 +08:00
|
|
|
|
|
|
|
/// Out of line virtual method to ensure vtables and metadata are emitted to a
|
|
|
|
/// single .o file.
|
|
|
|
void Pass::anchor() {}
|
|
|
|
|
2019-03-08 01:22:04 +08:00
|
|
|
/// Forwarding function to execute this pass.
|
2019-03-09 08:04:42 +08:00
|
|
|
LogicalResult FunctionPassBase::run(Function *fn,
|
|
|
|
FunctionAnalysisManager &fam) {
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
// Initialize the pass state.
|
|
|
|
passState.emplace(fn, fam);
|
2019-02-28 02:57:59 +08:00
|
|
|
|
2019-03-11 05:45:47 +08:00
|
|
|
// Instrument before the pass has run.
|
|
|
|
auto pi = fam.getPassInstrumentor();
|
|
|
|
if (pi)
|
|
|
|
pi->runBeforePass(this, fn);
|
|
|
|
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
// Invoke the virtual runOnFunction function.
|
2019-03-01 06:50:42 +08:00
|
|
|
runOnFunction();
|
|
|
|
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
// Invalidate any non preserved analyses.
|
|
|
|
fam.invalidate(passState->preservedAnalyses);
|
|
|
|
|
2019-03-11 05:45:47 +08:00
|
|
|
// Instrument after the pass has run.
|
|
|
|
bool passFailed = passState->irAndPassFailed.getInt();
|
|
|
|
if (pi) {
|
|
|
|
if (passFailed)
|
|
|
|
pi->runAfterPassFailed(this, fn);
|
|
|
|
else
|
|
|
|
pi->runAfterPass(this, fn);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return if the pass signaled a failure.
|
2019-03-11 06:32:54 +08:00
|
|
|
return failure(passFailed);
|
2019-02-28 02:57:59 +08:00
|
|
|
}
|
|
|
|
|
2019-03-08 01:22:04 +08:00
|
|
|
/// Forwarding function to execute this pass.
|
2019-03-09 08:04:42 +08:00
|
|
|
LogicalResult ModulePassBase::run(Module *module, ModuleAnalysisManager &mam) {
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
// Initialize the pass state.
|
|
|
|
passState.emplace(module, mam);
|
2019-02-28 02:57:59 +08:00
|
|
|
|
2019-03-11 05:45:47 +08:00
|
|
|
// Instrument before the pass has run.
|
|
|
|
auto pi = mam.getPassInstrumentor();
|
|
|
|
if (pi)
|
|
|
|
pi->runBeforePass(this, module);
|
|
|
|
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
// Invoke the virtual runOnModule function.
|
2019-03-01 06:50:42 +08:00
|
|
|
runOnModule();
|
|
|
|
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
// Invalidate any non preserved analyses.
|
|
|
|
mam.invalidate(passState->preservedAnalyses);
|
|
|
|
|
2019-03-11 05:45:47 +08:00
|
|
|
// Instrument after the pass has run.
|
|
|
|
bool passFailed = passState->irAndPassFailed.getInt();
|
|
|
|
if (pi) {
|
|
|
|
if (passFailed)
|
|
|
|
pi->runAfterPassFailed(this, module);
|
|
|
|
else
|
|
|
|
pi->runAfterPass(this, module);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return if the pass signaled a failure.
|
2019-03-11 06:32:54 +08:00
|
|
|
return failure(passFailed);
|
2019-02-28 02:57:59 +08:00
|
|
|
}
|
|
|
|
|
2019-02-28 09:49:51 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PassExecutor
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-02-28 02:57:59 +08:00
|
|
|
/// Run all of the passes in this manager over the current function.
|
2019-03-09 08:04:42 +08:00
|
|
|
LogicalResult detail::FunctionPassExecutor::run(Function *function,
|
|
|
|
FunctionAnalysisManager &fam) {
|
2019-03-05 04:33:13 +08:00
|
|
|
// Run each of the held passes.
|
|
|
|
for (auto &pass : passes)
|
2019-03-08 01:22:04 +08:00
|
|
|
if (failed(pass->run(function, fam)))
|
2019-03-11 06:32:54 +08:00
|
|
|
return failure();
|
|
|
|
return success();
|
2019-02-28 02:57:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Run all of the passes in this manager over the current module.
|
2019-03-09 08:04:42 +08:00
|
|
|
LogicalResult detail::ModulePassExecutor::run(Module *module,
|
|
|
|
ModuleAnalysisManager &mam) {
|
2019-03-05 04:33:13 +08:00
|
|
|
// Run each of the held passes.
|
|
|
|
for (auto &pass : passes)
|
2019-03-08 01:22:04 +08:00
|
|
|
if (failed(pass->run(module, mam)))
|
2019-03-11 06:32:54 +08:00
|
|
|
return failure();
|
|
|
|
return success();
|
2019-02-28 02:57:59 +08:00
|
|
|
}
|
|
|
|
|
2019-02-28 09:49:51 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// ModuleToFunctionPassAdaptor
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-02-28 02:57:59 +08:00
|
|
|
/// Execute the held function pass over all non-external functions within the
|
|
|
|
/// module.
|
2019-03-01 06:50:42 +08:00
|
|
|
void ModuleToFunctionPassAdaptor::runOnModule() {
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
ModuleAnalysisManager &mam = getAnalysisManager();
|
2019-02-28 02:57:59 +08:00
|
|
|
for (auto &func : getModule()) {
|
|
|
|
// Skip external functions.
|
|
|
|
if (func.isExternal())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Run the held function pipeline over the current function.
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
auto fam = mam.slice(&func);
|
2019-03-08 01:22:04 +08:00
|
|
|
if (failed(fpe.run(&func, fam)))
|
2019-03-01 06:50:42 +08:00
|
|
|
return signalPassFailure();
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
|
|
|
|
// Clear out any computed function analyses. These analyses won't be used
|
|
|
|
// any more in this pipeline, and this helps reduce the current working set
|
|
|
|
// of memory. If preserving these analyses becomes important in the future
|
|
|
|
// we can re-evalutate this.
|
|
|
|
fam.clear();
|
2019-02-28 02:57:59 +08:00
|
|
|
}
|
|
|
|
}
|
2019-02-28 09:49:51 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PassManager
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-03-05 04:33:13 +08:00
|
|
|
namespace {
|
|
|
|
/// Pass to verify a function and signal failure if necessary.
|
|
|
|
class FunctionVerifier : public FunctionPass<FunctionVerifier> {
|
|
|
|
void runOnFunction() {
|
2019-03-26 09:02:49 +08:00
|
|
|
if (getFunction().verify())
|
2019-03-05 04:33:13 +08:00
|
|
|
signalPassFailure();
|
|
|
|
markAllAnalysesPreserved();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Pass to verify a module and signal failure if necessary.
|
|
|
|
class ModuleVerifier : public ModulePass<ModuleVerifier> {
|
|
|
|
void runOnModule() {
|
|
|
|
if (getModule().verify())
|
|
|
|
signalPassFailure();
|
|
|
|
markAllAnalysesPreserved();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
PassManager::PassManager(bool verifyPasses)
|
2019-03-13 04:08:48 +08:00
|
|
|
: mpe(new ModulePassExecutor()), verifyPasses(verifyPasses),
|
|
|
|
passTiming(false) {}
|
2019-02-28 09:49:51 +08:00
|
|
|
|
|
|
|
PassManager::~PassManager() {}
|
|
|
|
|
2019-03-13 04:08:48 +08:00
|
|
|
/// Run the passes within this manager on the provided module.
|
|
|
|
LogicalResult PassManager::run(Module *module) {
|
|
|
|
ModuleAnalysisManager mam(module, instrumentor.get());
|
|
|
|
return mpe->run(module, mam);
|
|
|
|
}
|
|
|
|
|
2019-02-28 09:49:51 +08:00
|
|
|
/// Add an opaque pass pointer to the current manager. This takes ownership
|
|
|
|
/// over the provided pass pointer.
|
|
|
|
void PassManager::addPass(Pass *pass) {
|
|
|
|
switch (pass->getKind()) {
|
|
|
|
case Pass::Kind::FunctionPass:
|
|
|
|
addPass(cast<FunctionPassBase>(pass));
|
|
|
|
break;
|
|
|
|
case Pass::Kind::ModulePass:
|
|
|
|
addPass(cast<ModulePassBase>(pass));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add a module pass to the current manager. This takes ownership over the
|
|
|
|
/// provided pass pointer.
|
|
|
|
void PassManager::addPass(ModulePassBase *pass) {
|
|
|
|
nestedExecutorStack.clear();
|
|
|
|
mpe->addPass(pass);
|
2019-03-05 04:33:13 +08:00
|
|
|
|
|
|
|
// Add a verifier run if requested.
|
|
|
|
if (verifyPasses)
|
|
|
|
mpe->addPass(new ModuleVerifier());
|
2019-02-28 09:49:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Add a function pass to the current manager. This takes ownership over the
|
|
|
|
/// provided pass pointer. This will automatically create a function pass
|
|
|
|
/// executor if necessary.
|
|
|
|
void PassManager::addPass(FunctionPassBase *pass) {
|
|
|
|
detail::FunctionPassExecutor *fpe;
|
|
|
|
if (nestedExecutorStack.empty()) {
|
|
|
|
/// Create an executor adaptor for this pass.
|
|
|
|
auto *adaptor = new ModuleToFunctionPassAdaptor();
|
2019-03-05 04:33:13 +08:00
|
|
|
addPass(adaptor);
|
2019-02-28 09:49:51 +08:00
|
|
|
|
|
|
|
/// Add the executor to the stack.
|
|
|
|
fpe = &adaptor->getFunctionExecutor();
|
|
|
|
nestedExecutorStack.push_back(fpe);
|
|
|
|
} else {
|
|
|
|
fpe = cast<detail::FunctionPassExecutor>(nestedExecutorStack.back());
|
|
|
|
}
|
|
|
|
fpe->addPass(pass);
|
2019-03-05 04:33:13 +08:00
|
|
|
|
|
|
|
// Add a verifier run if requested.
|
|
|
|
if (verifyPasses)
|
|
|
|
fpe->addPass(new FunctionVerifier());
|
2019-02-28 09:49:51 +08:00
|
|
|
}
|
|
|
|
|
2019-03-11 05:45:47 +08:00
|
|
|
/// Add the provided instrumentation to the pass manager. This takes ownership
|
|
|
|
/// over the given pointer.
|
|
|
|
void PassManager::addInstrumentation(PassInstrumentation *pi) {
|
|
|
|
if (!instrumentor)
|
|
|
|
instrumentor.reset(new PassInstrumentor());
|
|
|
|
|
|
|
|
instrumentor->addInstrumentation(pi);
|
|
|
|
}
|
|
|
|
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// AnalysisManager
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2019-03-11 05:45:47 +08:00
|
|
|
/// Returns a pass instrumentation object for the current function.
|
|
|
|
PassInstrumentor *FunctionAnalysisManager::getPassInstrumentor() const {
|
|
|
|
return parent->getPassInstrumentor();
|
|
|
|
}
|
|
|
|
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
/// Create an analysis slice for the given child function.
|
|
|
|
FunctionAnalysisManager ModuleAnalysisManager::slice(Function *function) {
|
|
|
|
assert(function->getModule() == moduleAnalyses.getIRUnit() &&
|
|
|
|
"function has a different parent module");
|
|
|
|
auto it = functionAnalyses.try_emplace(function, function);
|
2019-03-11 05:45:47 +08:00
|
|
|
return {this, &it.first->second};
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Invalidate any non preserved analyses.
|
|
|
|
void ModuleAnalysisManager::invalidate(const detail::PreservedAnalyses &pa) {
|
2019-03-07 03:04:22 +08:00
|
|
|
// If all analyses were preserved, then there is nothing to do here.
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
if (pa.isAll())
|
|
|
|
return;
|
|
|
|
|
2019-03-07 03:04:22 +08:00
|
|
|
// Invalidate the module analyses directly.
|
|
|
|
moduleAnalyses.invalidate(pa);
|
|
|
|
|
|
|
|
// If no analyses were preserved, then just simply clear out the function
|
|
|
|
// analysis results.
|
|
|
|
if (pa.isNone()) {
|
|
|
|
functionAnalyses.clear();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, invalidate each function analyses.
|
|
|
|
for (auto &analysisPair : functionAnalyses)
|
|
|
|
analysisPair.second.invalidate(pa);
|
Implement the initial AnalysisManagement infrastructure, with the introduction of the FunctionAnalysisManager and ModuleAnalysisManager classes. These classes provide analysis computation, caching, and invalidation for a specific IR unit. The invalidation is currently limited to either all or none, i.e. you cannot yet preserve specific analyses.
An analysis can be any class, but it must provide the following:
* A constructor for a given IR unit.
struct MyAnalysis {
// Compute this analysis with the provided module.
MyAnalysis(Module *module);
};
Analyses can be accessed from a Pass by calling either the 'getAnalysisResult<AnalysisT>' or 'getCachedAnalysisResult<AnalysisT>' methods. A FunctionPass may query for a cached analysis on the parent module with 'getCachedModuleAnalysisResult'. Similary, a ModulePass may query an analysis, it doesn't need to be cached, on a child function with 'getFunctionAnalysisResult'.
By default, when running a pass all cached analyses are set to be invalidated. If no transformation was performed, a pass can use the method 'markAllAnalysesPreserved' to preserve all analysis results. As noted above, preserving specific analyses is not yet supported.
PiperOrigin-RevId: 236505642
2019-03-03 13:46:58 +08:00
|
|
|
}
|
2019-03-11 06:44:47 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PassInstrumentation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
PassInstrumentation::~PassInstrumentation() {}
|
2019-03-19 02:56:18 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// PassInstrumentor
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace mlir {
|
|
|
|
namespace detail {
|
|
|
|
struct PassInstrumentorImpl {
|
|
|
|
/// Mutex to keep instrumentation access thread-safe.
|
|
|
|
llvm::sys::SmartMutex<true> mutex;
|
|
|
|
|
|
|
|
/// Set of registered instrumentations.
|
|
|
|
std::vector<std::unique_ptr<PassInstrumentation>> instrumentations;
|
|
|
|
};
|
|
|
|
} // end namespace detail
|
|
|
|
} // end namespace mlir
|
|
|
|
|
|
|
|
PassInstrumentor::PassInstrumentor() : impl(new PassInstrumentorImpl()) {}
|
|
|
|
PassInstrumentor::~PassInstrumentor() {}
|
|
|
|
|
|
|
|
/// See PassInstrumentation::runBeforePass for details.
|
|
|
|
void PassInstrumentor::runBeforePass(Pass *pass, const llvm::Any &ir) {
|
|
|
|
llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
|
|
|
|
for (auto &instr : impl->instrumentations)
|
|
|
|
instr->runBeforePass(pass, ir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// See PassInstrumentation::runAfterPass for details.
|
|
|
|
void PassInstrumentor::runAfterPass(Pass *pass, const llvm::Any &ir) {
|
|
|
|
llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
|
|
|
|
for (auto &instr : llvm::reverse(impl->instrumentations))
|
|
|
|
instr->runAfterPass(pass, ir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// See PassInstrumentation::runAfterPassFailed for details.
|
|
|
|
void PassInstrumentor::runAfterPassFailed(Pass *pass, const llvm::Any &ir) {
|
|
|
|
llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
|
|
|
|
for (auto &instr : llvm::reverse(impl->instrumentations))
|
|
|
|
instr->runAfterPassFailed(pass, ir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// See PassInstrumentation::runBeforeAnalysis for details.
|
|
|
|
void PassInstrumentor::runBeforeAnalysis(llvm::StringRef name, AnalysisID *id,
|
|
|
|
const llvm::Any &ir) {
|
|
|
|
llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
|
|
|
|
for (auto &instr : impl->instrumentations)
|
|
|
|
instr->runBeforeAnalysis(name, id, ir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// See PassInstrumentation::runAfterAnalysis for details.
|
|
|
|
void PassInstrumentor::runAfterAnalysis(llvm::StringRef name, AnalysisID *id,
|
|
|
|
const llvm::Any &ir) {
|
|
|
|
llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
|
|
|
|
for (auto &instr : llvm::reverse(impl->instrumentations))
|
|
|
|
instr->runAfterAnalysis(name, id, ir);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add the given instrumentation to the collection. This takes ownership over
|
|
|
|
/// the given pointer.
|
|
|
|
void PassInstrumentor::addInstrumentation(PassInstrumentation *pi) {
|
|
|
|
llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
|
|
|
|
impl->instrumentations.emplace_back(pi);
|
|
|
|
}
|
2019-03-20 03:05:11 +08:00
|
|
|
|
|
|
|
constexpr AnalysisID mlir::detail::PreservedAnalyses::allAnalysesID;
|