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