MLIR  16.0.0git
Pass.cpp
Go to the documentation of this file.
1 //===- Pass.cpp - Pass infrastructure implementation ----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements common pass infrastructure.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "mlir/Pass/Pass.h"
14 #include "PassDetail.h"
15 #include "mlir/IR/Diagnostics.h"
16 #include "mlir/IR/Dialect.h"
17 #include "mlir/IR/OpDefinition.h"
18 #include "mlir/IR/Threading.h"
19 #include "mlir/IR/Verifier.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ADT/ScopeExit.h"
23 #include "llvm/Support/CommandLine.h"
24 #include "llvm/Support/CrashRecoveryContext.h"
25 #include "llvm/Support/Mutex.h"
26 #include "llvm/Support/Signals.h"
27 #include "llvm/Support/Threading.h"
28 #include "llvm/Support/ToolOutputFile.h"
29 
30 using namespace mlir;
31 using namespace mlir::detail;
32 
33 //===----------------------------------------------------------------------===//
34 // Pass
35 //===----------------------------------------------------------------------===//
36 
37 /// Out of line virtual method to ensure vtables and metadata are emitted to a
38 /// single .o file.
39 void Pass::anchor() {}
40 
41 /// Attempt to initialize the options of this pass from the given string.
43  return passOptions.parseFromString(options);
44 }
45 
46 /// Copy the option values from 'other', which is another instance of this
47 /// pass.
48 void Pass::copyOptionValuesFrom(const Pass *other) {
49  passOptions.copyOptionValuesFrom(other->passOptions);
50 }
51 
52 /// Prints out the pass in the textual representation of pipelines. If this is
53 /// an adaptor pass, print its pass managers.
54 void Pass::printAsTextualPipeline(raw_ostream &os) {
55  // Special case for adaptors to print its pass managers.
56  if (auto *adaptor = dyn_cast<OpToOpPassAdaptor>(this)) {
57  llvm::interleave(
58  adaptor->getPassManagers(),
59  [&](OpPassManager &pm) { pm.printAsTextualPipeline(os); },
60  [&] { os << ","; });
61  return;
62  }
63  // Otherwise, print the pass argument followed by its options. If the pass
64  // doesn't have an argument, print the name of the pass to give some indicator
65  // of what pass was run.
66  StringRef argument = getArgument();
67  if (!argument.empty())
68  os << argument;
69  else
70  os << "unknown<" << getName() << ">";
71  passOptions.print(os);
72 }
73 
74 //===----------------------------------------------------------------------===//
75 // OpPassManagerImpl
76 //===----------------------------------------------------------------------===//
77 
78 namespace mlir {
79 namespace detail {
82  : name(opName.getStringRef().str()), opName(opName),
83  initializationGeneration(0), nesting(nesting) {}
84  OpPassManagerImpl(StringRef name, OpPassManager::Nesting nesting)
85  : name(name == OpPassManager::getAnyOpAnchorName() ? "" : name.str()),
86  initializationGeneration(0), nesting(nesting) {}
88  : initializationGeneration(0), nesting(nesting) {}
90  : name(rhs.name), opName(rhs.opName),
91  initializationGeneration(rhs.initializationGeneration),
92  nesting(rhs.nesting) {
93  for (const std::unique_ptr<Pass> &pass : rhs.passes) {
94  std::unique_ptr<Pass> newPass = pass->clone();
95  newPass->threadingSibling = pass.get();
96  passes.push_back(std::move(newPass));
97  }
98  }
99 
100  /// Merge the passes of this pass manager into the one provided.
101  void mergeInto(OpPassManagerImpl &rhs);
102 
103  /// Nest a new operation pass manager for the given operation kind under this
104  /// pass manager.
106  return nest(OpPassManager(nestedName, nesting));
107  }
108  OpPassManager &nest(StringRef nestedName) {
109  return nest(OpPassManager(nestedName, nesting));
110  }
111  OpPassManager &nestAny() { return nest(OpPassManager(nesting)); }
112 
113  /// Nest the given pass manager under this pass manager.
114  OpPassManager &nest(OpPassManager &&nested);
115 
116  /// Add the given pass to this pass manager. If this pass has a concrete
117  /// operation type, it must be the same type as this pass manager.
118  void addPass(std::unique_ptr<Pass> pass);
119 
120  /// Clear the list of passes in this pass manager, other options are
121  /// preserved.
122  void clear();
123 
124  /// Finalize the pass list in preparation for execution. This includes
125  /// coalescing adjacent pass managers when possible, verifying scheduled
126  /// passes, etc.
127  LogicalResult finalizePassList(MLIRContext *ctx);
128 
129  /// Return the operation name of this pass manager.
131  if (!name.empty() && !opName)
132  opName = OperationName(name, &context);
133  return opName;
134  }
136  return name.empty() ? Optional<StringRef>() : Optional<StringRef>(name);
137  }
138 
139  /// Return the name used to anchor this pass manager. This is either the name
140  /// of an operation, or the result of `getAnyOpAnchorName()` in the case of an
141  /// op-agnostic pass manager.
142  StringRef getOpAnchorName() const {
143  return getOpName().value_or(OpPassManager::getAnyOpAnchorName());
144  }
145 
146  /// Indicate if the current pass manager can be scheduled on the given
147  /// operation type.
148  bool canScheduleOn(MLIRContext &context, OperationName opName);
149 
150  /// The name of the operation that passes of this pass manager operate on.
151  std::string name;
152 
153  /// The cached OperationName (internalized in the context) for the name of the
154  /// operation that passes of this pass manager operate on.
156 
157  /// The set of passes to run as part of this pass manager.
158  std::vector<std::unique_ptr<Pass>> passes;
159 
160  /// The current initialization generation of this pass manager. This is used
161  /// to indicate when a pass manager should be reinitialized.
163 
164  /// Control the implicit nesting of passes that mismatch the name set for this
165  /// OpPassManager.
167 };
168 } // namespace detail
169 } // namespace mlir
170 
172  assert(name == rhs.name && "merging unrelated pass managers");
173  for (auto &pass : passes)
174  rhs.passes.push_back(std::move(pass));
175  passes.clear();
176 }
177 
179  auto *adaptor = new OpToOpPassAdaptor(std::move(nested));
180  addPass(std::unique_ptr<Pass>(adaptor));
181  return adaptor->getPassManagers().front();
182 }
183 
184 void OpPassManagerImpl::addPass(std::unique_ptr<Pass> pass) {
185  // If this pass runs on a different operation than this pass manager, then
186  // implicitly nest a pass manager for this operation if enabled.
187  Optional<StringRef> pmOpName = getOpName();
188  Optional<StringRef> passOpName = pass->getOpName();
189  if (pmOpName && passOpName && *pmOpName != *passOpName) {
191  return nest(*passOpName).addPass(std::move(pass));
192  llvm::report_fatal_error(llvm::Twine("Can't add pass '") + pass->getName() +
193  "' restricted to '" + *passOpName +
194  "' on a PassManager intended to run on '" +
195  getOpAnchorName() + "', did you intend to nest?");
196  }
197 
198  passes.emplace_back(std::move(pass));
199 }
200 
201 void OpPassManagerImpl::clear() { passes.clear(); }
202 
204  auto finalizeAdaptor = [ctx](OpToOpPassAdaptor *adaptor) {
205  for (auto &pm : adaptor->getPassManagers())
206  if (failed(pm.getImpl().finalizePassList(ctx)))
207  return failure();
208  return success();
209  };
210 
211  // Walk the pass list and merge adjacent adaptors.
212  OpToOpPassAdaptor *lastAdaptor = nullptr;
213  for (auto &pass : passes) {
214  // Check to see if this pass is an adaptor.
215  if (auto *currentAdaptor = dyn_cast<OpToOpPassAdaptor>(pass.get())) {
216  // If it is the first adaptor in a possible chain, remember it and
217  // continue.
218  if (!lastAdaptor) {
219  lastAdaptor = currentAdaptor;
220  continue;
221  }
222 
223  // Otherwise, try to merge into the existing adaptor and delete the
224  // current one. If merging fails, just remember this as the last adaptor.
225  if (succeeded(currentAdaptor->tryMergeInto(ctx, *lastAdaptor)))
226  pass.reset();
227  else
228  lastAdaptor = currentAdaptor;
229  } else if (lastAdaptor) {
230  // If this pass isn't an adaptor, finalize it and forget the last adaptor.
231  if (failed(finalizeAdaptor(lastAdaptor)))
232  return failure();
233  lastAdaptor = nullptr;
234  }
235  }
236 
237  // If there was an adaptor at the end of the manager, finalize it as well.
238  if (lastAdaptor && failed(finalizeAdaptor(lastAdaptor)))
239  return failure();
240 
241  // Now that the adaptors have been merged, erase any empty slots corresponding
242  // to the merged adaptors that were nulled-out in the loop above.
243  llvm::erase_if(passes, std::logical_not<std::unique_ptr<Pass>>());
244 
245  // If this is a op-agnostic pass manager, there is nothing left to do.
246  Optional<OperationName> rawOpName = getOpName(*ctx);
247  if (!rawOpName)
248  return success();
249 
250  // Otherwise, verify that all of the passes are valid for the current
251  // operation anchor.
252  Optional<RegisteredOperationName> opName = rawOpName->getRegisteredInfo();
253  for (std::unique_ptr<Pass> &pass : passes) {
254  if (opName && !pass->canScheduleOn(*opName)) {
255  return emitError(UnknownLoc::get(ctx))
256  << "unable to schedule pass '" << pass->getName()
257  << "' on a PassManager intended to run on '" << getOpAnchorName()
258  << "'!";
259  }
260  }
261  return success();
262 }
263 
265  OperationName opName) {
266  // If this pass manager is op-specific, we simply check if the provided
267  // operation name is the same as this one.
268  Optional<OperationName> pmOpName = getOpName(context);
269  if (pmOpName)
270  return pmOpName == opName;
271 
272  // Otherwise, this is an op-agnostic pass manager. Check that the operation
273  // can be scheduled on all passes within the manager.
274  Optional<RegisteredOperationName> registeredInfo = opName.getRegisteredInfo();
275  if (!registeredInfo ||
276  !registeredInfo->hasTrait<OpTrait::IsIsolatedFromAbove>())
277  return false;
278  return llvm::all_of(passes, [&](const std::unique_ptr<Pass> &pass) {
279  return pass->canScheduleOn(*registeredInfo);
280  });
281 }
282 
283 //===----------------------------------------------------------------------===//
284 // OpPassManager
285 //===----------------------------------------------------------------------===//
286 
288  : impl(new OpPassManagerImpl(nesting)) {}
289 OpPassManager::OpPassManager(StringRef name, Nesting nesting)
290  : impl(new OpPassManagerImpl(name, nesting)) {}
292  : impl(new OpPassManagerImpl(name, nesting)) {}
293 OpPassManager::OpPassManager(OpPassManager &&rhs) { *this = std::move(rhs); }
294 OpPassManager::OpPassManager(const OpPassManager &rhs) { *this = rhs; }
296  impl = std::make_unique<OpPassManagerImpl>(*rhs.impl);
297  return *this;
298 }
300  impl = std::move(rhs.impl);
301  return *this;
302 }
303 
305 
307  return MutableArrayRef<std::unique_ptr<Pass>>{impl->passes}.begin();
308 }
310  return MutableArrayRef<std::unique_ptr<Pass>>{impl->passes}.end();
311 }
312 
314  return ArrayRef<std::unique_ptr<Pass>>{impl->passes}.begin();
315 }
317  return ArrayRef<std::unique_ptr<Pass>>{impl->passes}.end();
318 }
319 
320 /// Nest a new operation pass manager for the given operation kind under this
321 /// pass manager.
323  return impl->nest(nestedName);
324 }
325 OpPassManager &OpPassManager::nest(StringRef nestedName) {
326  return impl->nest(nestedName);
327 }
328 OpPassManager &OpPassManager::nestAny() { return impl->nestAny(); }
329 
330 /// Add the given pass to this pass manager. If this pass has a concrete
331 /// operation type, it must be the same type as this pass manager.
332 void OpPassManager::addPass(std::unique_ptr<Pass> pass) {
333  impl->addPass(std::move(pass));
334 }
335 
336 void OpPassManager::clear() { impl->clear(); }
337 
338 /// Returns the number of passes held by this manager.
339 size_t OpPassManager::size() const { return impl->passes.size(); }
340 
341 /// Returns the internal implementation instance.
343 
344 /// Return the operation name that this pass manager operates on.
346  return impl->getOpName();
347 }
348 
349 /// Return the operation name that this pass manager operates on.
351  return impl->getOpName(context);
352 }
353 
355  return impl->getOpAnchorName();
356 }
357 
358 /// Prints out the passes of the pass manager as the textual representation
359 /// of pipelines.
360 void OpPassManager::printAsTextualPipeline(raw_ostream &os) const {
361  os << getOpAnchorName() << "(";
362  llvm::interleave(
363  impl->passes,
364  [&](const std::unique_ptr<Pass> &pass) {
365  pass->printAsTextualPipeline(os);
366  },
367  [&]() { os << ","; });
368  os << ")";
369 }
370 
372  llvm::errs() << "Pass Manager with " << impl->passes.size() << " passes:\n";
373  printAsTextualPipeline(llvm::errs());
374  llvm::errs() << "\n";
375 }
376 
378  DialectRegistry &dialects) {
379  for (const Pass &pass : pm.getPasses())
380  pass.getDependentDialects(dialects);
381 }
382 
384  registerDialectsForPipeline(*this, dialects);
385 }
386 
387 void OpPassManager::setNesting(Nesting nesting) { impl->nesting = nesting; }
388 
390 
391 LogicalResult OpPassManager::initialize(MLIRContext *context,
392  unsigned newInitGeneration) {
393  if (impl->initializationGeneration == newInitGeneration)
394  return success();
395  impl->initializationGeneration = newInitGeneration;
396  for (Pass &pass : getPasses()) {
397  // If this pass isn't an adaptor, directly initialize it.
398  auto *adaptor = dyn_cast<OpToOpPassAdaptor>(&pass);
399  if (!adaptor) {
400  if (failed(pass.initialize(context)))
401  return failure();
402  continue;
403  }
404 
405  // Otherwise, initialize each of the adaptors pass managers.
406  for (OpPassManager &adaptorPM : adaptor->getPassManagers())
407  if (failed(adaptorPM.initialize(context, newInitGeneration)))
408  return failure();
409  }
410  return success();
411 }
412 
413 //===----------------------------------------------------------------------===//
414 // OpToOpPassAdaptor
415 //===----------------------------------------------------------------------===//
416 
417 LogicalResult OpToOpPassAdaptor::run(Pass *pass, Operation *op,
418  AnalysisManager am, bool verifyPasses,
419  unsigned parentInitGeneration) {
421  if (!opInfo)
422  return op->emitOpError()
423  << "trying to schedule a pass on an unregistered operation";
424  if (!opInfo->hasTrait<OpTrait::IsIsolatedFromAbove>())
425  return op->emitOpError() << "trying to schedule a pass on an operation not "
426  "marked as 'IsolatedFromAbove'";
427 
428  // Initialize the pass state with a callback for the pass to dynamically
429  // execute a pipeline on the currently visited operation.
431  PassInstrumentation::PipelineParentInfo parentInfo = {llvm::get_threadid(),
432  pass};
433  auto dynamicPipelineCallback = [&](OpPassManager &pipeline,
434  Operation *root) -> LogicalResult {
435  if (!op->isAncestor(root))
436  return root->emitOpError()
437  << "Trying to schedule a dynamic pipeline on an "
438  "operation that isn't "
439  "nested under the current operation the pass is processing";
440  assert(
441  pipeline.getImpl().canScheduleOn(*op->getContext(), root->getName()));
442 
443  // Before running, finalize the passes held by the pipeline.
444  if (failed(pipeline.getImpl().finalizePassList(root->getContext())))
445  return failure();
446 
447  // Initialize the user provided pipeline and execute the pipeline.
448  if (failed(pipeline.initialize(root->getContext(), parentInitGeneration)))
449  return failure();
450  AnalysisManager nestedAm = root == op ? am : am.nest(root);
451  return OpToOpPassAdaptor::runPipeline(pipeline, root, nestedAm,
452  verifyPasses, parentInitGeneration,
453  pi, &parentInfo);
454  };
455  pass->passState.emplace(op, am, dynamicPipelineCallback);
456 
457  // Instrument before the pass has run.
458  if (pi)
459  pi->runBeforePass(pass, op);
460 
461  // Invoke the virtual runOnOperation method.
462  if (auto *adaptor = dyn_cast<OpToOpPassAdaptor>(pass))
463  adaptor->runOnOperation(verifyPasses);
464  else
465  pass->runOnOperation();
466  bool passFailed = pass->passState->irAndPassFailed.getInt();
467 
468  // Invalidate any non preserved analyses.
469  am.invalidate(pass->passState->preservedAnalyses);
470 
471  // When verifyPasses is specified, we run the verifier (unless the pass
472  // failed).
473  if (!passFailed && verifyPasses) {
474  bool runVerifierNow = true;
475 
476  // If the pass is an adaptor pass, we don't run the verifier recursively
477  // because the nested operations should have already been verified after
478  // nested passes had run.
479  bool runVerifierRecursively = !isa<OpToOpPassAdaptor>(pass);
480 
481  // Reduce compile time by avoiding running the verifier if the pass didn't
482  // change the IR since the last time the verifier was run:
483  //
484  // 1) If the pass said that it preserved all analyses then it can't have
485  // permuted the IR.
486  //
487  // We run these checks in EXPENSIVE_CHECKS mode out of caution.
488 #ifndef EXPENSIVE_CHECKS
489  runVerifierNow = !pass->passState->preservedAnalyses.isAll();
490 #endif
491  if (runVerifierNow)
492  passFailed = failed(verify(op, runVerifierRecursively));
493  }
494 
495  // Instrument after the pass has run.
496  if (pi) {
497  if (passFailed)
498  pi->runAfterPassFailed(pass, op);
499  else
500  pi->runAfterPass(pass, op);
501  }
502 
503  // Return if the pass signaled a failure.
504  return failure(passFailed);
505 }
506 
507 /// Run the given operation and analysis manager on a provided op pass manager.
508 LogicalResult OpToOpPassAdaptor::runPipeline(
509  OpPassManager &pm, Operation *op, AnalysisManager am, bool verifyPasses,
510  unsigned parentInitGeneration, PassInstrumentor *instrumentor,
511  const PassInstrumentation::PipelineParentInfo *parentInfo) {
512  assert((!instrumentor || parentInfo) &&
513  "expected parent info if instrumentor is provided");
514  auto scopeExit = llvm::make_scope_exit([&] {
515  // Clear out any computed operation analyses. These analyses won't be used
516  // any more in this pipeline, and this helps reduce the current working set
517  // of memory. If preserving these analyses becomes important in the future
518  // we can re-evaluate this.
519  am.clear();
520  });
521 
522  // Run the pipeline over the provided operation.
523  if (instrumentor) {
524  instrumentor->runBeforePipeline(pm.getOpName(*op->getContext()),
525  *parentInfo);
526  }
527 
528  for (Pass &pass : pm.getPasses())
529  if (failed(run(&pass, op, am, verifyPasses, parentInitGeneration)))
530  return failure();
531 
532  if (instrumentor) {
533  instrumentor->runAfterPipeline(pm.getOpName(*op->getContext()),
534  *parentInfo);
535  }
536  return success();
537 }
538 
539 /// Find an operation pass manager with the given anchor name, or nullptr if one
540 /// does not exist.
541 static OpPassManager *
543  auto *it = llvm::find_if(
544  mgrs, [&](OpPassManager &mgr) { return mgr.getOpAnchorName() == name; });
545  return it == mgrs.end() ? nullptr : &*it;
546 }
547 
548 /// Find an operation pass manager that can operate on an operation of the given
549 /// type, or nullptr if one does not exist.
551  OperationName name,
552  MLIRContext &context) {
553  auto *it = llvm::find_if(mgrs, [&](OpPassManager &mgr) {
554  return mgr.getImpl().canScheduleOn(context, name);
555  });
556  return it == mgrs.end() ? nullptr : &*it;
557 }
558 
559 OpToOpPassAdaptor::OpToOpPassAdaptor(OpPassManager &&mgr) {
560  mgrs.emplace_back(std::move(mgr));
561 }
562 
563 void OpToOpPassAdaptor::getDependentDialects(DialectRegistry &dialects) const {
564  for (auto &pm : mgrs)
565  pm.getDependentDialects(dialects);
566 }
567 
568 LogicalResult OpToOpPassAdaptor::tryMergeInto(MLIRContext *ctx,
569  OpToOpPassAdaptor &rhs) {
570  // Functor used to check if a pass manager is generic, i.e. op-agnostic.
571  auto isGenericPM = [&](OpPassManager &pm) { return !pm.getOpName(); };
572 
573  // Functor used to detect if the given generic pass manager will have a
574  // potential schedule conflict with the given `otherPMs`.
575  auto hasScheduleConflictWith = [&](OpPassManager &genericPM,
577  return llvm::any_of(otherPMs, [&](OpPassManager &pm) {
578  // If this is a non-generic pass manager, a conflict will arise if a
579  // non-generic pass manager's operation name can be scheduled on the
580  // generic passmanager.
581  if (Optional<OperationName> pmOpName = pm.getOpName(*ctx))
582  return genericPM.getImpl().canScheduleOn(*ctx, *pmOpName);
583  // Otherwise, this is a generic pass manager. We current can't determine
584  // when generic pass managers can be merged, so conservatively assume they
585  // conflict.
586  return true;
587  });
588  };
589 
590  // Check that if either adaptor has a generic pass manager, that pm is
591  // compatible within any non-generic pass managers.
592  //
593  // Check the current adaptor.
594  auto *lhsGenericPMIt = llvm::find_if(mgrs, isGenericPM);
595  if (lhsGenericPMIt != mgrs.end() &&
596  hasScheduleConflictWith(*lhsGenericPMIt, rhs.mgrs))
597  return failure();
598  // Check the rhs adaptor.
599  auto *rhsGenericPMIt = llvm::find_if(rhs.mgrs, isGenericPM);
600  if (rhsGenericPMIt != rhs.mgrs.end() &&
601  hasScheduleConflictWith(*rhsGenericPMIt, mgrs))
602  return failure();
603 
604  for (auto &pm : mgrs) {
605  // If an existing pass manager exists, then merge the given pass manager
606  // into it.
607  if (auto *existingPM =
608  findPassManagerWithAnchor(rhs.mgrs, pm.getOpAnchorName())) {
609  pm.getImpl().mergeInto(existingPM->getImpl());
610  } else {
611  // Otherwise, add the given pass manager to the list.
612  rhs.mgrs.emplace_back(std::move(pm));
613  }
614  }
615  mgrs.clear();
616 
617  // After coalescing, sort the pass managers within rhs by name.
618  auto compareFn = [](const OpPassManager *lhs, const OpPassManager *rhs) {
619  // Order op-specific pass managers first and op-agnostic pass managers last.
620  if (Optional<StringRef> lhsName = lhs->getOpName()) {
621  if (Optional<StringRef> rhsName = rhs->getOpName())
622  return lhsName->compare(*rhsName);
623  return -1; // lhs(op-specific) < rhs(op-agnostic)
624  }
625  return 1; // lhs(op-agnostic) > rhs(op-specific)
626  };
627  llvm::array_pod_sort(rhs.mgrs.begin(), rhs.mgrs.end(), compareFn);
628  return success();
629 }
630 
631 /// Returns the adaptor pass name.
632 std::string OpToOpPassAdaptor::getAdaptorName() {
633  std::string name = "Pipeline Collection : [";
634  llvm::raw_string_ostream os(name);
635  llvm::interleaveComma(getPassManagers(), os, [&](OpPassManager &pm) {
636  os << '\'' << pm.getOpAnchorName() << '\'';
637  });
638  os << ']';
639  return os.str();
640 }
641 
642 void OpToOpPassAdaptor::runOnOperation() {
643  llvm_unreachable(
644  "Unexpected call to Pass::runOnOperation() on OpToOpPassAdaptor");
645 }
646 
647 /// Run the held pipeline over all nested operations.
648 void OpToOpPassAdaptor::runOnOperation(bool verifyPasses) {
649  if (getContext().isMultithreadingEnabled())
650  runOnOperationAsyncImpl(verifyPasses);
651  else
652  runOnOperationImpl(verifyPasses);
653 }
654 
655 /// Run this pass adaptor synchronously.
656 void OpToOpPassAdaptor::runOnOperationImpl(bool verifyPasses) {
657  auto am = getAnalysisManager();
658  PassInstrumentation::PipelineParentInfo parentInfo = {llvm::get_threadid(),
659  this};
660  auto *instrumentor = am.getPassInstrumentor();
661  for (auto &region : getOperation()->getRegions()) {
662  for (auto &block : region) {
663  for (auto &op : block) {
664  auto *mgr = findPassManagerFor(mgrs, op.getName(), *op.getContext());
665  if (!mgr)
666  continue;
667 
668  // Run the held pipeline over the current operation.
669  unsigned initGeneration = mgr->impl->initializationGeneration;
670  if (failed(runPipeline(*mgr, &op, am.nest(&op), verifyPasses,
671  initGeneration, instrumentor, &parentInfo)))
672  return signalPassFailure();
673  }
674  }
675  }
676 }
677 
678 /// Utility functor that checks if the two ranges of pass managers have a size
679 /// mismatch.
682  return lhs.size() != rhs.size() ||
683  llvm::any_of(llvm::seq<size_t>(0, lhs.size()),
684  [&](size_t i) { return lhs[i].size() != rhs[i].size(); });
685 }
686 
687 /// Run this pass adaptor synchronously.
688 void OpToOpPassAdaptor::runOnOperationAsyncImpl(bool verifyPasses) {
689  AnalysisManager am = getAnalysisManager();
690  MLIRContext *context = &getContext();
691 
692  // Create the async executors if they haven't been created, or if the main
693  // pipeline has changed.
694  if (asyncExecutors.empty() || hasSizeMismatch(asyncExecutors.front(), mgrs))
695  asyncExecutors.assign(context->getThreadPool().getThreadCount(), mgrs);
696 
697  // This struct represents the information for a single operation to be
698  // scheduled on a pass manager.
699  struct OpPMInfo {
700  OpPMInfo(unsigned passManagerIdx, Operation *op, AnalysisManager am)
701  : passManagerIdx(passManagerIdx), op(op), am(am) {}
702 
703  /// The index of the pass manager to schedule the operation on.
704  unsigned passManagerIdx;
705  /// The operation to schedule.
706  Operation *op;
707  /// The analysis manager for the operation.
708  AnalysisManager am;
709  };
710 
711  // Run a prepass over the operation to collect the nested operations to
712  // execute over. This ensures that an analysis manager exists for each
713  // operation, as well as providing a queue of operations to execute over.
714  std::vector<OpPMInfo> opInfos;
716  for (auto &region : getOperation()->getRegions()) {
717  for (Operation &op : region.getOps()) {
718  // Get the pass manager index for this operation type.
719  auto pmIdxIt = knownOpPMIdx.try_emplace(op.getName(), std::nullopt);
720  if (pmIdxIt.second) {
721  if (auto *mgr = findPassManagerFor(mgrs, op.getName(), *context))
722  pmIdxIt.first->second = std::distance(mgrs.begin(), mgr);
723  }
724 
725  // If this operation can be scheduled, add it to the list.
726  if (pmIdxIt.first->second)
727  opInfos.emplace_back(*pmIdxIt.first->second, &op, am.nest(&op));
728  }
729  }
730 
731  // Get the current thread for this adaptor.
732  PassInstrumentation::PipelineParentInfo parentInfo = {llvm::get_threadid(),
733  this};
734  auto *instrumentor = am.getPassInstrumentor();
735 
736  // An atomic failure variable for the async executors.
737  std::vector<std::atomic<bool>> activePMs(asyncExecutors.size());
738  std::fill(activePMs.begin(), activePMs.end(), false);
739  auto processFn = [&](OpPMInfo &opInfo) {
740  // Find an executor for this operation.
741  auto it = llvm::find_if(activePMs, [](std::atomic<bool> &isActive) {
742  bool expectedInactive = false;
743  return isActive.compare_exchange_strong(expectedInactive, true);
744  });
745  unsigned pmIndex = it - activePMs.begin();
746 
747  // Get the pass manager for this operation and execute it.
748  OpPassManager &pm = asyncExecutors[pmIndex][opInfo.passManagerIdx];
749  LogicalResult pipelineResult = runPipeline(
750  pm, opInfo.op, opInfo.am, verifyPasses,
751  pm.impl->initializationGeneration, instrumentor, &parentInfo);
752 
753  // Reset the active bit for this pass manager.
754  activePMs[pmIndex].store(false);
755  return pipelineResult;
756  };
757 
758  // Signal a failure if any of the executors failed.
759  if (failed(failableParallelForEach(context, opInfos, processFn)))
760  signalPassFailure();
761 }
762 
763 //===----------------------------------------------------------------------===//
764 // PassManager
765 //===----------------------------------------------------------------------===//
766 
768  StringRef operationName)
769  : OpPassManager(OperationName(operationName, ctx), nesting), context(ctx),
770  initializationKey(DenseMapInfo<llvm::hash_code>::getTombstoneKey()),
771  passTiming(false), verifyPasses(true) {}
772 
773 PassManager::~PassManager() = default;
774 
775 void PassManager::enableVerifier(bool enabled) { verifyPasses = enabled; }
776 
777 /// Run the passes within this manager on the provided operation.
779  MLIRContext *context = getContext();
780  Optional<OperationName> anchorOp = getOpName(*context);
781  if (anchorOp && anchorOp != op->getName())
782  return emitError(op->getLoc())
783  << "can't run '" << getOpAnchorName() << "' pass manager on '"
784  << op->getName() << "' op";
785 
786  // Register all dialects for the current pipeline.
787  DialectRegistry dependentDialects;
788  getDependentDialects(dependentDialects);
789  context->appendDialectRegistry(dependentDialects);
790  for (StringRef name : dependentDialects.getDialectNames())
791  context->getOrLoadDialect(name);
792 
793  // Before running, make sure to finalize the pipeline pass list.
794  if (failed(getImpl().finalizePassList(context)))
795  return failure();
796 
797  // Initialize all of the passes within the pass manager with a new generation.
798  llvm::hash_code newInitKey = context->getRegistryHash();
799  if (newInitKey != initializationKey) {
800  if (failed(initialize(context, impl->initializationGeneration + 1)))
801  return failure();
802  initializationKey = newInitKey;
803  }
804 
805  // Construct a top level analysis manager for the pipeline.
806  ModuleAnalysisManager am(op, instrumentor.get());
807 
808  // Notify the context that we start running a pipeline for book keeping.
809  context->enterMultiThreadedExecution();
810 
811  // If reproducer generation is enabled, run the pass manager with crash
812  // handling enabled.
813  LogicalResult result =
814  crashReproGenerator ? runWithCrashRecovery(op, am) : runPasses(op, am);
815 
816  // Notify the context that the run is done.
817  context->exitMultiThreadedExecution();
818 
819  // Dump all of the pass statistics if necessary.
820  if (passStatisticsMode)
821  dumpStatistics();
822  return result;
823 }
824 
825 /// Add the provided instrumentation to the pass manager.
826 void PassManager::addInstrumentation(std::unique_ptr<PassInstrumentation> pi) {
827  if (!instrumentor)
828  instrumentor = std::make_unique<PassInstrumentor>();
829 
830  instrumentor->addInstrumentation(std::move(pi));
831 }
832 
833 LogicalResult PassManager::runPasses(Operation *op, AnalysisManager am) {
834  return OpToOpPassAdaptor::runPipeline(*this, op, am, verifyPasses,
835  impl->initializationGeneration);
836 }
837 
838 //===----------------------------------------------------------------------===//
839 // AnalysisManager
840 //===----------------------------------------------------------------------===//
841 
842 /// Get an analysis manager for the given operation, which must be a proper
843 /// descendant of the current operation represented by this analysis manager.
845  Operation *currentOp = impl->getOperation();
846  assert(currentOp->isProperAncestor(op) &&
847  "expected valid descendant operation");
848 
849  // Check for the base case where the provided operation is immediately nested.
850  if (currentOp == op->getParentOp())
851  return nestImmediate(op);
852 
853  // Otherwise, we need to collect all ancestors up to the current operation.
854  SmallVector<Operation *, 4> opAncestors;
855  do {
856  opAncestors.push_back(op);
857  op = op->getParentOp();
858  } while (op != currentOp);
859 
860  AnalysisManager result = *this;
861  for (Operation *op : llvm::reverse(opAncestors))
862  result = result.nestImmediate(op);
863  return result;
864 }
865 
866 /// Get an analysis manager for the given immediately nested child operation.
867 AnalysisManager AnalysisManager::nestImmediate(Operation *op) {
868  assert(impl->getOperation() == op->getParentOp() &&
869  "expected immediate child operation");
870 
871  auto it = impl->childAnalyses.find(op);
872  if (it == impl->childAnalyses.end())
873  it = impl->childAnalyses
874  .try_emplace(op, std::make_unique<NestedAnalysisMap>(op, impl))
875  .first;
876  return {it->second.get()};
877 }
878 
879 /// Invalidate any non preserved analyses.
881  const detail::PreservedAnalyses &pa) {
882  // If all analyses were preserved, then there is nothing to do here.
883  if (pa.isAll())
884  return;
885 
886  // Invalidate the analyses for the current operation directly.
887  analyses.invalidate(pa);
888 
889  // If no analyses were preserved, then just simply clear out the child
890  // analysis results.
891  if (pa.isNone()) {
892  childAnalyses.clear();
893  return;
894  }
895 
896  // Otherwise, invalidate each child analysis map.
897  SmallVector<NestedAnalysisMap *, 8> mapsToInvalidate(1, this);
898  while (!mapsToInvalidate.empty()) {
899  auto *map = mapsToInvalidate.pop_back_val();
900  for (auto &analysisPair : map->childAnalyses) {
901  analysisPair.second->invalidate(pa);
902  if (!analysisPair.second->childAnalyses.empty())
903  mapsToInvalidate.push_back(analysisPair.second.get());
904  }
905  }
906 }
907 
908 //===----------------------------------------------------------------------===//
909 // PassInstrumentation
910 //===----------------------------------------------------------------------===//
911 
913 
915  Optional<OperationName> name, const PipelineParentInfo &parentInfo) {}
916 
918  Optional<OperationName> name, const PipelineParentInfo &parentInfo) {}
919 
920 //===----------------------------------------------------------------------===//
921 // PassInstrumentor
922 //===----------------------------------------------------------------------===//
923 
924 namespace mlir {
925 namespace detail {
927  /// Mutex to keep instrumentation access thread-safe.
929 
930  /// Set of registered instrumentations.
931  std::vector<std::unique_ptr<PassInstrumentation>> instrumentations;
932 };
933 } // namespace detail
934 } // namespace mlir
935 
938 
939 /// See PassInstrumentation::runBeforePipeline for details.
942  const PassInstrumentation::PipelineParentInfo &parentInfo) {
943  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
944  for (auto &instr : impl->instrumentations)
945  instr->runBeforePipeline(name, parentInfo);
946 }
947 
948 /// See PassInstrumentation::runAfterPipeline for details.
951  const PassInstrumentation::PipelineParentInfo &parentInfo) {
952  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
953  for (auto &instr : llvm::reverse(impl->instrumentations))
954  instr->runAfterPipeline(name, parentInfo);
955 }
956 
957 /// See PassInstrumentation::runBeforePass for details.
959  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
960  for (auto &instr : impl->instrumentations)
961  instr->runBeforePass(pass, op);
962 }
963 
964 /// See PassInstrumentation::runAfterPass for details.
966  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
967  for (auto &instr : llvm::reverse(impl->instrumentations))
968  instr->runAfterPass(pass, op);
969 }
970 
971 /// See PassInstrumentation::runAfterPassFailed for details.
973  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
974  for (auto &instr : llvm::reverse(impl->instrumentations))
975  instr->runAfterPassFailed(pass, op);
976 }
977 
978 /// See PassInstrumentation::runBeforeAnalysis for details.
980  Operation *op) {
981  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
982  for (auto &instr : impl->instrumentations)
983  instr->runBeforeAnalysis(name, id, op);
984 }
985 
986 /// See PassInstrumentation::runAfterAnalysis for details.
988  Operation *op) {
989  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
990  for (auto &instr : llvm::reverse(impl->instrumentations))
991  instr->runAfterAnalysis(name, id, op);
992 }
993 
994 /// Add the given instrumentation to the collection.
996  std::unique_ptr<PassInstrumentation> pi) {
997  llvm::sys::SmartScopedLock<true> instrumentationLock(impl->mutex);
998  impl->instrumentations.emplace_back(std::move(pi));
999 }
static llvm::ManagedStatic< PassManagerOptions > options
static void registerDialectsForPipeline(const OpPassManager &pm, DialectRegistry &dialects)
Definition: Pass.cpp:377
static bool hasSizeMismatch(ArrayRef< OpPassManager > lhs, ArrayRef< OpPassManager > rhs)
Utility functor that checks if the two ranges of pass managers have a size mismatch.
Definition: Pass.cpp:680
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,...
Definition: Pass.cpp:550
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.
Definition: Pass.cpp:542
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...
Definition: Pass.cpp:844
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.
Definition: MLIRContext.h:56
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
llvm::hash_code getRegistryHash()
Returns a hash of the registry of the context that may be used to give a rough indicator of if the st...
void enterMultiThreadedExecution()
These APIs are tracking whether the context will be used in a multithreading environment: this has no...
llvm::ThreadPool & getThreadPool()
Return the thread pool used by this context.
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
Definition: MLIRContext.h:93
void exitMultiThreadedExecution()
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,...
Definition: PassManager.h:52
OpPassManager & operator=(const OpPassManager &rhs)
Definition: Pass.cpp:295
friend class PassManager
Allow access to the constructor.
Definition: PassManager.h:186
OpPassManager(Nesting nesting=Nesting::Explicit)
Construct a new op-agnostic ("any") pass manager with the given operation type and nesting behavior.
Definition: Pass.cpp:287
OpPassManager & nest()
Definition: PassManager.h:103
void printAsTextualPipeline(raw_ostream &os) const
Prints out the passes of the pass manager as the textual representation of pipelines.
Definition: Pass.cpp:360
void setNesting(Nesting nesting)
Enable or disable the implicit nesting on this particular PassManager.
Definition: Pass.cpp:387
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...
Definition: Pass.cpp:350
size_t size() const
Returns the number of passes held by this manager.
Definition: Pass.cpp:339
detail::OpPassManagerImpl & getImpl()
Returns the internal implementation instance.
Definition: Pass.cpp:342
void addPass(std::unique_ptr< Pass > pass)
Add the given pass to this pass manager.
Definition: Pass.cpp:332
Nesting getNesting()
Return the current nesting mode.
Definition: Pass.cpp:389
Nesting
This enum represents the nesting behavior of the pass manager.
Definition: PassManager.h:55
@ Implicit
Implicit nesting behavior.
void dump()
Raw dump of the pass manager to llvm::errs().
Definition: Pass.cpp:371
llvm::pointee_iterator< MutableArrayRef< std::unique_ptr< Pass > >::iterator > pass_iterator
Iterator over the passes in this pass manager.
Definition: PassManager.h:82
llvm::pointee_iterator< ArrayRef< std::unique_ptr< Pass > >::const_iterator > const_pass_iterator
Definition: PassManager.h:88
void getDependentDialects(DialectRegistry &dialects) const
Register dependent dialects for the current pass manager.
Definition: Pass.cpp:383
StringRef getOpAnchorName() const
Return the name used to anchor this pass manager.
Definition: Pass.cpp:354
OpPassManager & nestAny()
Nest a new op-agnostic ("any") pass manager under this pass manager.
Definition: Pass.cpp:328
iterator_range< pass_iterator > getPasses()
Definition: PassManager.h:85
static StringRef getAnyOpAnchorName()
Return the string name used to anchor op-agnostic pass managers that operate generically on any viabl...
Definition: PassManager.h:143
Optional< StringRef > getOpName() const
Return the operation name that this pass manager operates on, or std::nullopt if this is an op-agnost...
Definition: Pass.cpp:345
void clear()
Clear the pipeline, but not the other options set on this OpPassManager.
Definition: Pass.cpp:336
pass_iterator begin()
Definition: Pass.cpp:306
pass_iterator end()
Definition: Pass.cpp:309
This class provides the API for ops that are known to be isolated from above.
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:31
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:147
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:154
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:165
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:50
Optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
Definition: Operation.h:54
bool isAncestor(Operation *other)
Return true if this operation is an ancestor of the other operation.
Definition: Operation.h:194
bool isProperAncestor(Operation *other)
Return true if this operation is a proper ancestor of the other operation.
Definition: Operation.cpp:176
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:512
virtual ~PassInstrumentation()=0
virtual void runBeforePipeline(Optional< OperationName > name, const PipelineParentInfo &parentInfo)
A callback to run before a pass pipeline is executed.
Definition: Pass.cpp:914
virtual void runAfterPipeline(Optional< OperationName > name, const PipelineParentInfo &parentInfo)
A callback to run after a pass pipeline has executed.
Definition: Pass.cpp:917
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.
Definition: Pass.cpp:972
void addInstrumentation(std::unique_ptr< PassInstrumentation > pi)
Add the given instrumentation to the collection.
Definition: Pass.cpp:995
void runBeforeAnalysis(StringRef name, TypeID id, Operation *op)
See PassInstrumentation::runBeforeAnalysis for details.
Definition: Pass.cpp:979
void runAfterPass(Pass *pass, Operation *op)
See PassInstrumentation::runAfterPass for details.
Definition: Pass.cpp:965
void runAfterPipeline(Optional< OperationName > name, const PassInstrumentation::PipelineParentInfo &parentInfo)
See PassInstrumentation::runAfterPipeline for details.
Definition: Pass.cpp:949
void runAfterAnalysis(StringRef name, TypeID id, Operation *op)
See PassInstrumentation::runAfterAnalysis for details.
Definition: Pass.cpp:987
void runBeforePass(Pass *pass, Operation *op)
See PassInstrumentation::runBeforePass for details.
Definition: Pass.cpp:958
void runBeforePipeline(Optional< OperationName > name, const PassInstrumentation::PipelineParentInfo &parentInfo)
See PassInstrumentation::runBeforePipeline for details.
Definition: Pass.cpp:940
MLIRContext * getContext() const
Return an instance of the context.
Definition: PassManager.h:230
LogicalResult run(Operation *op)
Run the passes within this manager on the provided operation.
Definition: Pass.cpp:778
void addInstrumentation(std::unique_ptr< PassInstrumentation > pi)
Add the provided instrumentation to the pass manager.
Definition: Pass.cpp:826
void enableVerifier(bool enabled=true)
Runs the verifier after each individual pass.
Definition: Pass.cpp:775
The abstract base pass class.
Definition: Pass.h:50
void copyOptionValuesFrom(const Pass *other)
Copy the option values from 'other', which is another instance of this pass.
Definition: Pass.cpp:48
void printAsTextualPipeline(raw_ostream &os)
Prints out the pass in the textual representation of pipelines.
Definition: Pass.cpp:54
virtual LogicalResult initializeOptions(StringRef options)
Attempt to initialize the options of this pass from the given string.
Definition: Pass.cpp:42
virtual void runOnOperation()=0
The polymorphic API that runs the pass over the currently held operation.
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
detail::ValueImpl * impl
A pointer to the internal implementation of the value.
Definition: Value.h:233
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.
Definition: PassDetail.h:23
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.
Include the generated interface declarations.
Definition: CallGraph.h:229
Detect if any of the given parameter types has a sub-element handler.
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
LogicalResult failableParallelForEach(MLIRContext *context, IteratorT begin, IteratorT end, FuncT &&func)
Invoke the given function on the elements between [begin, end) asynchronously.
Definition: Threading.h:36
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
Definition: Verifier.cpp:372
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
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.
Definition: Pass.cpp:880
void clear()
Clear the list of passes in this pass manager, other options are preserved.
Definition: Pass.cpp:201
OpPassManagerImpl(const OpPassManagerImpl &rhs)
Definition: Pass.cpp:89
std::string name
The name of the operation that passes of this pass manager operate on.
Definition: Pass.cpp:151
OpPassManager::Nesting nesting
Control the implicit nesting of passes that mismatch the name set for this OpPassManager.
Definition: Pass.cpp:166
void addPass(std::unique_ptr< Pass > pass)
Add the given pass to this pass manager.
Definition: Pass.cpp:184
OpPassManager & nest(StringRef nestedName)
Definition: Pass.cpp:108
unsigned initializationGeneration
The current initialization generation of this pass manager.
Definition: Pass.cpp:162
Optional< StringRef > getOpName() const
Definition: Pass.cpp:135
OpPassManagerImpl(OperationName opName, OpPassManager::Nesting nesting)
Definition: Pass.cpp:81
bool canScheduleOn(MLIRContext &context, OperationName opName)
Indicate if the current pass manager can be scheduled on the given operation type.
Definition: Pass.cpp:264
Optional< OperationName > opName
The cached OperationName (internalized in the context) for the name of the operation that passes of t...
Definition: Pass.cpp:155
OpPassManagerImpl(OpPassManager::Nesting nesting)
Definition: Pass.cpp:87
StringRef getOpAnchorName() const
Return the name used to anchor this pass manager.
Definition: Pass.cpp:142
Optional< OperationName > getOpName(MLIRContext &context)
Return the operation name of this pass manager.
Definition: Pass.cpp:130
OpPassManager & nestAny()
Definition: Pass.cpp:111
OpPassManager & nest(OperationName nestedName)
Nest a new operation pass manager for the given operation kind under this pass manager.
Definition: Pass.cpp:105
std::vector< std::unique_ptr< Pass > > passes
The set of passes to run as part of this pass manager.
Definition: Pass.cpp:158
void mergeInto(OpPassManagerImpl &rhs)
Merge the passes of this pass manager into the one provided.
Definition: Pass.cpp:171
LogicalResult finalizePassList(MLIRContext *ctx)
Finalize the pass list in preparation for execution.
Definition: Pass.cpp:203
OpPassManagerImpl(StringRef name, OpPassManager::Nesting nesting)
Definition: Pass.cpp:84
std::vector< std::unique_ptr< PassInstrumentation > > instrumentations
Set of registered instrumentations.
Definition: Pass.cpp:931
llvm::sys::SmartMutex< true > mutex
Mutex to keep instrumentation access thread-safe.
Definition: Pass.cpp:928