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