MLIR  14.0.0git
GreedyPatternRewriteDriver.cpp
Go to the documentation of this file.
1 //===- GreedyPatternRewriteDriver.cpp - A greedy rewriter -----------------===//
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 mlir::applyPatternsAndFoldGreedily.
10 //
11 //===----------------------------------------------------------------------===//
12 
18 #include "llvm/ADT/DenseMap.h"
19 #include "llvm/Support/CommandLine.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/ScopedPrinter.h"
22 #include "llvm/Support/raw_ostream.h"
23 
24 using namespace mlir;
25 
26 #define DEBUG_TYPE "greedy-rewriter"
27 
28 //===----------------------------------------------------------------------===//
29 // GreedyPatternRewriteDriver
30 //===----------------------------------------------------------------------===//
31 
32 namespace {
33 /// This is a worklist-driven driver for the PatternMatcher, which repeatedly
34 /// applies the locally optimal patterns in a roughly "bottom up" way.
35 class GreedyPatternRewriteDriver : public PatternRewriter {
36 public:
37  explicit GreedyPatternRewriteDriver(MLIRContext *ctx,
38  const FrozenRewritePatternSet &patterns,
39  const GreedyRewriteConfig &config);
40 
41  /// Simplify the operations within the given regions.
42  bool simplify(MutableArrayRef<Region> regions);
43 
44  /// Add the given operation to the worklist.
45  void addToWorklist(Operation *op);
46 
47  /// Pop the next operation from the worklist.
48  Operation *popFromWorklist();
49 
50  /// If the specified operation is in the worklist, remove it.
51  void removeFromWorklist(Operation *op);
52 
53 protected:
54  // Implement the hook for inserting operations, and make sure that newly
55  // inserted ops are added to the worklist for processing.
56  void notifyOperationInserted(Operation *op) override;
57 
58  // Look over the provided operands for any defining operations that should
59  // be re-added to the worklist. This function should be called when an
60  // operation is modified or removed, as it may trigger further
61  // simplifications.
62  template <typename Operands>
63  void addToWorklist(Operands &&operands);
64 
65  // If an operation is about to be removed, make sure it is not in our
66  // worklist anymore because we'd get dangling references to it.
67  void notifyOperationRemoved(Operation *op) override;
68 
69  // When the root of a pattern is about to be replaced, it can trigger
70  // simplifications to its users - make sure to add them to the worklist
71  // before the root is changed.
72  void notifyRootReplaced(Operation *op) override;
73 
74  /// PatternRewriter hook for erasing a dead operation.
75  void eraseOp(Operation *op) override;
76 
77  /// PatternRewriter hook for notifying match failure reasons.
79  notifyMatchFailure(Operation *op,
80  function_ref<void(Diagnostic &)> reasonCallback) override;
81 
82  /// The low-level pattern applicator.
83  PatternApplicator matcher;
84 
85  /// The worklist for this transformation keeps track of the operations that
86  /// need to be revisited, plus their index in the worklist. This allows us to
87  /// efficiently remove operations from the worklist when they are erased, even
88  /// if they aren't the root of a pattern.
89  std::vector<Operation *> worklist;
91 
92  /// Non-pattern based folder for operations.
93  OperationFolder folder;
94 
95 private:
96  /// Configuration information for how to simplify.
97  GreedyRewriteConfig config;
98 
99 #ifndef NDEBUG
100  /// A logger used to emit information during the application process.
101  llvm::ScopedPrinter logger{llvm::dbgs()};
102 #endif
103 };
104 } // namespace
105 
106 GreedyPatternRewriteDriver::GreedyPatternRewriteDriver(
107  MLIRContext *ctx, const FrozenRewritePatternSet &patterns,
108  const GreedyRewriteConfig &config)
109  : PatternRewriter(ctx), matcher(patterns), folder(ctx), config(config) {
110  worklist.reserve(64);
111 
112  // Apply a simple cost model based solely on pattern benefit.
113  matcher.applyDefaultCostModel();
114 }
115 
116 bool GreedyPatternRewriteDriver::simplify(MutableArrayRef<Region> regions) {
117 #ifndef NDEBUG
118  const char *logLineComment =
119  "//===-------------------------------------------===//\n";
120 
121  /// A utility function to log a process result for the given reason.
122  auto logResult = [&](StringRef result, const llvm::Twine &msg = {}) {
123  logger.unindent();
124  logger.startLine() << "} -> " << result;
125  if (!msg.isTriviallyEmpty())
126  logger.getOStream() << " : " << msg;
127  logger.getOStream() << "\n";
128  };
129  auto logResultWithLine = [&](StringRef result, const llvm::Twine &msg = {}) {
130  logResult(result, msg);
131  logger.startLine() << logLineComment;
132  };
133 #endif
134 
135  bool changed = false;
136  unsigned iteration = 0;
137  do {
138  worklist.clear();
139  worklistMap.clear();
140 
141  if (!config.useTopDownTraversal) {
142  // Add operations to the worklist in postorder.
143  for (auto &region : regions)
144  region.walk([this](Operation *op) { addToWorklist(op); });
145  } else {
146  // Add all nested operations to the worklist in preorder.
147  for (auto &region : regions)
148  region.walk<WalkOrder::PreOrder>(
149  [this](Operation *op) { worklist.push_back(op); });
150 
151  // Reverse the list so our pop-back loop processes them in-order.
152  std::reverse(worklist.begin(), worklist.end());
153  // Remember the reverse index.
154  for (size_t i = 0, e = worklist.size(); i != e; ++i)
155  worklistMap[worklist[i]] = i;
156  }
157 
158  // These are scratch vectors used in the folding loop below.
159  SmallVector<Value, 8> originalOperands, resultValues;
160 
161  changed = false;
162  while (!worklist.empty()) {
163  auto *op = popFromWorklist();
164 
165  // Nulls get added to the worklist when operations are removed, ignore
166  // them.
167  if (op == nullptr)
168  continue;
169 
170  LLVM_DEBUG({
171  logger.getOStream() << "\n";
172  logger.startLine() << logLineComment;
173  logger.startLine() << "Processing operation : '" << op->getName()
174  << "'(" << op << ") {\n";
175  logger.indent();
176 
177  // If the operation has no regions, just print it here.
178  if (op->getNumRegions() == 0) {
179  op->print(
180  logger.startLine(),
182  logger.getOStream() << "\n\n";
183  }
184  });
185 
186  // If the operation is trivially dead - remove it.
187  if (isOpTriviallyDead(op)) {
188  notifyOperationRemoved(op);
189  op->erase();
190  changed = true;
191 
192  LLVM_DEBUG(logResultWithLine("success", "operation is trivially dead"));
193  continue;
194  }
195 
196  // Collects all the operands and result uses of the given `op` into work
197  // list. Also remove `op` and nested ops from worklist.
198  originalOperands.assign(op->operand_begin(), op->operand_end());
199  auto preReplaceAction = [&](Operation *op) {
200  // Add the operands to the worklist for visitation.
201  addToWorklist(originalOperands);
202 
203  // Add all the users of the result to the worklist so we make sure
204  // to revisit them.
205  for (auto result : op->getResults())
206  for (auto *userOp : result.getUsers())
207  addToWorklist(userOp);
208 
209  notifyOperationRemoved(op);
210  };
211 
212  // Add the given operation to the worklist.
213  auto collectOps = [this](Operation *op) { addToWorklist(op); };
214 
215  // Try to fold this op.
216  bool inPlaceUpdate;
217  if ((succeeded(folder.tryToFold(op, collectOps, preReplaceAction,
218  &inPlaceUpdate)))) {
219  LLVM_DEBUG(logResultWithLine("success", "operation was folded"));
220 
221  changed = true;
222  if (!inPlaceUpdate)
223  continue;
224  }
225 
226  // Try to match one of the patterns. The rewriter is automatically
227  // notified of any necessary changes, so there is nothing else to do
228  // here.
229 #ifndef NDEBUG
230  auto canApply = [&](const Pattern &pattern) {
231  LLVM_DEBUG({
232  logger.getOStream() << "\n";
233  logger.startLine() << "* Pattern " << pattern.getDebugName() << " : '"
234  << op->getName() << " -> (";
235  llvm::interleaveComma(pattern.getGeneratedOps(), logger.getOStream());
236  logger.getOStream() << ")' {\n";
237  logger.indent();
238  });
239  return true;
240  };
241  auto onFailure = [&](const Pattern &pattern) {
242  LLVM_DEBUG(logResult("failure", "pattern failed to match"));
243  };
244  auto onSuccess = [&](const Pattern &pattern) {
245  LLVM_DEBUG(logResult("success", "pattern applied successfully"));
246  return success();
247  };
248 
249  LogicalResult matchResult =
250  matcher.matchAndRewrite(op, *this, canApply, onFailure, onSuccess);
251  if (succeeded(matchResult))
252  LLVM_DEBUG(logResultWithLine("success", "pattern matched"));
253  else
254  LLVM_DEBUG(logResultWithLine("failure", "pattern failed to match"));
255 #else
256  LogicalResult matchResult = matcher.matchAndRewrite(op, *this);
257 #endif
258  changed |= succeeded(matchResult);
259  }
260 
261  // After applying patterns, make sure that the CFG of each of the regions
262  // is kept up to date.
263  if (config.enableRegionSimplification)
264  changed |= succeeded(simplifyRegions(*this, regions));
265  } while (changed &&
266  (++iteration < config.maxIterations ||
268 
269  // Whether the rewrite converges, i.e. wasn't changed in the last iteration.
270  return !changed;
271 }
272 
273 void GreedyPatternRewriteDriver::addToWorklist(Operation *op) {
274  // Check to see if the worklist already contains this op.
275  if (worklistMap.count(op))
276  return;
277 
278  worklistMap[op] = worklist.size();
279  worklist.push_back(op);
280 }
281 
282 Operation *GreedyPatternRewriteDriver::popFromWorklist() {
283  auto *op = worklist.back();
284  worklist.pop_back();
285 
286  // This operation is no longer in the worklist, keep worklistMap up to date.
287  if (op)
288  worklistMap.erase(op);
289  return op;
290 }
291 
292 void GreedyPatternRewriteDriver::removeFromWorklist(Operation *op) {
293  auto it = worklistMap.find(op);
294  if (it != worklistMap.end()) {
295  assert(worklist[it->second] == op && "malformed worklist data structure");
296  worklist[it->second] = nullptr;
297  worklistMap.erase(it);
298  }
299 }
300 
301 void GreedyPatternRewriteDriver::notifyOperationInserted(Operation *op) {
302  LLVM_DEBUG({
303  logger.startLine() << "** Insert : '" << op->getName() << "'(" << op
304  << ")\n";
305  });
306  addToWorklist(op);
307 }
308 
309 template <typename Operands>
310 void GreedyPatternRewriteDriver::addToWorklist(Operands &&operands) {
311  for (Value operand : operands) {
312  // If the use count of this operand is now < 2, we re-add the defining
313  // operation to the worklist.
314  // TODO: This is based on the fact that zero use operations
315  // may be deleted, and that single use values often have more
316  // canonicalization opportunities.
317  if (!operand || (!operand.use_empty() && !operand.hasOneUse()))
318  continue;
319  if (auto *defOp = operand.getDefiningOp())
320  addToWorklist(defOp);
321  }
322 }
323 
324 void GreedyPatternRewriteDriver::notifyOperationRemoved(Operation *op) {
325  addToWorklist(op->getOperands());
326  op->walk([this](Operation *operation) {
327  removeFromWorklist(operation);
328  folder.notifyRemoval(operation);
329  });
330 }
331 
332 void GreedyPatternRewriteDriver::notifyRootReplaced(Operation *op) {
333  LLVM_DEBUG({
334  logger.startLine() << "** Replace : '" << op->getName() << "'(" << op
335  << ")\n";
336  });
337  for (auto result : op->getResults())
338  for (auto *user : result.getUsers())
339  addToWorklist(user);
340 }
341 
342 void GreedyPatternRewriteDriver::eraseOp(Operation *op) {
343  LLVM_DEBUG({
344  logger.startLine() << "** Erase : '" << op->getName() << "'(" << op
345  << ")\n";
346  });
348 }
349 
350 LogicalResult GreedyPatternRewriteDriver::notifyMatchFailure(
351  Operation *op, function_ref<void(Diagnostic &)> reasonCallback) {
352  LLVM_DEBUG({
354  reasonCallback(diag);
355  logger.startLine() << "** Failure : " << diag.str() << "\n";
356  });
357  return failure();
358 }
359 
360 /// Rewrite the regions of the specified operation, which must be isolated from
361 /// above, by repeatedly applying the highest benefit patterns in a greedy
362 /// work-list driven manner. Return success if no more patterns can be matched
363 /// in the result operation regions. Note: This does not apply patterns to the
364 /// top-level operation itself.
365 ///
368  const FrozenRewritePatternSet &patterns,
369  GreedyRewriteConfig config) {
370  if (regions.empty())
371  return success();
372 
373  // The top-level operation must be known to be isolated from above to
374  // prevent performing canonicalizations on operations defined at or above
375  // the region containing 'op'.
376  auto regionIsIsolated = [](Region &region) {
377  return region.getParentOp()->hasTrait<OpTrait::IsIsolatedFromAbove>();
378  };
379  (void)regionIsIsolated;
380  assert(llvm::all_of(regions, regionIsIsolated) &&
381  "patterns can only be applied to operations IsolatedFromAbove");
382 
383  // Start the pattern driver.
384  GreedyPatternRewriteDriver driver(regions[0].getContext(), patterns, config);
385  bool converged = driver.simplify(regions);
386  LLVM_DEBUG(if (!converged) {
387  llvm::dbgs() << "The pattern rewrite doesn't converge after scanning "
388  << config.maxIterations << " times\n";
389  });
390  return success(converged);
391 }
392 
393 //===----------------------------------------------------------------------===//
394 // OpPatternRewriteDriver
395 //===----------------------------------------------------------------------===//
396 
397 namespace {
398 /// This is a simple driver for the PatternMatcher to apply patterns and perform
399 /// folding on a single op. It repeatedly applies locally optimal patterns.
400 class OpPatternRewriteDriver : public PatternRewriter {
401 public:
402  explicit OpPatternRewriteDriver(MLIRContext *ctx,
403  const FrozenRewritePatternSet &patterns)
404  : PatternRewriter(ctx), matcher(patterns), folder(ctx) {
405  // Apply a simple cost model based solely on pattern benefit.
406  matcher.applyDefaultCostModel();
407  }
408 
409  LogicalResult simplifyLocally(Operation *op, int maxIterations, bool &erased);
410 
411  // These are hooks implemented for PatternRewriter.
412 protected:
413  /// If an operation is about to be removed, mark it so that we can let clients
414  /// know.
415  void notifyOperationRemoved(Operation *op) override {
416  opErasedViaPatternRewrites = true;
417  }
418 
419  // When a root is going to be replaced, its removal will be notified as well.
420  // So there is nothing to do here.
421  void notifyRootReplaced(Operation *op) override {}
422 
423 private:
424  /// The low-level pattern applicator.
425  PatternApplicator matcher;
426 
427  /// Non-pattern based folder for operations.
428  OperationFolder folder;
429 
430  /// Set to true if the operation has been erased via pattern rewrites.
431  bool opErasedViaPatternRewrites = false;
432 };
433 
434 } // namespace
435 
436 /// Performs the rewrites and folding only on `op`. The simplification
437 /// converges if the op is erased as a result of being folded, replaced, or
438 /// becoming dead, or no more changes happen in an iteration. Returns success if
439 /// the rewrite converges in `maxIterations`. `erased` is set to true if `op`
440 /// gets erased.
441 LogicalResult OpPatternRewriteDriver::simplifyLocally(Operation *op,
442  int maxIterations,
443  bool &erased) {
444  bool changed = false;
445  erased = false;
446  opErasedViaPatternRewrites = false;
447  int iterations = 0;
448  // Iterate until convergence or until maxIterations. Deletion of the op as
449  // a result of being dead or folded is convergence.
450  do {
451  changed = false;
452 
453  // If the operation is trivially dead - remove it.
454  if (isOpTriviallyDead(op)) {
455  op->erase();
456  erased = true;
457  return success();
458  }
459 
460  // Try to fold this op.
461  bool inPlaceUpdate;
462  if (succeeded(folder.tryToFold(op, /*processGeneratedConstants=*/nullptr,
463  /*preReplaceAction=*/nullptr,
464  &inPlaceUpdate))) {
465  changed = true;
466  if (!inPlaceUpdate) {
467  erased = true;
468  return success();
469  }
470  }
471 
472  // Try to match one of the patterns. The rewriter is automatically
473  // notified of any necessary changes, so there is nothing else to do here.
474  changed |= succeeded(matcher.matchAndRewrite(op, *this));
475  if ((erased = opErasedViaPatternRewrites))
476  return success();
477  } while (changed &&
478  (++iterations < maxIterations ||
479  maxIterations == GreedyRewriteConfig::kNoIterationLimit));
480 
481  // Whether the rewrite converges, i.e. wasn't changed in the last iteration.
482  return failure(changed);
483 }
484 
485 //===----------------------------------------------------------------------===//
486 // MultiOpPatternRewriteDriver
487 //===----------------------------------------------------------------------===//
488 
489 namespace {
490 
491 /// This is a specialized GreedyPatternRewriteDriver to apply patterns and
492 /// perform folding for a supplied set of ops. It repeatedly simplifies while
493 /// restricting the rewrites to only the provided set of ops or optionally
494 /// to those directly affected by it (result users or operand providers).
495 class MultiOpPatternRewriteDriver : public GreedyPatternRewriteDriver {
496 public:
497  explicit MultiOpPatternRewriteDriver(MLIRContext *ctx,
498  const FrozenRewritePatternSet &patterns,
499  bool strict)
500  : GreedyPatternRewriteDriver(ctx, patterns, GreedyRewriteConfig()),
501  strictMode(strict) {}
502 
503  bool simplifyLocally(ArrayRef<Operation *> op);
504 
505 private:
506  // Look over the provided operands for any defining operations that should
507  // be re-added to the worklist. This function should be called when an
508  // operation is modified or removed, as it may trigger further
509  // simplifications. If `strict` is set to true, only ops in
510  // `strictModeFilteredOps` are considered.
511  template <typename Operands>
512  void addOperandsToWorklist(Operands &&operands) {
513  for (Value operand : operands) {
514  if (auto *defOp = operand.getDefiningOp()) {
515  if (!strictMode || strictModeFilteredOps.contains(defOp))
516  addToWorklist(defOp);
517  }
518  }
519  }
520 
521  void notifyOperationRemoved(Operation *op) override {
522  GreedyPatternRewriteDriver::notifyOperationRemoved(op);
523  if (strictMode)
524  strictModeFilteredOps.erase(op);
525  }
526 
527  /// If `strictMode` is true, any pre-existing ops outside of
528  /// `strictModeFilteredOps` remain completely untouched by the rewrite driver.
529  /// If `strictMode` is false, operations that use results of (or supply
530  /// operands to) any rewritten ops stemming from the simplification of the
531  /// provided ops are in turn simplified; any other ops still remain untouched
532  /// (i.e., regardless of `strictMode`).
533  bool strictMode = false;
534 
535  /// The list of ops we are restricting our rewrites to if `strictMode` is on.
536  /// These include the supplied set of ops as well as new ops created while
537  /// rewriting those ops. This set is not maintained when strictMode is off.
538  llvm::SmallDenseSet<Operation *, 4> strictModeFilteredOps;
539 };
540 
541 } // namespace
542 
543 /// Performs the specified rewrites on `ops` while also trying to fold these ops
544 /// as well as any other ops that were in turn created due to these rewrite
545 /// patterns. Any pre-existing ops outside of `ops` remain completely
546 /// unmodified if `strictMode` is true. If `strictMode` is false, other
547 /// operations that use results of rewritten ops or supply operands to such ops
548 /// are in turn simplified; any other ops still remain unmodified (i.e.,
549 /// regardless of `strictMode`). Note that ops in `ops` could be erased as a
550 /// result of folding, becoming dead, or via pattern rewrites. Returns true if
551 /// at all any changes happened.
552 // Unlike `OpPatternRewriteDriver::simplifyLocally` which works on a single op
553 // or GreedyPatternRewriteDriver::simplify, this method just iterates until
554 // the worklist is empty. As our objective is to keep simplification "local",
555 // there is no strong rationale to re-add all operations into the worklist and
556 // rerun until an iteration changes nothing. If more widereaching simplification
557 // is desired, GreedyPatternRewriteDriver should be used.
558 bool MultiOpPatternRewriteDriver::simplifyLocally(ArrayRef<Operation *> ops) {
559  if (strictMode) {
560  strictModeFilteredOps.clear();
561  strictModeFilteredOps.insert(ops.begin(), ops.end());
562  }
563 
564  bool changed = false;
565  worklist.clear();
566  worklistMap.clear();
567  for (Operation *op : ops)
568  addToWorklist(op);
569 
570  // These are scratch vectors used in the folding loop below.
571  SmallVector<Value, 8> originalOperands, resultValues;
572  while (!worklist.empty()) {
573  Operation *op = popFromWorklist();
574 
575  // Nulls get added to the worklist when operations are removed, ignore
576  // them.
577  if (op == nullptr)
578  continue;
579 
580  // If the operation is trivially dead - remove it.
581  if (isOpTriviallyDead(op)) {
582  notifyOperationRemoved(op);
583  op->erase();
584  changed = true;
585  continue;
586  }
587 
588  // Collects all the operands and result uses of the given `op` into work
589  // list. Also remove `op` and nested ops from worklist.
590  originalOperands.assign(op->operand_begin(), op->operand_end());
591  auto preReplaceAction = [&](Operation *op) {
592  // Add the operands to the worklist for visitation.
593  addOperandsToWorklist(originalOperands);
594 
595  // Add all the users of the result to the worklist so we make sure
596  // to revisit them.
597  for (Value result : op->getResults())
598  for (Operation *userOp : result.getUsers()) {
599  if (!strictMode || strictModeFilteredOps.contains(userOp))
600  addToWorklist(userOp);
601  }
602  notifyOperationRemoved(op);
603  };
604 
605  // Add the given operation generated by the folder to the worklist.
606  auto processGeneratedConstants = [this](Operation *op) {
607  // Newly created ops are also simplified -- these are also "local".
608  addToWorklist(op);
609  // When strict mode is off, we don't need to maintain
610  // strictModeFilteredOps.
611  if (strictMode)
612  strictModeFilteredOps.insert(op);
613  };
614 
615  // Try to fold this op.
616  bool inPlaceUpdate;
617  if (succeeded(folder.tryToFold(op, processGeneratedConstants,
618  preReplaceAction, &inPlaceUpdate))) {
619  changed = true;
620  if (!inPlaceUpdate) {
621  // Op has been erased.
622  continue;
623  }
624  }
625 
626  // Try to match one of the patterns. The rewriter is automatically
627  // notified of any necessary changes, so there is nothing else to do
628  // here.
629  changed |= succeeded(matcher.matchAndRewrite(op, *this));
630  }
631 
632  return changed;
633 }
634 
635 /// Rewrites only `op` using the supplied canonicalization patterns and
636 /// folding. `erased` is set to true if the op is erased as a result of being
637 /// folded, replaced, or dead.
639  Operation *op, const FrozenRewritePatternSet &patterns, bool *erased) {
640  // Start the pattern driver.
641  GreedyRewriteConfig config;
642  OpPatternRewriteDriver driver(op->getContext(), patterns);
643  bool opErased;
644  LogicalResult converged =
645  driver.simplifyLocally(op, config.maxIterations, opErased);
646  if (erased)
647  *erased = opErased;
648  LLVM_DEBUG(if (failed(converged)) {
649  llvm::dbgs() << "The pattern rewrite doesn't converge after scanning "
650  << config.maxIterations << " times";
651  });
652  return converged;
653 }
654 
656  const FrozenRewritePatternSet &patterns,
657  bool strict) {
658  if (ops.empty())
659  return false;
660 
661  // Start the pattern driver.
662  MultiOpPatternRewriteDriver driver(ops.front()->getContext(), patterns,
663  strict);
664  return driver.simplifyLocally(ops);
665 }
Include the generated interface declarations.
This class contains a list of basic blocks and a link to the parent operation it is attached to...
Definition: Region.h:26
static std::string diag(llvm::Value &v)
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
Definition: PatternMatch.h:881
bool isOpTriviallyDead(Operation *op)
Return true if the given operation is unused, and has no side effects on memory that prevent erasing...
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
operand_range getOperands()
Returns an iterator on the underlying Value&#39;s.
Definition: Operation.h:247
This class represents a frozen set of patterns that can be processed by a pattern applicator...
LogicalResult applyOpPatternsAndFold(Operation *op, const FrozenRewritePatternSet &patterns, bool *erased=nullptr)
Applies the specified patterns on op alone while also trying to fold it, by selecting the highest ben...
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
This class allows control over how the GreedyPatternRewriteDriver works.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value...
Definition: LogicalResult.h:68
bool useTopDownTraversal
This specifies the order of initial traversal that populates the rewriters worklist.
void erase()
Remove this operation from its parent block and delete it.
Definition: Operation.cpp:424
This class contains all of the data related to a pattern, but does not contain any methods or logic f...
Definition: PatternMatch.h:71
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:99
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
std::enable_if< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT >::type walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one)...
Definition: Operation.h:515
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine...
Definition: Diagnostics.h:157
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
OpPrintingFlags & printGenericOpForm()
Always print operations in the generic form.
Definition: AsmPrinter.cpp:194
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:106
int64_t maxIterations
This specifies the maximum number of times the rewriter will iterate between applying patterns and si...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:84
A utility class for folding operations, and unifying duplicated constants generated along the way...
Definition: FoldUtils.h:32
static constexpr int64_t kNoIterationLimit
operand_iterator operand_begin()
Definition: Operation.h:243
Set of flags used to control the behavior of the various IR print methods (e.g.
OpPrintingFlags & elideLargeElementsAttrs(int64_t largeElementLimit=16)
Enables the elision of large elements attributes by printing a lexically valid but otherwise meaningl...
Definition: AsmPrinter.cpp:180
LogicalResult simplifyRegions(RewriterBase &rewriter, MutableArrayRef< Region > regions)
Run a set of structural simplifications over the given regions.
This class provides the API for ops that are known to be isolated from above.
This class manages the application of a group of rewrite patterns, with a user-provided cost model...
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
operand_iterator operand_end()
Definition: Operation.h:244
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:57
user_range getUsers()
Returns a range of all users.
Definition: Operation.h:591
LogicalResult applyPatternsAndFoldGreedily(MutableArrayRef< Region > regions, const FrozenRewritePatternSet &patterns, GreedyRewriteConfig config=GreedyRewriteConfig())
Rewrite the regions of the specified operation, which must be isolated from above, by repeatedly applying the highest benefit patterns in a greedy work-list driven manner.
result_range getResults()
Definition: Operation.h:284