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"
44 os << llvm::formatv(
"`{0}` running `{1}` on Operation `{2}`",
tag,
51 : llvm::dyn_cast_if_present<Operation *>(
irUnits[0]);
67 function_ref<LogicalResult(
const Twine &)> errorHandler) {
69 llvm::raw_string_ostream os(errStr);
70 if (failed(passOptions.parseFromString(
options, os))) {
71 return errorHandler(errStr);
79 passOptions.copyOptionValuesFrom(other->passOptions);
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");
210 rhs.passes.push_back(std::move(pass));
216 addPass(std::unique_ptr<Pass>(adaptor));
217 return adaptor->getPassManagers().front();
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 '" +
234 passes.emplace_back(std::move(pass));
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 "
264 << currentAdaptor->getPassManagers().size()
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 '"
308 std::optional<RegisteredOperationName>
opName =
309 rawOpName->getRegisteredInfo();
310 for (std::unique_ptr<Pass> &pass :
passes) {
313 <<
"unable to schedule pass '" << pass->getName()
319 LDBG(3) <<
"Pass list finalization completed successfully";
327 std::optional<OperationName> pmOpName =
getOpName(context);
329 return pmOpName ==
opName;
333 std::optional<RegisteredOperationName> registeredInfo =
334 opName.getRegisteredInfo();
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);
383 return impl->nest(nestedName);
386 return impl->nest(nestedName);
393 impl->addPass(std::move(pass));
406 return impl->getOpName();
410std::optional<OperationName>
412 return impl->getOpName(context);
416 return impl->getOpAnchorName();
425 bool pretty =
false) {
426 os << anchorName <<
"(";
456 indentedOS, anchorName,
463 llvm::errs() <<
"Pass Manager with " <<
impl->passes.size() <<
" passes:\n";
465 llvm::errs() <<
"\n";
471 pass.getDependentDialects(dialects);
482LogicalResult 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: ";
526llvm::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());
546LogicalResult 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 <<
"' 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);
604 bool passFailed = pass->passState->irAndPassFailed.getInt();
609 if (
auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass))
610 adaptor->runOnOperation(verifyPasses);
613 passFailed = pass->passState->irAndPassFailed.getInt();
619 am.
invalidate(pass->passState->preservedAnalyses);
623 if (!passFailed && verifyPasses) {
624 bool runVerifierNow =
true;
629 bool runVerifierRecursively = !isa<OpToOpPassAdaptor>(pass);
638#ifndef EXPENSIVE_CHECKS
639 runVerifierNow = !pass->passState->preservedAnalyses.isAll();
642 passFailed =
failed(
verify(op, runVerifierRecursively));
651 passFailed = passFailed || pass->passState->irAndPassFailed.getInt();
656 return failure(passFailed);
660LogicalResult OpToOpPassAdaptor::runPipeline(
665 os <<
"Running pipeline on operation '"
667 << pm.
size() <<
" passes, verifyPasses=" << verifyPasses
671 assert((!instrumentor || parentInfo) &&
672 "expected parent info if instrumentor is provided");
673 auto scopeExit = llvm::make_scope_exit([&] {
688 if (
failed(run(&pass, op, am, verifyPasses, parentInitGeneration))) {
689 LDBG() <<
"Pipeline failed for pass '" << pass.
getName()
690 <<
"' on operation '"
707 LDBG(3) <<
"Looking for pass manager with anchor name '" << name <<
"' among "
708 << mgrs.size() <<
" managers";
710 auto *it = llvm::find_if(
713 if (it == mgrs.end()) {
714 LDBG(2) <<
"No pass manager found with anchor name '" << name <<
"'";
718 LDBG(2) <<
"Found pass manager with anchor name '" << name <<
"'";
727 LDBG(4) <<
"Looking for pass manager that can handle operation '" << name
728 <<
"' among " << mgrs.size() <<
" managers";
734 if (it == mgrs.end()) {
735 LDBG(4) <<
"No pass manager found that can handle operation '" << name
740 LDBG(4) <<
"Found pass manager '" << it->getOpAnchorName()
741 <<
"' that can handle operation '" << name <<
"'";
746 mgrs.emplace_back(std::move(mgr));
750 for (
auto &pm : mgrs)
756 LDBG(3) <<
"Attempting to merge pass adaptor with " << mgrs.size()
757 <<
" managers into rhs with " <<
rhs.mgrs.size() <<
" managers";
770 if (std::optional<OperationName> pmOpName = pm.
getOpName(*ctx))
783 auto *lhsGenericPMIt = llvm::find_if(mgrs, isGenericPM);
784 if (lhsGenericPMIt != mgrs.end()) {
785 LDBG(4) <<
"Found generic pass manager on LHS, checking for conflicts";
786 if (hasScheduleConflictWith(*lhsGenericPMIt,
rhs.mgrs)) {
788 <<
"Merge failed: LHS generic pass manager has conflicts with RHS";
793 auto *rhsGenericPMIt = llvm::find_if(
rhs.mgrs, isGenericPM);
794 if (rhsGenericPMIt !=
rhs.mgrs.end()) {
795 LDBG(4) <<
"Found generic pass manager on RHS, checking for conflicts";
796 if (hasScheduleConflictWith(*rhsGenericPMIt, mgrs)) {
798 <<
"Merge failed: RHS generic pass manager has conflicts with LHS";
803 for (
auto &pm : mgrs) {
806 if (
auto *existingPM =
811 rhs.mgrs.emplace_back(std::move(pm));
819 if (std::optional<StringRef> lhsName =
lhs.getOpName()) {
820 if (std::optional<StringRef> rhsName =
rhs.getOpName())
821 return *lhsName < *rhsName;
826 llvm::sort(
rhs.mgrs, compareFn);
832 std::string name =
"Pipeline Collection : [";
833 llvm::raw_string_ostream os(name);
843 "Unexpected call to Pass::runOnOperation() on OpToOpPassAdaptor");
849 runOnOperationAsyncImpl(verifyPasses);
851 runOnOperationImpl(verifyPasses);
855void OpToOpPassAdaptor::runOnOperationImpl(
bool verifyPasses) {
857 os <<
"Running pass adaptor synchronously on operation '"
859 <<
"' with " << mgrs.size()
860 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
864 auto am = getAnalysisManager();
867 auto *instrumentor = am.getPassInstrumentor();
869 unsigned processedOps = 0;
870 for (
auto ®ion : getOperation()->getRegions()) {
871 for (
auto &block : region) {
872 for (
auto &op : block) {
875 LDBG(2) <<
"Skipping operation '"
877 <<
"': no suitable pass manager found";
882 LDBG(2) <<
"Processing operation '"
884 <<
"' with pass manager '" << mgr->getOpAnchorName() <<
"'";
886 unsigned initGeneration = mgr->impl->initializationGeneration;
887 if (
failed(runPipeline(*mgr, &op, am.nest(&op), verifyPasses,
888 initGeneration, instrumentor, &parentInfo))) {
889 LDBG(2) <<
"Pipeline failed for operation '"
899 LDBG() <<
"Completed synchronous pass adaptor run, processed " << processedOps
907 return lhs.size() !=
rhs.size() ||
908 llvm::any_of(llvm::seq<size_t>(0,
lhs.size()),
909 [&](
size_t i) { return lhs[i].size() != rhs[i].size(); });
913void OpToOpPassAdaptor::runOnOperationAsyncImpl(
bool verifyPasses) {
915 os <<
"Running pass adaptor asynchronously on operation '"
917 <<
"' with " << mgrs.size()
918 <<
" pass managers, verifyPasses=" << verifyPasses <<
" pipeline: ";
927 if (asyncExecutors.empty() ||
hasSizeMismatch(asyncExecutors.front(), mgrs)) {
928 LDBG(2) <<
"Creating " << context->
getThreadPool().getMaxConcurrency()
929 <<
" async executors";
930 asyncExecutors.assign(context->
getThreadPool().getMaxConcurrency(), mgrs);
936 OpPMInfo(
unsigned passManagerIdx, Operation *op, AnalysisManager am)
937 : passManagerIdx(passManagerIdx), op(op), am(am) {}
940 unsigned passManagerIdx;
950 std::vector<OpPMInfo> opInfos;
953 LDBG(2) <<
"Collecting operations for async execution";
954 for (
auto ®ion : getOperation()->getRegions()) {
957 auto pmIdxIt = knownOpPMIdx.try_emplace(op.
getName(), std::nullopt);
958 if (pmIdxIt.second) {
960 pmIdxIt.first->second = std::distance(mgrs.begin(), mgr);
961 LDBG(2) <<
"Operation '"
963 <<
"' will use pass manager '" << mgr->getOpAnchorName()
969 if (pmIdxIt.first->second) {
970 opInfos.emplace_back(*pmIdxIt.first->second, &op, am.nest(&op));
972 LDBG(2) <<
"Operation '"
974 <<
"' skipped: no suitable pass manager";
979 LDBG(2) <<
"Collected " << opInfos.size()
980 <<
" operations for async execution";
985 auto *instrumentor = am.getPassInstrumentor();
988 std::vector<std::atomic<bool>> activePMs(asyncExecutors.size());
989 llvm::fill(activePMs,
false);
990 std::atomic<bool> hasFailure =
false;
993 auto it = llvm::find_if(activePMs, [](std::atomic<bool> &isActive) {
994 bool expectedInactive =
false;
995 return isActive.compare_exchange_strong(expectedInactive,
true);
997 unsigned pmIndex = it - activePMs.begin();
1000 OpPassManager &pm = asyncExecutors[pmIndex][opInfo.passManagerIdx];
1001 LogicalResult pipelineResult = runPipeline(
1002 pm, opInfo.op, opInfo.am, verifyPasses,
1003 pm.impl->initializationGeneration, instrumentor, &parentInfo);
1004 if (
failed(pipelineResult))
1005 hasFailure.store(
true);
1008 activePMs[pmIndex].store(
false);
1013 signalPassFailure();
1023 verifyPasses(
true) {}
1028 verifyPasses(
true) {}
1037 os <<
"Starting PassManager run on operation '"
1039 <<
size() <<
" passes, verifyPasses=" << verifyPasses <<
" pipeline: ";
1044 std::optional<OperationName> anchorOp =
getOpName(*context);
1045 if (anchorOp && anchorOp != op->
getName()) {
1052 LDBG(2) <<
"Registering dependent dialects for pipeline";
1055 context->appendDialectRegistry(dependentDialects);
1057 LDBG(2) <<
"Loading dialect: " << name;
1058 context->getOrLoadDialect(name);
1062 if (failed(
getImpl().finalizePassList(context))) {
1063 LDBG(2) <<
"Pass list finalization failed";
1068 context->enterMultiThreadedExecution();
1071 llvm::hash_code newInitKey = context->getRegistryHash();
1072 llvm::hash_code pipelineKey = hash();
1073 if (newInitKey != initializationKey ||
1074 pipelineKey != pipelineInitializationKey) {
1075 LDBG(2) <<
"Initializing passes with new generation: "
1076 << (
impl->initializationGeneration + 1);
1077 if (failed(initialize(context,
impl->initializationGeneration + 1))) {
1078 LDBG(2) <<
"Pass initialization failed";
1081 initializationKey = newInitKey;
1082 pipelineInitializationKey = pipelineKey;
1084 LDBG(2) <<
"Using existing pass initialization (generation: "
1085 <<
impl->initializationGeneration <<
")";
1089 LDBG(2) <<
"Constructing analysis manager for pipeline execution";
1094 LDBG(2) <<
"Executing pipeline with "
1095 << (crashReproGenerator ?
"crash recovery" :
"normal execution");
1097 crashReproGenerator ? runWithCrashRecovery(op, am) : runPasses(op, am);
1100 context->exitMultiThreadedExecution();
1103 if (passStatisticsMode) {
1104 LDBG(2) <<
"Dumping pass statistics";
1108 LDBG(2) <<
"PassManager run completed with result: "
1109 << (succeeded(
result) ?
"success" :
"failure");
1116 instrumentor = std::make_unique<PassInstrumentor>();
1118 instrumentor->addInstrumentation(std::move(pi));
1122 LDBG(2) <<
"Executing passes using OpToOpPassAdaptor pipeline";
1123 return OpToOpPassAdaptor::runPipeline(*
this, op, am, verifyPasses,
1124 impl->initializationGeneration);
1136 "expected valid descendant operation");
1140 return nestImmediate(op);
1145 opAncestors.push_back(op);
1147 }
while (op != currentOp);
1149 AnalysisManager
result = *
this;
1150 for (
Operation *op : llvm::reverse(opAncestors))
1158 "expected immediate child operation");
1160 auto [it,
inserted] =
impl->childAnalyses.try_emplace(op);
1162 it->second = std::make_unique<NestedAnalysisMap>(op,
impl);
1163 return {it->second.get()};
1185 while (!mapsToInvalidate.empty()) {
1186 auto *map = mapsToInvalidate.pop_back_val();
1187 for (
auto &analysisPair : map->childAnalyses) {
1188 analysisPair.second->invalidate(pa);
1189 if (!analysisPair.second->childAnalyses.empty())
1190 mapsToInvalidate.push_back(analysisPair.second.get());
1232 std::optional<OperationName> name,
1234 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1235 for (
auto &instr :
impl->instrumentations)
1236 instr->runBeforePipeline(name, parentInfo);
1241 std::optional<OperationName> name,
1243 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1244 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1245 instr->runAfterPipeline(name, parentInfo);
1250 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1251 for (
auto &instr :
impl->instrumentations)
1252 instr->runBeforePass(pass, op);
1257 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1258 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1259 instr->runAfterPass(pass, op);
1264 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1265 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1266 instr->runAfterPassFailed(pass, op);
1272 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1273 for (
auto &instr :
impl->instrumentations)
1274 instr->runBeforeAnalysis(name,
id, op);
1280 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1281 for (
auto &instr : llvm::reverse(
impl->instrumentations))
1282 instr->runAfterAnalysis(name,
id, op);
1287 std::unique_ptr<PassInstrumentation> pi) {
1288 llvm::sys::SmartScopedLock<true> instrumentationLock(
impl->mutex);
1289 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.
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.
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.
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.
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.