21#include "llvm/ADT/Hashing.h"
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/ScopeExit.h"
24#include "llvm/Support/DebugLog.h"
25#include "llvm/Support/Mutex.h"
26#include "llvm/Support/Signals.h"
27#include "llvm/Support/Threading.h"
31#define DEBUG_TYPE "pass-manager"
45 os << llvm::formatv(
"`{0}` running `{1}` on Operation `{2}`",
tag,
52 : llvm::dyn_cast_if_present<Operation *>(
irUnits[0]);
68 function_ref<LogicalResult(
const Twine &)> errorHandler) {
70 llvm::raw_string_ostream os(errStr);
71 if (failed(passOptions.parseFromString(
options, os))) {
72 return errorHandler(errStr);
80 passOptions.copyOptionValuesFrom(other->passOptions);
88 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(
this)) {
90 adaptor->getPassManagers(),
91 [&](
OpPassManager &pm) { pm.printAsTextualPipeline(os, pretty); },
103 if (!argument.empty())
106 os <<
"unknown<" <<
getName() <<
">";
107 passOptions.print(os);
129 for (
const std::unique_ptr<Pass> &pass : rhs.passes) {
130 std::unique_ptr<Pass> newPass = pass->clone();
131 newPass->threadingSibling = pass.get();
132 passes.push_back(std::move(newPass));
154 void addPass(std::unique_ptr<Pass> pass);
172 return name.empty() ? std::optional<StringRef>()
173 : std::optional<StringRef>(
name);
195 std::vector<std::unique_ptr<Pass>>
passes;
209 assert(
name == rhs.name &&
"merging unrelated pass managers");
211 rhs.passes.push_back(std::move(pass));
217 addPass(std::unique_ptr<Pass>(adaptor));
218 return adaptor->getPassManagers().front();
224 std::optional<StringRef> pmOpName =
getOpName();
225 std::optional<StringRef> passOpName = pass->getOpName();
226 if (pmOpName && passOpName && *pmOpName != *passOpName) {
228 return nest(*passOpName).addPass(std::move(pass));
229 llvm::report_fatal_error(llvm::Twine(
"Can't add pass '") + pass->getName() +
230 "' restricted to '" + *passOpName +
231 "' on a PassManager intended to run on '" +
235 passes.emplace_back(std::move(pass));
242 for (
auto &pm : adaptor->getPassManagers())
243 if (failed(pm.getImpl().finalizePassList(ctx)))
249 LDBG(3) <<
"Merging adjacent adaptors in pass list";
251 for (
auto &pass :
passes) {
253 if (
auto *currentAdaptor = dyn_cast<OpToOpPassAdaptor>(pass.get())) {
257 LDBG(3) <<
"Found first adaptor in chain";
258 lastAdaptor = currentAdaptor;
264 LDBG(3) <<
"Attempting to merge adaptor with "
265 << currentAdaptor->getPassManagers().size()
266 <<
" managers into previous adaptor";
267 if (succeeded(currentAdaptor->tryMergeInto(ctx, *lastAdaptor))) {
268 LDBG(3) <<
"Successfully merged adaptors, removing current one";
271 LDBG(3) <<
"Failed to merge adaptors, keeping current as last";
272 lastAdaptor = currentAdaptor;
274 }
else if (lastAdaptor) {
276 LDBG(3) <<
"Finalizing adaptor chain before non-adaptor pass";
277 if (failed(finalizeAdaptor(lastAdaptor)))
279 lastAdaptor =
nullptr;
284 if (lastAdaptor && failed(finalizeAdaptor(lastAdaptor)))
289 size_t beforeErase =
passes.size();
290 llvm::erase_if(
passes, std::logical_not<std::unique_ptr<Pass>>());
291 if (beforeErase !=
passes.size()) {
292 LDBG(3) <<
"Removed " << (beforeErase -
passes.size())
293 <<
" merged adaptor slots from pass list";
297 std::optional<OperationName> rawOpName =
getOpName(*ctx);
300 <<
"Op-agnostic pass manager, skipping operation-specific verification";
306 LDBG(3) <<
"Verifying " <<
passes.size() <<
" passes for operation '"
309 std::optional<RegisteredOperationName>
opName =
310 rawOpName->getRegisteredInfo();
311 for (std::unique_ptr<Pass> &pass :
passes) {
314 <<
"unable to schedule pass '" << pass->getName()
320 LDBG(3) <<
"Pass list finalization completed successfully";
328 std::optional<OperationName> pmOpName =
getOpName(context);
330 return pmOpName ==
opName;
334 std::optional<RegisteredOperationName> registeredInfo =
335 opName.getRegisteredInfo();
336 if (!registeredInfo ||
339 return llvm::all_of(
passes, [&](
const std::unique_ptr<Pass> &pass) {
340 return pass->canScheduleOn(*registeredInfo);
357 impl = std::make_unique<OpPassManagerImpl>(*rhs.impl);
361 impl = std::move(rhs.impl);
384 return impl->nest(nestedName);
387 return impl->nest(nestedName);
394 impl->addPass(std::move(pass));
407 return impl->getOpName();
411std::optional<OperationName>
413 return impl->getOpName(context);
417 return impl->getOpAnchorName();
426 bool pretty =
false) {
427 os << anchorName <<
"(";
457 indentedOS, anchorName,
464 llvm::errs() <<
"Pass Manager with " <<
impl->passes.size() <<
" passes:\n";
466 llvm::errs() <<
"\n";
472 pass.getDependentDialects(dialects);
483LogicalResult OpPassManager::initialize(
MLIRContext *context,
484 unsigned newInitGeneration) {
486 if (
impl->initializationGeneration == newInitGeneration) {
487 LDBG(2) <<
"Pass manager already initialized "
488 <<
"' (generation " << newInitGeneration <<
") with " <<
size()
494 <<
"' (generation " << newInitGeneration <<
") with " <<
size()
496 impl->initializationGeneration = newInitGeneration;
500 auto *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
502 LDBG(2) <<
"Initializing pass '" << pass.getName() <<
"'";
503 if (failed(pass.initialize(context))) {
504 LDBG(2) <<
"Failed to initialize pass '" << pass.getName() <<
"'";
511 LDBG(3) <<
"Initializing adaptor pass with "
512 << adaptor->getPassManagers().size() <<
" nested managers";
514 if (
failed(adaptorPM.initialize(context, newInitGeneration))) {
515 LDBG(2) <<
"Failed to initialize nested pass manager";
520 LDBG_OS([&](raw_ostream &os) {
521 os <<
"Pass manager initialization completed successfully: ";
527llvm::hash_code OpPassManager::hash() {
528 llvm::hash_code hashCode{};
531 auto *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
533 hashCode = llvm::hash_combine(hashCode, &pass);
538 llvm::hash_combine(hashCode, adaptorPM.hash());
547LogicalResult OpToOpPassAdaptor::run(
Pass *pass,
Operation *op,
549 unsigned parentInitGeneration) {
550 LDBG() <<
"Running pass '" << pass->
getName() <<
"' on operation '"
557 <<
"trying to schedule a pass on an unregistered operation";
560 return op->
emitOpError() <<
"trying to schedule a pass on an operation not "
561 "marked as 'IsolatedFromAbove'";
565 <<
"' on an unsupported operation";
576 return root->emitOpError()
577 <<
"Trying to schedule a dynamic pipeline on an "
578 "operation that isn't "
579 "nested under the current operation the pass is processing";
585 LDBG() <<
"Failed to finalize pass list for pipeline";
590 if (
failed(pipeline.initialize(root->getContext(), parentInitGeneration)))
593 return OpToOpPassAdaptor::runPipeline(pipeline, root, nestedAm,
594 verifyPasses, parentInitGeneration,
597 pass->passState.emplace(op, am, dynamicPipelineCallback);
605 bool passFailed = pass->passState->irAndPassFailed.getInt();
610 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass))
611 adaptor->runOnOperation(verifyPasses);
614 passFailed = pass->passState->irAndPassFailed.getInt();
620 am.
invalidate(pass->passState->preservedAnalyses);
624 if (!passFailed && verifyPasses) {
625 bool runVerifierNow =
true;
630 bool runVerifierRecursively = !isa<OpToOpPassAdaptor>(pass);
639#ifndef EXPENSIVE_CHECKS
640 runVerifierNow = !pass->passState->preservedAnalyses.isAll();
643 passFailed =
failed(
verify(op, runVerifierRecursively));
652 passFailed = passFailed || pass->passState->irAndPassFailed.getInt();
657 return failure(passFailed);
661LogicalResult OpToOpPassAdaptor::runPipeline(
666 os <<
"Running pipeline on operation '"
668 << pm.
size() <<
" passes, verifyPasses=" << verifyPasses
672 assert((!instrumentor || parentInfo) &&
673 "expected parent info if instrumentor is provided");
674 llvm::scope_exit scopeExit([&] {
689 if (
failed(run(&pass, op, am, verifyPasses, parentInitGeneration))) {
690 LDBG() <<
"Pipeline failed for pass '" << pass.
getName()
691 <<
"' on operation '"
708 LDBG(3) <<
"Looking for pass manager with anchor name '" << name <<
"' among "
709 << mgrs.size() <<
" managers";
711 auto *it = llvm::find_if(
714 if (it == mgrs.end()) {
715 LDBG(2) <<
"No pass manager found with anchor name '" << name <<
"'";
719 LDBG(2) <<
"Found pass manager with anchor name '" << name <<
"'";
728 LDBG(4) <<
"Looking for pass manager that can handle operation '" << name
729 <<
"' among " << mgrs.size() <<
" managers";
735 if (it == mgrs.end()) {
736 LDBG(4) <<
"No pass manager found that can handle operation '" << name
741 LDBG(4) <<
"Found pass manager '" << it->getOpAnchorName()
742 <<
"' that can handle operation '" << name <<
"'";
747 mgrs.emplace_back(std::move(mgr));
751 for (
auto &pm : mgrs)
757 LDBG(3) <<
"Attempting to merge pass adaptor with " << mgrs.size()
758 <<
" managers into rhs with " << rhs.mgrs.size() <<
" managers";
771 if (std::optional<OperationName> pmOpName = pm.
getOpName(*ctx))
784 auto *lhsGenericPMIt = llvm::find_if(mgrs, isGenericPM);
785 if (lhsGenericPMIt != mgrs.end()) {
786 LDBG(4) <<
"Found generic pass manager on LHS, checking for conflicts";
787 if (hasScheduleConflictWith(*lhsGenericPMIt, rhs.mgrs)) {
789 <<
"Merge failed: LHS generic pass manager has conflicts with RHS";
794 auto *rhsGenericPMIt = llvm::find_if(rhs.mgrs, isGenericPM);
795 if (rhsGenericPMIt != rhs.mgrs.end()) {
796 LDBG(4) <<
"Found generic pass manager on RHS, checking for conflicts";
797 if (hasScheduleConflictWith(*rhsGenericPMIt, mgrs)) {
799 <<
"Merge failed: RHS generic pass manager has conflicts with LHS";
804 for (
auto &pm : mgrs) {
807 if (
auto *existingPM =
812 rhs.mgrs.emplace_back(std::move(pm));
820 if (std::optional<StringRef> lhsName = lhs.getOpName()) {
821 if (std::optional<StringRef> rhsName = rhs.getOpName())
822 return *lhsName < *rhsName;
827 llvm::sort(rhs.mgrs, compareFn);
833 std::string name =
"Pipeline Collection : [";
834 llvm::raw_string_ostream os(name);
844 "Unexpected call to Pass::runOnOperation() on OpToOpPassAdaptor");
850 runOnOperationAsyncImpl(verifyPasses);
852 runOnOperationImpl(verifyPasses);
856void OpToOpPassAdaptor::runOnOperationImpl(
bool verifyPasses) {
858 os <<
"Running pass adaptor synchronously on operation '"
860 <<
"' with " << mgrs.size()
861 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
865 auto am = getAnalysisManager();
868 auto *instrumentor = am.getPassInstrumentor();
870 unsigned processedOps = 0;
871 for (
auto ®ion : getOperation()->getRegions()) {
872 for (
auto &block : region) {
873 for (
auto &op : block) {
876 LDBG(2) <<
"Skipping operation '"
878 <<
"': no suitable pass manager found";
883 LDBG(2) <<
"Processing operation '"
885 <<
"' with pass manager '" << mgr->getOpAnchorName() <<
"'";
887 unsigned initGeneration = mgr->impl->initializationGeneration;
888 if (
failed(runPipeline(*mgr, &op, am.nest(&op), verifyPasses,
889 initGeneration, instrumentor, &parentInfo))) {
890 LDBG(2) <<
"Pipeline failed for operation '"
900 LDBG() <<
"Completed synchronous pass adaptor run, processed " << processedOps
908 return lhs.size() != rhs.size() ||
909 llvm::any_of(llvm::seq<size_t>(0, lhs.size()),
910 [&](
size_t i) { return lhs[i].size() != rhs[i].size(); });
914void OpToOpPassAdaptor::runOnOperationAsyncImpl(
bool verifyPasses) {
916 os <<
"Running pass adaptor asynchronously on operation '"
918 <<
"' with " << mgrs.size()
919 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
928 if (asyncExecutors.empty() ||
hasSizeMismatch(asyncExecutors.front(), mgrs)) {
929 LDBG(2) <<
"Creating " << context->
getThreadPool().getMaxConcurrency()
930 <<
" async executors";
931 asyncExecutors.assign(context->
getThreadPool().getMaxConcurrency(), mgrs);
937 OpPMInfo(
unsigned passManagerIdx, Operation *op, AnalysisManager am)
938 : passManagerIdx(passManagerIdx), op(op), am(am) {}
941 unsigned passManagerIdx;
951 std::vector<OpPMInfo> opInfos;
954 LDBG(2) <<
"Collecting operations for async execution";
955 for (
auto ®ion : getOperation()->getRegions()) {
958 auto pmIdxIt = knownOpPMIdx.try_emplace(op.
getName(), std::nullopt);
959 if (pmIdxIt.second) {
961 pmIdxIt.first->second = std::distance(mgrs.begin(), mgr);
962 LDBG(2) <<
"Operation '"
964 <<
"' will use pass manager '" << mgr->getOpAnchorName()
970 if (pmIdxIt.first->second) {
971 opInfos.emplace_back(*pmIdxIt.first->second, &op, am.nest(&op));
973 LDBG(2) <<
"Operation '"
975 <<
"' skipped: no suitable pass manager";
980 LDBG(2) <<
"Collected " << opInfos.size()
981 <<
" operations for async execution";
986 auto *instrumentor = am.getPassInstrumentor();
991 std::atomic<bool> hasFailure =
false;
993 context, opInfos.begin(), opInfos.end(),
994 [&](OpPMInfo &opInfo,
unsigned pmIndex) {
995 OpPassManager &pm = asyncExecutors[pmIndex][opInfo.passManagerIdx];
996 LogicalResult pipelineResult = runPipeline(
997 pm, opInfo.op, opInfo.am, verifyPasses,
998 pm.impl->initializationGeneration, instrumentor, &parentInfo);
999 if (failed(pipelineResult))
1000 hasFailure.store(true);
1007 signalPassFailure();
1017 verifyPasses(
true) {}
1022 verifyPasses(
true) {}
1031 os <<
"Starting PassManager run on operation '"
1033 <<
size() <<
" passes, verifyPasses=" << verifyPasses <<
" pipeline: ";
1038 std::optional<OperationName> anchorOp =
getOpName(*context);
1039 if (anchorOp && anchorOp != op->
getName()) {
1046 LDBG(2) <<
"Registering dependent dialects for pipeline";
1049 context->appendDialectRegistry(dependentDialects);
1051 LDBG(2) <<
"Loading dialect: " << name;
1052 Dialect *loaded = context->getOrLoadDialect(name);
1053 assert(loaded &&
"allocator-backed registration must resolve");
1057 context, [&]() { return emitError(op->getLoc()); })))
1061 if (failed(
getImpl().finalizePassList(context))) {
1062 LDBG(2) <<
"Pass list finalization failed";
1067 context->enterMultiThreadedExecution();
1070 llvm::hash_code newInitKey = context->getRegistryHash();
1071 llvm::hash_code pipelineKey = hash();
1072 if (newInitKey != initializationKey ||
1073 pipelineKey != pipelineInitializationKey) {
1074 LDBG(2) <<
"Initializing passes with new generation: "
1075 << (
impl->initializationGeneration + 1);
1076 if (failed(initialize(context,
impl->initializationGeneration + 1))) {
1077 LDBG(2) <<
"Pass initialization failed";
1080 initializationKey = newInitKey;
1081 pipelineInitializationKey = pipelineKey;
1083 LDBG(2) <<
"Using existing pass initialization (generation: "
1084 <<
impl->initializationGeneration <<
")";
1088 LDBG(2) <<
"Constructing analysis manager for pipeline execution";
1093 LDBG(2) <<
"Executing pipeline with "
1094 << (crashReproGenerator ?
"crash recovery" :
"normal execution");
1096 crashReproGenerator ? runWithCrashRecovery(op, am) : runPasses(op, am);
1099 context->exitMultiThreadedExecution();
1102 if (passStatisticsMode) {
1103 LDBG(2) <<
"Dumping pass statistics";
1107 LDBG(2) <<
"PassManager run completed with result: "
1108 << (succeeded(
result) ?
"success" :
"failure");
1115 instrumentor = std::make_unique<PassInstrumentor>();
1117 instrumentor->addInstrumentation(std::move(pi));
1121 LDBG(2) <<
"Executing passes using OpToOpPassAdaptor pipeline";
1122 return OpToOpPassAdaptor::runPipeline(*
this, op, am, verifyPasses,
1123 impl->initializationGeneration);
1135 "expected valid descendant operation");
1139 return nestImmediate(op);
1144 opAncestors.push_back(op);
1146 }
while (op != currentOp);
1148 AnalysisManager
result = *
this;
1149 for (
Operation *op : llvm::reverse(opAncestors))
1157 "expected immediate child operation");
1159 auto [it,
inserted] =
impl->childAnalyses.try_emplace(op);
1161 it->second = std::make_unique<NestedAnalysisMap>(op,
impl);
1162 return {it->second.get()};
1184 while (!mapsToInvalidate.empty()) {
1185 auto *map = mapsToInvalidate.pop_back_val();
1186 for (
auto &analysisPair : map->childAnalyses) {
1187 analysisPair.second->invalidate(pa);
1188 if (!analysisPair.second->childAnalyses.empty())
1189 mapsToInvalidate.push_back(analysisPair.second.get());
1225 std::unique_lock<llvm::sys::SmartMutex<true>> lock(
mutex, std::defer_lock);
1242 std::optional<OperationName> name,
1244 auto instrumentationLock =
impl->lockInstrumentations();
1245 for (
auto &instr :
impl->instrumentations)
1246 instr->runBeforePipeline(name, parentInfo);
1251 std::optional<OperationName> name,
1253 auto instrumentationLock =
impl->lockInstrumentations();
1254 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1255 instr->runAfterPipeline(name, parentInfo);
1260 auto instrumentationLock =
impl->lockInstrumentations();
1261 for (
auto &instr :
impl->instrumentations)
1262 instr->runBeforePass(pass, op);
1267 auto instrumentationLock =
impl->lockInstrumentations();
1268 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1269 instr->runAfterPass(pass, op);
1274 auto instrumentationLock =
impl->lockInstrumentations();
1275 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1276 instr->runAfterPassFailed(pass, op);
1282 auto instrumentationLock =
impl->lockInstrumentations();
1283 for (
auto &instr :
impl->instrumentations)
1284 instr->runBeforeAnalysis(name,
id, op);
1290 auto instrumentationLock =
impl->lockInstrumentations();
1291 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1292 instr->runAfterAnalysis(name,
id, op);
1297 std::unique_ptr<PassInstrumentation> pi) {
1298 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1299 impl->threadSafe &= pi->isThreadSafe();
1300 impl->instrumentations.emplace_back(std::move(pi));
true
Given two iterators into the same block, return "true" if a is before `b.
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
false
Parses a map_entries map type from a string format back into its numeric value.
static llvm::ManagedStatic< PassManagerOptions > options
void printAsTextualPipeline(raw_indented_ostream &os, StringRef anchorName, const llvm::iterator_range< OpPassManager::pass_iterator > &passes, bool pretty=false)
Prints out the passes of the pass manager as the textual representation of pipelines.
static void registerDialectsForPipeline(const OpPassManager &pm, DialectRegistry &dialects)
static bool hasSizeMismatch(ArrayRef< OpPassManager > lhs, ArrayRef< OpPassManager > rhs)
Utility functor that checks if the two ranges of pass managers have a size mismatch.
static OpPassManager * findPassManagerFor(MutableArrayRef< OpPassManager > mgrs, OperationName name, MLIRContext &context)
Find an operation pass manager that can operate on an operation of the given type,...
static OpPassManager * findPassManagerWithAnchor(MutableArrayRef< OpPassManager > mgrs, StringRef name)
Find an operation pass manager with the given anchor name, or nullptr if one does not exist.
#define MLIR_DEFINE_EXPLICIT_TYPE_ID(CLASS_NAME)
This class represents an analysis manager for a particular operation instance.
void clear()
Clear any held analyses.
void invalidate(const PreservedAnalyses &pa)
Invalidate any non preserved analyses,.
AnalysisManager nest(Operation *op)
Get an analysis manager for the given operation, which must be a proper descendant of the current ope...
PassInstrumentor * getPassInstrumentor() const
Returns a pass instrumentation object for the current operation.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
SmallVector< StringRef > getRegisteredDialectNames() const
Return the names of dialects registered in this registry with an allocator function.
LogicalResult preloadSelectDialects(MLIRContext *ctx, function_ref< InFlightDiagnostic()> emitError={}) const
Load into ctx every dialect previously added via addDialectToPreload(StringRef).
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
MLIRContext is the top-level object for a collection of MLIR operations.
void executeAction(function_ref< void()> actionFn, const tracing::Action &action)
Dispatch the provided action to the handler if any, or just execute it.
llvm::ThreadPoolInterface & getThreadPool()
Return the thread pool used by this context.
An analysis manager class specifically for the top-level operation.
This class represents a pass manager that runs passes on either a specific operation type,...
void printAsTextualPipeline(raw_ostream &os, bool pretty=false) const
Prints out the passes of the pass manager as the textual representation of pipelines.
OpPassManager & operator=(const OpPassManager &rhs)
friend class PassManager
Allow access to the constructor.
OpPassManager(Nesting nesting=Nesting::Explicit)
Construct a new op-agnostic ("any") pass manager with the given operation type and nesting behavior.
std::optional< OperationName > getOpName(MLIRContext &context) const
Return the operation name that this pass manager operates on, or std::nullopt if this is an op-agnost...
void setNesting(Nesting nesting)
Enable or disable the implicit nesting on this particular PassManager.
size_t size() const
Returns the number of passes held by this manager.
detail::OpPassManagerImpl & getImpl()
Returns the internal implementation instance.
void addPass(std::unique_ptr< Pass > pass)
Add the given pass to this pass manager.
Nesting getNesting()
Return the current nesting mode.
Nesting
This enum represents the nesting behavior of the pass manager.
@ Implicit
Implicit nesting behavior.
void dump()
Raw dump of the pass manager to llvm::errs().
llvm::pointee_iterator< MutableArrayRef< std::unique_ptr< Pass > >::iterator > pass_iterator
Iterator over the passes in this pass manager.
void getDependentDialects(DialectRegistry &dialects) const
Register dependent dialects for the current pass manager.
StringRef getOpAnchorName() const
Return the name used to anchor this pass manager.
std::optional< StringRef > getOpName() const
Return the operation name that this pass manager operates on, or std::nullopt if this is an op-agnost...
iterator_range< pass_iterator > getPasses()
OpPassManager & nestAny()
Nest a new op-agnostic ("any") pass manager under this pass manager.
llvm::pointee_iterator< ArrayRef< std::unique_ptr< Pass > >::const_iterator > const_pass_iterator
static StringRef getAnyOpAnchorName()
Return the string name used to anchor op-agnostic pass managers that operate generically on any viabl...
void clear()
Clear the pipeline, but not the other options set on this OpPassManager.
Set of flags used to control the behavior of the various IR print methods (e.g.
This class provides the API for ops that are known to be isolated from above.
A wrapper class that allows for printing an operation with a set of flags, useful to act as a "stream...
Operation is the basic unit of execution within MLIR.
Location getLoc()
The source location the operation was defined or derived from.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
std::optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
OperationName getName()
The name of an operation is the key identifier for it.
bool isAncestor(Operation *other)
Return true if this operation is an ancestor of the other operation.
bool isProperAncestor(Operation *other)
Return true if this operation is a proper ancestor of the other operation.
MLIRContext * getContext()
Return the context this operation is associated with.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
This class encapsulates the "action" of executing a single pass.
void print(raw_ostream &os) const override
Print a textual version of this action to os.
PassExecutionAction(ArrayRef< IRUnit > irUnits, const Pass &pass)
Construct a PassExecutionAction.
Operation * getOp() const
Get the operation that is the base of this pass.
static constexpr StringLiteral tag
The tag required by ActionImpl to identify this action.
const Pass & pass
Reference to the pass being run.
virtual void runAfterPipeline(std::optional< OperationName > name, const PipelineParentInfo &parentInfo)
A callback to run after a pass pipeline has executed.
void signalPassFailure(Pass *pass)
Helper method to enable analysis to signal pass failure.
virtual ~PassInstrumentation()=0
virtual void runBeforePipeline(std::optional< OperationName > name, const PipelineParentInfo &parentInfo)
A callback to run before a pass pipeline is executed.
This class holds a collection of PassInstrumentation objects, and invokes their respective call backs...
void runAfterPassFailed(Pass *pass, Operation *op)
See PassInstrumentation::runAfterPassFailed for details.
void addInstrumentation(std::unique_ptr< PassInstrumentation > pi)
Add the given instrumentation to the collection.
void runBeforeAnalysis(StringRef name, TypeID id, Operation *op)
See PassInstrumentation::runBeforeAnalysis for details.
void runAfterPass(Pass *pass, Operation *op)
See PassInstrumentation::runAfterPass for details.
void runAfterAnalysis(StringRef name, TypeID id, Operation *op)
See PassInstrumentation::runAfterAnalysis for details.
void runBeforePass(Pass *pass, Operation *op)
See PassInstrumentation::runBeforePass for details.
void runBeforePipeline(std::optional< OperationName > name, const PassInstrumentation::PipelineParentInfo &parentInfo)
See PassInstrumentation::runBeforePipeline for details.
void runAfterPipeline(std::optional< OperationName > name, const PassInstrumentation::PipelineParentInfo &parentInfo)
See PassInstrumentation::runAfterPipeline for details.
MLIRContext * getContext() const
Return an instance of the context.
LogicalResult run(Operation *op)
Run the passes within this manager on the provided operation.
void addInstrumentation(std::unique_ptr< PassInstrumentation > pi)
Add the provided instrumentation to the pass manager.
void enableVerifier(bool enabled=true)
Runs the verifier after each individual pass.
The abstract base pass class.
void copyOptionValuesFrom(const Pass *other)
Copy the option values from 'other', which is another instance of this pass.
virtual LogicalResult initializeOptions(StringRef options, function_ref< LogicalResult(const Twine &)> errorHandler)
Attempt to initialize the options of this pass from the given string.
virtual bool canScheduleOn(RegisteredOperationName opName) const =0
Indicate if the current pass can be scheduled on the given operation type.
Pass(TypeID passID, std::optional< StringRef > opName=std::nullopt)
void printAsTextualPipeline(raw_ostream &os, bool pretty=false)
Prints out the pass in the textual representation of pipelines.
virtual void runOnOperation()=0
The polymorphic API that runs the pass over the currently held operation.
friend class OpPassManager
Allow access to 'clone'.
virtual StringRef getName() const =0
Returns the derived pass name.
void signalPassFailure()
Signal that some invariant was broken when running.
virtual StringRef getArgument() const
Return the command line argument used when registering this pass.
This class provides an efficient unique identifier for a specific C++ type.
An adaptor pass used to run operation passes over nested operations.
void getDependentDialects(DialectRegistry &dialects) const override
Populate the set of dependent dialects for the passes in the current adaptor.
MutableArrayRef< OpPassManager > getPassManagers()
Returns the pass managers held by this adaptor.
void runOnOperation() override
The polymorphic API that runs the pass over the currently held operation.
std::string getAdaptorName()
Returns the adaptor pass name.
LogicalResult tryMergeInto(MLIRContext *ctx, OpToOpPassAdaptor &rhs)
Try to merge the current pass adaptor into 'rhs'.
OpToOpPassAdaptor(OpPassManager &&mgr)
A utility class to represent the analyses that are known to be preserved.
bool isAll() const
Returns true if all analyses were marked preserved.
bool isNone() const
Returns true if no analyses were marked preserved.
raw_ostream subclass that simplifies indention a sequence of code.
raw_indented_ostream & indent()
Increases the indent and returning this raw_indented_ostream.
raw_indented_ostream & unindent()
Decreases the indent and returning this raw_indented_ostream.
ArrayRef< IRUnit > irUnits
Set of IR units (operations, regions, blocks, values) that are associated with this action.
virtual ArrayRef< IRUnit > getContextIRUnits() const
Return the set of IR units that are associated with this action.
Include the generated interface declarations.
LogicalResult failableParallelForEachWithWorkerId(MLIRContext *context, IteratorT begin, IteratorT end, FuncT &&func)
Invoke the given function on the elements between [begin, end) asynchronously, passing each element a...
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
llvm::function_ref< Fn > function_ref
This struct represents information related to the parent pass of pipeline.
detail::AnalysisMap analyses
The analyses for the owning operation.
DenseMap< Operation *, std::unique_ptr< NestedAnalysisMap > > childAnalyses
The cached analyses for nested operations.
void invalidate(const PreservedAnalyses &pa)
Invalidate any non preserved analyses.
void clear()
Clear the list of passes in this pass manager, other options are preserved.
OpPassManagerImpl(const OpPassManagerImpl &rhs)
std::string name
The name of the operation that passes of this pass manager operate on.
OpPassManager::Nesting nesting
Control the implicit nesting of passes that mismatch the name set for this OpPassManager.
std::optional< StringRef > getOpName() const
void addPass(std::unique_ptr< Pass > pass)
Add the given pass to this pass manager.
unsigned initializationGeneration
The current initialization generation of this pass manager.
OpPassManagerImpl(OperationName opName, OpPassManager::Nesting nesting)
bool canScheduleOn(MLIRContext &context, OperationName opName)
Indicate if the current pass manager can be scheduled on the given operation type.
OpPassManagerImpl(OpPassManager::Nesting nesting)
StringRef getOpAnchorName() const
Return the name used to anchor this pass manager.
std::optional< OperationName > getOpName(MLIRContext &context)
Return the operation name of this pass manager.
OpPassManager & nest(OperationName nestedName)
Nest a new operation pass manager for the given operation kind under this pass manager.
OpPassManager & nestAny()
std::vector< std::unique_ptr< Pass > > passes
The set of passes to run as part of this pass manager.
void mergeInto(OpPassManagerImpl &rhs)
Merge the passes of this pass manager into the one provided.
LogicalResult finalizePassList(MLIRContext *ctx)
Finalize the pass list in preparation for execution.
OpPassManager & nest(StringRef nestedName)
std::optional< OperationName > opName
The cached OperationName (internalized in the context) for the name of the operation that passes of t...
OpPassManagerImpl(StringRef name, OpPassManager::Nesting nesting)
std::vector< std::unique_ptr< PassInstrumentation > > instrumentations
Set of registered instrumentations.
llvm::sys::SmartMutex< true > mutex
Mutex to keep instrumentation access thread-safe.
auto lockInstrumentations()
bool threadSafe
Dispatch may run concurrently only if every instrumentation opts in.