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"
30 #define DEBUG_TYPE "pass-manager"
41 :
Base(irUnits), pass(pass) {}
44 os << llvm::formatv(
"`{0}` running `{1}` on Operation `{2}`",
tag,
50 return irUnits.empty() ? nullptr
51 : llvm::dyn_cast_if_present<Operation *>(
irUnits[0]);
62 void Pass::anchor() {}
67 function_ref<LogicalResult(
const Twine &)> errorHandler) {
69 llvm::raw_string_ostream os(errStr);
71 return errorHandler(errStr);
87 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(
this)) {
89 adaptor->getPassManagers(),
90 [&](
OpPassManager &pm) { pm.printAsTextualPipeline(os, pretty); },
102 if (!argument.empty())
105 os <<
"unknown<" <<
getName() <<
">";
106 passOptions.
print(os);
128 for (
const std::unique_ptr<Pass> &pass : rhs.
passes) {
129 std::unique_ptr<Pass> newPass = pass->clone();
130 newPass->threadingSibling = pass.get();
131 passes.push_back(std::move(newPass));
153 void addPass(std::unique_ptr<Pass> pass);
171 return name.empty() ? std::optional<StringRef>()
172 : std::optional<StringRef>(
name);
194 std::vector<std::unique_ptr<Pass>>
passes;
208 assert(name == rhs.
name &&
"merging unrelated pass managers");
209 for (
auto &pass : passes)
210 rhs.
passes.push_back(std::move(pass));
216 addPass(std::unique_ptr<Pass>(adaptor));
217 return adaptor->getPassManagers().front();
220 void OpPassManagerImpl::addPass(std::unique_ptr<Pass> pass) {
223 std::optional<StringRef> pmOpName = getOpName();
224 std::optional<StringRef> passOpName = pass->getOpName();
225 if (pmOpName && passOpName && *pmOpName != *passOpName) {
227 return nest(*passOpName).addPass(std::move(pass));
228 llvm::report_fatal_error(llvm::Twine(
"Can't add pass '") + pass->getName() +
229 "' restricted to '" + *passOpName +
230 "' on a PassManager intended to run on '" +
231 getOpAnchorName() +
"', did you intend to nest?");
234 passes.emplace_back(std::move(pass));
237 void OpPassManagerImpl::clear() { passes.clear(); }
239 LogicalResult OpPassManagerImpl::finalizePassList(
MLIRContext *ctx) {
241 for (
auto &pm : adaptor->getPassManagers())
242 if (
failed(pm.getImpl().finalizePassList(ctx)))
248 LDBG(3) <<
"Merging adjacent adaptors in pass list";
250 for (
auto &pass : passes) {
252 if (
auto *currentAdaptor = dyn_cast<OpToOpPassAdaptor>(pass.get())) {
256 LDBG(3) <<
"Found first adaptor in chain";
257 lastAdaptor = currentAdaptor;
263 LDBG(3) <<
"Attempting to merge adaptor with "
265 <<
" managers into previous adaptor";
266 if (succeeded(currentAdaptor->tryMergeInto(ctx, *lastAdaptor))) {
267 LDBG(3) <<
"Successfully merged adaptors, removing current one";
270 LDBG(3) <<
"Failed to merge adaptors, keeping current as last";
271 lastAdaptor = currentAdaptor;
273 }
else if (lastAdaptor) {
275 LDBG(3) <<
"Finalizing adaptor chain before non-adaptor pass";
276 if (
failed(finalizeAdaptor(lastAdaptor)))
278 lastAdaptor =
nullptr;
283 if (lastAdaptor &&
failed(finalizeAdaptor(lastAdaptor)))
288 size_t beforeErase = passes.size();
289 llvm::erase_if(passes, std::logical_not<std::unique_ptr<Pass>>());
290 if (beforeErase != passes.size()) {
291 LDBG(3) <<
"Removed " << (beforeErase - passes.size())
292 <<
" merged adaptor slots from pass list";
296 std::optional<OperationName> rawOpName = getOpName(*ctx);
299 <<
"Op-agnostic pass manager, skipping operation-specific verification";
305 LDBG(3) <<
"Verifying " << passes.size() <<
" passes for operation '"
306 << getOpAnchorName() <<
"'";
308 std::optional<RegisteredOperationName> opName =
309 rawOpName->getRegisteredInfo();
310 for (std::unique_ptr<Pass> &pass : passes) {
311 if (opName && !pass->canScheduleOn(*opName)) {
313 <<
"unable to schedule pass '" << pass->getName()
314 <<
"' on a PassManager intended to run on '" << getOpAnchorName()
319 LDBG(3) <<
"Pass list finalization completed successfully";
327 std::optional<OperationName> pmOpName = getOpName(context);
329 return pmOpName == opName;
333 std::optional<RegisteredOperationName> registeredInfo =
335 if (!registeredInfo ||
338 return llvm::all_of(passes, [&](
const std::unique_ptr<Pass> &pass) {
339 return pass->canScheduleOn(*registeredInfo);
356 impl = std::make_unique<OpPassManagerImpl>(*rhs.impl);
360 impl = std::move(rhs.impl);
383 return impl->nest(nestedName);
386 return impl->nest(nestedName);
393 impl->addPass(std::move(pass));
406 return impl->getOpName();
410 std::optional<OperationName>
412 return impl->getOpName(context);
416 return impl->getOpAnchorName();
425 bool pretty =
false) {
426 os << anchorName <<
"(";
446 raw_ostream &os, StringRef anchorName,
456 indentedOS, anchorName,
463 llvm::errs() <<
"Pass Manager with " <<
impl->passes.size() <<
" passes:\n";
465 llvm::errs() <<
"\n";
471 pass.getDependentDialects(dialects);
482 LogicalResult OpPassManager::initialize(
MLIRContext *context,
483 unsigned newInitGeneration) {
485 if (
impl->initializationGeneration == newInitGeneration) {
486 LDBG(2) <<
"Pass manager already initialized "
487 <<
"' (generation " << newInitGeneration <<
") with " <<
size()
493 <<
"' (generation " << newInitGeneration <<
") with " <<
size()
495 impl->initializationGeneration = newInitGeneration;
499 auto *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
501 LDBG(2) <<
"Initializing pass '" << pass.getName() <<
"'";
502 if (
failed(pass.initialize(context))) {
503 LDBG(2) <<
"Failed to initialize pass '" << pass.getName() <<
"'";
510 LDBG(3) <<
"Initializing adaptor pass with "
511 << adaptor->getPassManagers().size() <<
" nested managers";
513 if (
failed(adaptorPM.initialize(context, newInitGeneration))) {
514 LDBG(2) <<
"Failed to initialize nested pass manager";
519 LDBG_OS([&](raw_ostream &os) {
520 os <<
"Pass manager initialization completed successfully: ";
526 llvm::hash_code OpPassManager::hash() {
527 llvm::hash_code hashCode{};
530 auto *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
532 hashCode = llvm::hash_combine(hashCode, &pass);
537 llvm::hash_combine(hashCode, adaptorPM.hash());
546 LogicalResult OpToOpPassAdaptor::run(
Pass *pass,
Operation *op,
548 unsigned parentInitGeneration) {
549 LDBG() <<
"Running pass '" << pass->
getName() <<
"' on operation '"
556 <<
"trying to schedule a pass on an unregistered operation";
559 return op->
emitOpError() <<
"trying to schedule a pass on an operation not "
560 "marked as 'IsolatedFromAbove'";
564 <<
"trying to schedule a pass on an unsupported operation";
575 return root->emitOpError()
576 <<
"Trying to schedule a dynamic pipeline on an "
577 "operation that isn't "
578 "nested under the current operation the pass is processing";
584 LDBG() <<
"Failed to finalize pass list for pipeline";
589 if (
failed(pipeline.initialize(root->getContext(), parentInitGeneration)))
592 return OpToOpPassAdaptor::runPipeline(pipeline, root, nestedAm,
593 verifyPasses, parentInitGeneration,
596 pass->passState.emplace(op, am, dynamicPipelineCallback);
602 bool passFailed =
false;
606 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass))
607 adaptor->runOnOperation(verifyPasses);
610 passFailed = pass->passState->irAndPassFailed.getInt();
615 am.
invalidate(pass->passState->preservedAnalyses);
619 if (!passFailed && verifyPasses) {
620 bool runVerifierNow =
true;
625 bool runVerifierRecursively = !isa<OpToOpPassAdaptor>(pass);
634 #ifndef EXPENSIVE_CHECKS
635 runVerifierNow = !pass->passState->preservedAnalyses.isAll();
638 passFailed =
failed(
verify(op, runVerifierRecursively));
650 return failure(passFailed);
654 LogicalResult OpToOpPassAdaptor::runPipeline(
658 LDBG_OS([&](raw_ostream &os) {
659 os <<
"Running pipeline on operation '"
661 << pm.
size() <<
" passes, verifyPasses=" << verifyPasses
665 assert((!instrumentor || parentInfo) &&
666 "expected parent info if instrumentor is provided");
667 auto scopeExit = llvm::make_scope_exit([&] {
682 if (
failed(run(&pass, op, am, verifyPasses, parentInitGeneration))) {
683 LDBG() <<
"Pipeline failed for pass '" << pass.
getName()
684 <<
"' on operation '"
701 LDBG(3) <<
"Looking for pass manager with anchor name '" << name <<
"' among "
702 << mgrs.size() <<
" managers";
704 auto *it = llvm::find_if(
707 if (it == mgrs.end()) {
708 LDBG(2) <<
"No pass manager found with anchor name '" << name <<
"'";
712 LDBG(2) <<
"Found pass manager with anchor name '" << name <<
"'";
721 LDBG(4) <<
"Looking for pass manager that can handle operation '" << name
722 <<
"' among " << mgrs.size() <<
" managers";
725 return mgr.
getImpl().canScheduleOn(context, name);
728 if (it == mgrs.end()) {
729 LDBG(4) <<
"No pass manager found that can handle operation '" << name
734 LDBG(4) <<
"Found pass manager '" << it->getOpAnchorName()
735 <<
"' that can handle operation '" << name <<
"'";
740 mgrs.emplace_back(std::move(mgr));
744 for (
auto &pm : mgrs)
750 LDBG(3) <<
"Attempting to merge pass adaptor with " << mgrs.size()
751 <<
" managers into rhs with " << rhs.mgrs.size() <<
" managers";
764 if (std::optional<OperationName> pmOpName = pm.
getOpName(*ctx))
777 auto *lhsGenericPMIt = llvm::find_if(mgrs, isGenericPM);
778 if (lhsGenericPMIt != mgrs.end()) {
779 LDBG(4) <<
"Found generic pass manager on LHS, checking for conflicts";
780 if (hasScheduleConflictWith(*lhsGenericPMIt, rhs.mgrs)) {
782 <<
"Merge failed: LHS generic pass manager has conflicts with RHS";
787 auto *rhsGenericPMIt = llvm::find_if(rhs.mgrs, isGenericPM);
788 if (rhsGenericPMIt != rhs.mgrs.end()) {
789 LDBG(4) <<
"Found generic pass manager on RHS, checking for conflicts";
790 if (hasScheduleConflictWith(*rhsGenericPMIt, mgrs)) {
792 <<
"Merge failed: RHS generic pass manager has conflicts with LHS";
797 for (
auto &pm : mgrs) {
800 if (
auto *existingPM =
805 rhs.mgrs.emplace_back(std::move(pm));
813 if (std::optional<StringRef> lhsName = lhs.
getOpName()) {
814 if (std::optional<StringRef> rhsName = rhs.
getOpName())
815 return *lhsName < *rhsName;
820 llvm::sort(rhs.mgrs, compareFn);
825 std::string OpToOpPassAdaptor::getAdaptorName() {
826 std::string name =
"Pipeline Collection : [";
827 llvm::raw_string_ostream os(name);
828 llvm::interleaveComma(getPassManagers(), os, [&](
OpPassManager &pm) {
835 void OpToOpPassAdaptor::runOnOperation() {
837 "Unexpected call to Pass::runOnOperation() on OpToOpPassAdaptor");
841 void OpToOpPassAdaptor::runOnOperation(
bool verifyPasses) {
843 runOnOperationAsyncImpl(verifyPasses);
845 runOnOperationImpl(verifyPasses);
849 void OpToOpPassAdaptor::runOnOperationImpl(
bool verifyPasses) {
850 LDBG_OS([&](raw_ostream &os) {
851 os <<
"Running pass adaptor synchronously on operation '"
853 <<
"' with " << mgrs.size()
854 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
858 auto am = getAnalysisManager();
861 auto *instrumentor = am.getPassInstrumentor();
863 unsigned processedOps = 0;
864 for (
auto ®ion : getOperation()->getRegions()) {
865 for (
auto &block : region) {
866 for (
auto &op : block) {
869 LDBG(2) <<
"Skipping operation '"
871 <<
"': no suitable pass manager found";
876 LDBG(2) <<
"Processing operation '"
878 <<
"' with pass manager '" << mgr->getOpAnchorName() <<
"'";
880 unsigned initGeneration = mgr->impl->initializationGeneration;
881 if (
failed(runPipeline(*mgr, &op, am.nest(&op), verifyPasses,
882 initGeneration, instrumentor, &parentInfo))) {
883 LDBG(2) <<
"Pipeline failed for operation '"
893 LDBG() <<
"Completed synchronous pass adaptor run, processed " << processedOps
901 return lhs.size() != rhs.size() ||
902 llvm::any_of(llvm::seq<size_t>(0, lhs.size()),
903 [&](
size_t i) { return lhs[i].size() != rhs[i].size(); });
907 void OpToOpPassAdaptor::runOnOperationAsyncImpl(
bool verifyPasses) {
908 LDBG_OS([&](raw_ostream &os) {
909 os <<
"Running pass adaptor asynchronously on operation '"
911 <<
"' with " << mgrs.size()
912 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
921 if (asyncExecutors.empty() ||
hasSizeMismatch(asyncExecutors.front(), mgrs)) {
922 LDBG(2) <<
"Creating " << context->
getThreadPool().getMaxConcurrency()
923 <<
" async executors";
924 asyncExecutors.assign(context->
getThreadPool().getMaxConcurrency(), mgrs);
931 : passManagerIdx(passManagerIdx), op(op), am(am) {}
934 unsigned passManagerIdx;
944 std::vector<OpPMInfo> opInfos;
947 LDBG(2) <<
"Collecting operations for async execution";
948 for (
auto ®ion : getOperation()->getRegions()) {
951 auto pmIdxIt = knownOpPMIdx.try_emplace(op.
getName(), std::nullopt);
952 if (pmIdxIt.second) {
954 pmIdxIt.first->second = std::distance(mgrs.begin(), mgr);
955 LDBG(2) <<
"Operation '"
957 <<
"' will use pass manager '" << mgr->getOpAnchorName()
963 if (pmIdxIt.first->second) {
964 opInfos.emplace_back(*pmIdxIt.first->second, &op, am.nest(&op));
966 LDBG(2) <<
"Operation '"
968 <<
"' skipped: no suitable pass manager";
973 LDBG(2) <<
"Collected " << opInfos.size()
974 <<
" operations for async execution";
979 auto *instrumentor = am.getPassInstrumentor();
982 std::vector<std::atomic<bool>> activePMs(asyncExecutors.size());
983 llvm::fill(activePMs,
false);
984 std::atomic<bool> hasFailure =
false;
987 auto it = llvm::find_if(activePMs, [](std::atomic<bool> &isActive) {
988 bool expectedInactive =
false;
989 return isActive.compare_exchange_strong(expectedInactive,
true);
991 unsigned pmIndex = it - activePMs.begin();
994 OpPassManager &pm = asyncExecutors[pmIndex][opInfo.passManagerIdx];
995 LogicalResult pipelineResult = runPipeline(
996 pm, opInfo.op, opInfo.am, verifyPasses,
997 pm.impl->initializationGeneration, instrumentor, &parentInfo);
998 if (
failed(pipelineResult))
999 hasFailure.store(
true);
1002 activePMs[pmIndex].store(
false);
1007 signalPassFailure();
1016 :
OpPassManager(operationName, nesting), context(ctx), passTiming(false),
1017 verifyPasses(true) {}
1021 context(operationName.
getContext()), passTiming(false),
1022 verifyPasses(true) {}
1030 LDBG_OS([&](raw_ostream &os) {
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 context->getOrLoadDialect(name);
1057 LDBG(2) <<
"Pass list finalization failed";
1062 context->enterMultiThreadedExecution();
1065 llvm::hash_code newInitKey = context->getRegistryHash();
1066 llvm::hash_code pipelineKey = hash();
1067 if (newInitKey != initializationKey ||
1068 pipelineKey != pipelineInitializationKey) {
1069 LDBG(2) <<
"Initializing passes with new generation: "
1070 << (
impl->initializationGeneration + 1);
1071 if (
failed(initialize(context,
impl->initializationGeneration + 1))) {
1072 LDBG(2) <<
"Pass initialization failed";
1075 initializationKey = newInitKey;
1076 pipelineInitializationKey = pipelineKey;
1078 LDBG(2) <<
"Using existing pass initialization (generation: "
1079 <<
impl->initializationGeneration <<
")";
1083 LDBG(2) <<
"Constructing analysis manager for pipeline execution";
1088 LDBG(2) <<
"Executing pipeline with "
1089 << (crashReproGenerator ?
"crash recovery" :
"normal execution");
1090 LogicalResult result =
1091 crashReproGenerator ? runWithCrashRecovery(op, am) : runPasses(op, am);
1094 context->exitMultiThreadedExecution();
1097 if (passStatisticsMode) {
1098 LDBG(2) <<
"Dumping pass statistics";
1102 LDBG(2) <<
"PassManager run completed with result: "
1103 << (succeeded(result) ?
"success" :
"failure");
1110 instrumentor = std::make_unique<PassInstrumentor>();
1116 LDBG(2) <<
"Executing passes using OpToOpPassAdaptor pipeline";
1117 return OpToOpPassAdaptor::runPipeline(*
this, op, am, verifyPasses,
1118 impl->initializationGeneration);
1130 "expected valid descendant operation");
1134 return nestImmediate(op);
1139 opAncestors.push_back(op);
1141 }
while (op != currentOp);
1144 for (
Operation *op : llvm::reverse(opAncestors))
1145 result = result.nestImmediate(op);
1152 "expected immediate child operation");
1154 auto [it, inserted] =
impl->childAnalyses.try_emplace(op);
1156 it->second = std::make_unique<NestedAnalysisMap>(op,
impl);
1157 return {it->second.get()};
1179 while (!mapsToInvalidate.empty()) {
1180 auto *map = mapsToInvalidate.pop_back_val();
1181 for (
auto &analysisPair : map->childAnalyses) {
1182 analysisPair.second->invalidate(pa);
1183 if (!analysisPair.second->childAnalyses.empty())
1184 mapsToInvalidate.push_back(analysisPair.second.get());
1222 std::optional<OperationName> name,
1224 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1225 for (
auto &instr :
impl->instrumentations)
1226 instr->runBeforePipeline(name, parentInfo);
1231 std::optional<OperationName> name,
1233 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1234 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1235 instr->runAfterPipeline(name, parentInfo);
1240 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1241 for (
auto &instr :
impl->instrumentations)
1242 instr->runBeforePass(pass, op);
1247 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1248 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1249 instr->runAfterPass(pass, op);
1254 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1255 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1256 instr->runAfterPassFailed(pass, op);
1262 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1263 for (
auto &instr :
impl->instrumentations)
1264 instr->runBeforeAnalysis(name,
id, op);
1270 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1271 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1272 instr->runAfterAnalysis(name,
id, op);
1277 std::unique_ptr<PassInstrumentation> pi) {
1278 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1279 impl->instrumentations.emplace_back(std::move(pi));
static MLIRContext * getContext(OpFoldResult val)
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.
auto getDialectNames() const
Return the names of dialects known to this registry.
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.
llvm::pointee_iterator< ArrayRef< std::unique_ptr< Pass > >::const_iterator > const_pass_iterator
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...
OpPassManager & nestAny()
Nest a new op-agnostic ("any") pass manager under this pass manager.
iterator_range< pass_iterator > getPasses()
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...
std::optional< RegisteredOperationName > getRegisteredInfo() const
If this operation is registered, returns the registered information, std::nullopt otherwise.
Operation is the basic unit of execution within MLIR.
MLIRContext * getContext()
Return the context this operation is associated with.
std::optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
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...
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.
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.
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.
void printAsTextualPipeline(raw_ostream &os, bool pretty=false)
Prints out the pass in the textual representation of pipelines.
std::optional< StringRef > getOpName() const
Returns the name of the operation that this pass operates on, or std::nullopt if this is a generic Op...
virtual void runOnOperation()=0
The polymorphic API that runs the pass over the currently held operation.
virtual StringRef getName() const =0
Returns the derived pass name.
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.
void invalidate(const PreservedAnalyses &pa)
Invalidate any cached analyses based upon the given set of preserved analyses.
An adaptor pass used to run operation passes over nested operations.
MutableArrayRef< OpPassManager > getPassManagers()
Returns the pass managers held by this adaptor.
LogicalResult parseFromString(StringRef options, raw_ostream &errorStream=llvm::errs())
Parse options out as key=value pairs that can then be handed off to the llvm::cl command line passing...
void print(raw_ostream &os) const
Print the options held by this struct in a form that can be parsed via 'parseFromString'.
void copyOptionValuesFrom(const PassOptions &other)
Copy the option values from 'other' into 'this', where 'other' has the same options as 'this'.
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 & unindent()
Decreases the indent and returning this raw_indented_ostream.
raw_indented_ostream & indent()
Increases the indent and returning this raw_indented_ostream.
virtual ArrayRef< IRUnit > getContextIRUnits() const
Return the set of IR units that are associated with this action.
ArrayRef< IRUnit > irUnits
Set of IR units (operations, regions, blocks, values) that are associated with this action.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void parallelForEach(MLIRContext *context, IteratorT begin, IteratorT end, FuncT &&func)
Invoke the given function on the elements between [begin, end) asynchronously.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
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< OperationName > getOpName(MLIRContext &context)
Return the operation name of this pass manager.
void addPass(std::unique_ptr< Pass > pass)
Add the given pass to this pass manager.
OpPassManager & nest(StringRef nestedName)
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.
OpPassManager & nestAny()
OpPassManager & nest(OperationName nestedName)
Nest a new operation pass manager for the given operation kind under this pass manager.
std::vector< std::unique_ptr< Pass > > passes
The set of passes to run as part of this pass manager.
std::optional< StringRef > getOpName() const
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.
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.