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,
463#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
465 llvm::errs() <<
"Pass Manager with " <<
impl->passes.size() <<
" passes:\n";
467 llvm::errs() <<
"\n";
474 pass.getDependentDialects(dialects);
485LogicalResult OpPassManager::initialize(
MLIRContext *context,
486 unsigned newInitGeneration) {
488 if (
impl->initializationGeneration == newInitGeneration) {
489 LDBG(2) <<
"Pass manager already initialized "
490 <<
"' (generation " << newInitGeneration <<
") with " <<
size()
496 <<
"' (generation " << newInitGeneration <<
") with " <<
size()
498 impl->initializationGeneration = newInitGeneration;
502 auto *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
504 LDBG(2) <<
"Initializing pass '" << pass.getName() <<
"'";
505 if (failed(pass.initialize(context))) {
506 LDBG(2) <<
"Failed to initialize pass '" << pass.getName() <<
"'";
513 LDBG(3) <<
"Initializing adaptor pass with "
514 << adaptor->getPassManagers().size() <<
" nested managers";
516 if (
failed(adaptorPM.initialize(context, newInitGeneration))) {
517 LDBG(2) <<
"Failed to initialize nested pass manager";
522 LDBG_OS([&](raw_ostream &os) {
523 os <<
"Pass manager initialization completed successfully: ";
529llvm::hash_code OpPassManager::hash() {
530 llvm::hash_code hashCode{};
533 auto *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
535 hashCode = llvm::hash_combine(hashCode, &pass);
540 llvm::hash_combine(hashCode, adaptorPM.hash());
549LogicalResult OpToOpPassAdaptor::run(
Pass *pass,
Operation *op,
551 unsigned parentInitGeneration) {
552 LDBG() <<
"Running pass '" << pass->
getName() <<
"' on operation '"
559 <<
"trying to schedule a pass on an unregistered operation";
562 return op->
emitOpError() <<
"trying to schedule a pass on an operation not "
563 "marked as 'IsolatedFromAbove'";
567 <<
"' on an unsupported operation";
578 return root->emitOpError()
579 <<
"Trying to schedule a dynamic pipeline on an "
580 "operation that isn't "
581 "nested under the current operation the pass is processing";
587 LDBG() <<
"Failed to finalize pass list for pipeline";
592 if (
failed(pipeline.initialize(root->getContext(), parentInitGeneration)))
595 return OpToOpPassAdaptor::runPipeline(pipeline, root, nestedAm,
596 verifyPasses, parentInitGeneration,
599 pass->passState.emplace(op, am, dynamicPipelineCallback);
607 bool passFailed = pass->passState->irAndPassFailed.getInt();
612 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass))
613 adaptor->runOnOperation(verifyPasses);
616 passFailed = pass->passState->irAndPassFailed.getInt();
622 am.
invalidate(pass->passState->preservedAnalyses);
626 if (!passFailed && verifyPasses) {
627 bool runVerifierNow =
true;
632 bool runVerifierRecursively = !isa<OpToOpPassAdaptor>(pass);
641#ifndef EXPENSIVE_CHECKS
642 runVerifierNow = !pass->passState->preservedAnalyses.isAll();
645 passFailed =
failed(
verify(op, runVerifierRecursively));
654 passFailed = passFailed || pass->passState->irAndPassFailed.getInt();
659 return failure(passFailed);
663LogicalResult OpToOpPassAdaptor::runPipeline(
668 os <<
"Running pipeline on operation '"
670 << pm.
size() <<
" passes, verifyPasses=" << verifyPasses
674 assert((!instrumentor || parentInfo) &&
675 "expected parent info if instrumentor is provided");
676 llvm::scope_exit scopeExit([&] {
691 if (
failed(run(&pass, op, am, verifyPasses, parentInitGeneration))) {
692 LDBG() <<
"Pipeline failed for pass '" << pass.
getName()
693 <<
"' on operation '"
710 LDBG(3) <<
"Looking for pass manager with anchor name '" << name <<
"' among "
711 << mgrs.size() <<
" managers";
713 auto *it = llvm::find_if(
716 if (it == mgrs.end()) {
717 LDBG(2) <<
"No pass manager found with anchor name '" << name <<
"'";
721 LDBG(2) <<
"Found pass manager with anchor name '" << name <<
"'";
730 LDBG(4) <<
"Looking for pass manager that can handle operation '" << name
731 <<
"' among " << mgrs.size() <<
" managers";
737 if (it == mgrs.end()) {
738 LDBG(4) <<
"No pass manager found that can handle operation '" << name
743 LDBG(4) <<
"Found pass manager '" << it->getOpAnchorName()
744 <<
"' that can handle operation '" << name <<
"'";
749 mgrs.emplace_back(std::move(mgr));
753 for (
auto &pm : mgrs)
759 LDBG(3) <<
"Attempting to merge pass adaptor with " << mgrs.size()
760 <<
" managers into rhs with " << rhs.mgrs.size() <<
" managers";
773 if (std::optional<OperationName> pmOpName = pm.
getOpName(*ctx))
786 auto *lhsGenericPMIt = llvm::find_if(mgrs, isGenericPM);
787 if (lhsGenericPMIt != mgrs.end()) {
788 LDBG(4) <<
"Found generic pass manager on LHS, checking for conflicts";
789 if (hasScheduleConflictWith(*lhsGenericPMIt, rhs.mgrs)) {
791 <<
"Merge failed: LHS generic pass manager has conflicts with RHS";
796 auto *rhsGenericPMIt = llvm::find_if(rhs.mgrs, isGenericPM);
797 if (rhsGenericPMIt != rhs.mgrs.end()) {
798 LDBG(4) <<
"Found generic pass manager on RHS, checking for conflicts";
799 if (hasScheduleConflictWith(*rhsGenericPMIt, mgrs)) {
801 <<
"Merge failed: RHS generic pass manager has conflicts with LHS";
806 for (
auto &pm : mgrs) {
809 if (
auto *existingPM =
814 rhs.mgrs.emplace_back(std::move(pm));
822 if (std::optional<StringRef> lhsName = lhs.getOpName()) {
823 if (std::optional<StringRef> rhsName = rhs.getOpName())
824 return *lhsName < *rhsName;
829 llvm::sort(rhs.mgrs, compareFn);
835 std::string name =
"Pipeline Collection : [";
836 llvm::raw_string_ostream os(name);
846 "Unexpected call to Pass::runOnOperation() on OpToOpPassAdaptor");
852 runOnOperationAsyncImpl(verifyPasses);
854 runOnOperationImpl(verifyPasses);
858void OpToOpPassAdaptor::runOnOperationImpl(
bool verifyPasses) {
860 os <<
"Running pass adaptor synchronously on operation '"
862 <<
"' with " << mgrs.size()
863 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
867 auto am = getAnalysisManager();
870 auto *instrumentor = am.getPassInstrumentor();
872 unsigned processedOps = 0;
873 for (
auto ®ion : getOperation()->getRegions()) {
874 for (
auto &block : region) {
875 for (
auto &op : block) {
878 LDBG(2) <<
"Skipping operation '"
880 <<
"': no suitable pass manager found";
885 LDBG(2) <<
"Processing operation '"
887 <<
"' with pass manager '" << mgr->getOpAnchorName() <<
"'";
889 unsigned initGeneration = mgr->impl->initializationGeneration;
890 if (
failed(runPipeline(*mgr, &op, am.nest(&op), verifyPasses,
891 initGeneration, instrumentor, &parentInfo))) {
892 LDBG(2) <<
"Pipeline failed for operation '"
902 LDBG() <<
"Completed synchronous pass adaptor run, processed " << processedOps
910 return lhs.size() != rhs.size() ||
911 llvm::any_of(llvm::seq<size_t>(0, lhs.size()),
912 [&](
size_t i) { return lhs[i].size() != rhs[i].size(); });
916void OpToOpPassAdaptor::runOnOperationAsyncImpl(
bool verifyPasses) {
918 os <<
"Running pass adaptor asynchronously on operation '"
920 <<
"' with " << mgrs.size()
921 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
930 if (asyncExecutors.empty() ||
hasSizeMismatch(asyncExecutors.front(), mgrs)) {
931 LDBG(2) <<
"Creating " << context->
getThreadPool().getMaxConcurrency()
932 <<
" async executors";
933 asyncExecutors.assign(context->
getThreadPool().getMaxConcurrency(), mgrs);
939 OpPMInfo(
unsigned passManagerIdx, Operation *op, AnalysisManager am)
940 : passManagerIdx(passManagerIdx), op(op), am(am) {}
943 unsigned passManagerIdx;
953 std::vector<OpPMInfo> opInfos;
956 LDBG(2) <<
"Collecting operations for async execution";
957 for (
auto ®ion : getOperation()->getRegions()) {
960 auto pmIdxIt = knownOpPMIdx.try_emplace(op.
getName(), std::nullopt);
961 if (pmIdxIt.second) {
963 pmIdxIt.first->second = std::distance(mgrs.begin(), mgr);
964 LDBG(2) <<
"Operation '"
966 <<
"' will use pass manager '" << mgr->getOpAnchorName()
972 if (pmIdxIt.first->second) {
973 opInfos.emplace_back(*pmIdxIt.first->second, &op, am.nest(&op));
975 LDBG(2) <<
"Operation '"
977 <<
"' skipped: no suitable pass manager";
982 LDBG(2) <<
"Collected " << opInfos.size()
983 <<
" operations for async execution";
988 auto *instrumentor = am.getPassInstrumentor();
993 std::atomic<bool> hasFailure =
false;
995 context, opInfos.begin(), opInfos.end(),
996 [&](OpPMInfo &opInfo,
unsigned pmIndex) {
997 OpPassManager &pm = asyncExecutors[pmIndex][opInfo.passManagerIdx];
998 LogicalResult pipelineResult = runPipeline(
999 pm, opInfo.op, opInfo.am, verifyPasses,
1000 pm.impl->initializationGeneration, instrumentor, &parentInfo);
1001 if (failed(pipelineResult))
1002 hasFailure.store(true);
1009 signalPassFailure();
1019 verifyPasses(
true) {}
1024 verifyPasses(
true) {}
1033 os <<
"Starting PassManager run on operation '"
1035 <<
size() <<
" passes, verifyPasses=" << verifyPasses <<
" pipeline: ";
1040 std::optional<OperationName> anchorOp =
getOpName(*context);
1041 if (anchorOp && anchorOp != op->
getName()) {
1048 LDBG(2) <<
"Registering dependent dialects for pipeline";
1051 context->appendDialectRegistry(dependentDialects);
1053 LDBG(2) <<
"Loading dialect: " << name;
1054 Dialect *loaded = context->getOrLoadDialect(name);
1055 assert(loaded &&
"allocator-backed registration must resolve");
1059 context, [&]() { return emitError(op->getLoc()); })))
1063 if (failed(
getImpl().finalizePassList(context))) {
1064 LDBG(2) <<
"Pass list finalization failed";
1069 context->enterMultiThreadedExecution();
1072 llvm::hash_code newInitKey = context->getRegistryHash();
1073 llvm::hash_code pipelineKey = hash();
1074 if (newInitKey != initializationKey ||
1075 pipelineKey != pipelineInitializationKey) {
1076 LDBG(2) <<
"Initializing passes with new generation: "
1077 << (
impl->initializationGeneration + 1);
1078 if (failed(initialize(context,
impl->initializationGeneration + 1))) {
1079 LDBG(2) <<
"Pass initialization failed";
1082 initializationKey = newInitKey;
1083 pipelineInitializationKey = pipelineKey;
1085 LDBG(2) <<
"Using existing pass initialization (generation: "
1086 <<
impl->initializationGeneration <<
")";
1090 LDBG(2) <<
"Constructing analysis manager for pipeline execution";
1095 LDBG(2) <<
"Executing pipeline with "
1096 << (crashReproGenerator ?
"crash recovery" :
"normal execution");
1098 crashReproGenerator ? runWithCrashRecovery(op, am) : runPasses(op, am);
1101 context->exitMultiThreadedExecution();
1104 if (passStatisticsMode) {
1105 LDBG(2) <<
"Dumping pass statistics";
1109 LDBG(2) <<
"PassManager run completed with result: "
1110 << (succeeded(
result) ?
"success" :
"failure");
1117 instrumentor = std::make_unique<PassInstrumentor>();
1119 instrumentor->addInstrumentation(std::move(pi));
1123 LDBG(2) <<
"Executing passes using OpToOpPassAdaptor pipeline";
1124 return OpToOpPassAdaptor::runPipeline(*
this, op, am, verifyPasses,
1125 impl->initializationGeneration);
1137 "expected valid descendant operation");
1141 return nestImmediate(op);
1146 opAncestors.push_back(op);
1148 }
while (op != currentOp);
1150 AnalysisManager
result = *
this;
1151 for (
Operation *op : llvm::reverse(opAncestors))
1159 "expected immediate child operation");
1161 auto [it,
inserted] =
impl->childAnalyses.try_emplace(op);
1163 it->second = std::make_unique<NestedAnalysisMap>(op,
impl);
1164 return {it->second.get()};
1186 while (!mapsToInvalidate.empty()) {
1187 auto *map = mapsToInvalidate.pop_back_val();
1188 for (
auto &analysisPair : map->childAnalyses) {
1189 analysisPair.second->invalidate(pa);
1190 if (!analysisPair.second->childAnalyses.empty())
1191 mapsToInvalidate.push_back(analysisPair.second.get());
1227 std::unique_lock<llvm::sys::SmartMutex<true>> lock(
mutex, std::defer_lock);
1244 std::optional<OperationName> name,
1246 auto instrumentationLock =
impl->lockInstrumentations();
1247 for (
auto &instr :
impl->instrumentations)
1248 instr->runBeforePipeline(name, parentInfo);
1253 std::optional<OperationName> name,
1255 auto instrumentationLock =
impl->lockInstrumentations();
1256 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1257 instr->runAfterPipeline(name, parentInfo);
1262 auto instrumentationLock =
impl->lockInstrumentations();
1263 for (
auto &instr :
impl->instrumentations)
1264 instr->runBeforePass(pass, op);
1269 auto instrumentationLock =
impl->lockInstrumentations();
1270 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1271 instr->runAfterPass(pass, op);
1276 auto instrumentationLock =
impl->lockInstrumentations();
1277 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1278 instr->runAfterPassFailed(pass, op);
1284 auto instrumentationLock =
impl->lockInstrumentations();
1285 for (
auto &instr :
impl->instrumentations)
1286 instr->runBeforeAnalysis(name,
id, op);
1292 auto instrumentationLock =
impl->lockInstrumentations();
1293 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1294 instr->runAfterAnalysis(name,
id, op);
1299 std::unique_ptr<PassInstrumentation> pi) {
1300 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1301 impl->threadSafe &= pi->isThreadSafe();
1302 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.
LLVM_DUMP_METHOD 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.