MLIR  14.0.0git
Operation.cpp
Go to the documentation of this file.
1 //===- Operation.cpp - Operation support code -----------------------------===//
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 #include "mlir/IR/Operation.h"
11 #include "mlir/IR/BuiltinTypes.h"
12 #include "mlir/IR/Dialect.h"
14 #include "mlir/IR/PatternMatch.h"
15 #include "mlir/IR/TypeUtilities.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include <numeric>
19 
20 using namespace mlir;
21 
22 //===----------------------------------------------------------------------===//
23 // Operation
24 //===----------------------------------------------------------------------===//
25 
26 /// Create a new Operation with the specific fields.
28  TypeRange resultTypes, ValueRange operands,
29  ArrayRef<NamedAttribute> attributes,
30  BlockRange successors, unsigned numRegions) {
31  return create(location, name, resultTypes, operands,
32  DictionaryAttr::get(location.getContext(), attributes),
33  successors, numRegions);
34 }
35 
36 /// Create a new Operation from operation state.
38  return create(state.location, state.name, state.types, state.operands,
39  state.attributes.getDictionary(state.getContext()),
40  state.successors, state.regions);
41 }
42 
43 /// Create a new Operation with the specific fields.
45  TypeRange resultTypes, ValueRange operands,
46  DictionaryAttr attributes, BlockRange successors,
47  RegionRange regions) {
48  unsigned numRegions = regions.size();
49  Operation *op = create(location, name, resultTypes, operands, attributes,
50  successors, numRegions);
51  for (unsigned i = 0; i < numRegions; ++i)
52  if (regions[i])
53  op->getRegion(i).takeBody(*regions[i]);
54  return op;
55 }
56 
57 /// Overload of create that takes an existing DictionaryAttr to avoid
58 /// unnecessarily uniquing a list of attributes.
60  TypeRange resultTypes, ValueRange operands,
61  DictionaryAttr attributes, BlockRange successors,
62  unsigned numRegions) {
63  assert(llvm::all_of(resultTypes, [](Type t) { return t; }) &&
64  "unexpected null result type");
65 
66  // We only need to allocate additional memory for a subset of results.
67  unsigned numTrailingResults = OpResult::getNumTrailing(resultTypes.size());
68  unsigned numInlineResults = OpResult::getNumInline(resultTypes.size());
69  unsigned numSuccessors = successors.size();
70  unsigned numOperands = operands.size();
71  unsigned numResults = resultTypes.size();
72 
73  // If the operation is known to have no operands, don't allocate an operand
74  // storage.
75  bool needsOperandStorage =
76  operands.empty() ? !name.hasTrait<OpTrait::ZeroOperands>() : true;
77 
78  // Compute the byte size for the operation and the operand storage. This takes
79  // into account the size of the operation, its trailing objects, and its
80  // prefixed objects.
81  size_t byteSize =
82  totalSizeToAlloc<detail::OperandStorage, BlockOperand, Region, OpOperand>(
83  needsOperandStorage ? 1 : 0, numSuccessors, numRegions, numOperands);
84  size_t prefixByteSize = llvm::alignTo(
85  Operation::prefixAllocSize(numTrailingResults, numInlineResults),
86  alignof(Operation));
87  char *mallocMem = reinterpret_cast<char *>(malloc(byteSize + prefixByteSize));
88  void *rawMem = mallocMem + prefixByteSize;
89 
90  // Create the new Operation.
91  Operation *op =
92  ::new (rawMem) Operation(location, name, numResults, numSuccessors,
93  numRegions, attributes, needsOperandStorage);
94 
95  assert((numSuccessors == 0 || op->mightHaveTrait<OpTrait::IsTerminator>()) &&
96  "unexpected successors in a non-terminator operation");
97 
98  // Initialize the results.
99  auto resultTypeIt = resultTypes.begin();
100  for (unsigned i = 0; i < numInlineResults; ++i, ++resultTypeIt)
101  new (op->getInlineOpResult(i)) detail::InlineOpResult(*resultTypeIt, i);
102  for (unsigned i = 0; i < numTrailingResults; ++i, ++resultTypeIt) {
103  new (op->getOutOfLineOpResult(i))
104  detail::OutOfLineOpResult(*resultTypeIt, i);
105  }
106 
107  // Initialize the regions.
108  for (unsigned i = 0; i != numRegions; ++i)
109  new (&op->getRegion(i)) Region(op);
110 
111  // Initialize the operands.
112  if (needsOperandStorage) {
113  new (&op->getOperandStorage()) detail::OperandStorage(
114  op, op->getTrailingObjects<OpOperand>(), operands);
115  }
116 
117  // Initialize the successors.
118  auto blockOperands = op->getBlockOperands();
119  for (unsigned i = 0; i != numSuccessors; ++i)
120  new (&blockOperands[i]) BlockOperand(op, successors[i]);
121 
122  return op;
123 }
124 
125 Operation::Operation(Location location, OperationName name, unsigned numResults,
126  unsigned numSuccessors, unsigned numRegions,
127  DictionaryAttr attributes, bool hasOperandStorage)
128  : location(location), numResults(numResults), numSuccs(numSuccessors),
129  numRegions(numRegions), hasOperandStorage(hasOperandStorage), name(name),
130  attrs(attributes) {
131  assert(attributes && "unexpected null attribute dictionary");
132 #ifndef NDEBUG
133  if (!getDialect() && !getContext()->allowsUnregisteredDialects())
134  llvm::report_fatal_error(
135  name.getStringRef() +
136  " created with unregistered dialect. If this is intended, please call "
137  "allowUnregisteredDialects() on the MLIRContext, or use "
138  "-allow-unregistered-dialect with the MLIR tool used.");
139 #endif
140 }
141 
142 // Operations are deleted through the destroy() member because they are
143 // allocated via malloc.
144 Operation::~Operation() {
145  assert(block == nullptr && "operation destroyed but still in a block");
146 #ifndef NDEBUG
147  if (!use_empty()) {
148  {
150  emitOpError("operation destroyed but still has uses");
151  for (Operation *user : getUsers())
152  diag.attachNote(user->getLoc()) << "- use: " << *user << "\n";
153  }
154  llvm::report_fatal_error("operation destroyed but still has uses");
155  }
156 #endif
157  // Explicitly run the destructors for the operands.
158  if (hasOperandStorage)
159  getOperandStorage().~OperandStorage();
160 
161  // Explicitly run the destructors for the successors.
162  for (auto &successor : getBlockOperands())
163  successor.~BlockOperand();
164 
165  // Explicitly destroy the regions.
166  for (auto &region : getRegions())
167  region.~Region();
168 }
169 
170 /// Destroy this operation or one of its subclasses.
172  // Operations may have additional prefixed allocation, which needs to be
173  // accounted for here when computing the address to free.
174  char *rawMem = reinterpret_cast<char *>(this) -
175  llvm::alignTo(prefixAllocSize(), alignof(Operation));
176  this->~Operation();
177  free(rawMem);
178 }
179 
180 /// Return true if this operation is a proper ancestor of the `other`
181 /// operation.
183  while ((other = other->getParentOp()))
184  if (this == other)
185  return true;
186  return false;
187 }
188 
189 /// Replace any uses of 'from' with 'to' within this operation.
191  if (from == to)
192  return;
193  for (auto &operand : getOpOperands())
194  if (operand.get() == from)
195  operand.set(to);
196 }
197 
198 /// Replace the current operands of this operation with the ones provided in
199 /// 'operands'.
201  if (LLVM_LIKELY(hasOperandStorage))
202  return getOperandStorage().setOperands(this, operands);
203  assert(operands.empty() && "setting operands without an operand storage");
204 }
205 
206 /// Replace the operands beginning at 'start' and ending at 'start' + 'length'
207 /// with the ones provided in 'operands'. 'operands' may be smaller or larger
208 /// than the range pointed to by 'start'+'length'.
209 void Operation::setOperands(unsigned start, unsigned length,
210  ValueRange operands) {
211  assert((start + length) <= getNumOperands() &&
212  "invalid operand range specified");
213  if (LLVM_LIKELY(hasOperandStorage))
214  return getOperandStorage().setOperands(this, start, length, operands);
215  assert(operands.empty() && "setting operands without an operand storage");
216 }
217 
218 /// Insert the given operands into the operand list at the given 'index'.
219 void Operation::insertOperands(unsigned index, ValueRange operands) {
220  if (LLVM_LIKELY(hasOperandStorage))
221  return setOperands(index, /*length=*/0, operands);
222  assert(operands.empty() && "inserting operands without an operand storage");
223 }
224 
225 //===----------------------------------------------------------------------===//
226 // Diagnostics
227 //===----------------------------------------------------------------------===//
228 
229 /// Emit an error about fatal conditions with this operation, reporting up to
230 /// any diagnostic handlers that may be listening.
233  if (getContext()->shouldPrintOpOnDiagnostic()) {
234  diag.attachNote(getLoc())
235  .append("see current operation: ")
236  .appendOp(*this, OpPrintingFlags().printGenericOpForm());
237  }
238  return diag;
239 }
240 
241 /// Emit a warning about this operation, reporting up to any diagnostic
242 /// handlers that may be listening.
245  if (getContext()->shouldPrintOpOnDiagnostic())
246  diag.attachNote(getLoc()) << "see current operation: " << *this;
247  return diag;
248 }
249 
250 /// Emit a remark about this operation, reporting up to any diagnostic
251 /// handlers that may be listening.
254  if (getContext()->shouldPrintOpOnDiagnostic())
255  diag.attachNote(getLoc()) << "see current operation: " << *this;
256  return diag;
257 }
258 
259 //===----------------------------------------------------------------------===//
260 // Operation Ordering
261 //===----------------------------------------------------------------------===//
262 
263 constexpr unsigned Operation::kInvalidOrderIdx;
264 constexpr unsigned Operation::kOrderStride;
265 
266 /// Given an operation 'other' that is within the same parent block, return
267 /// whether the current operation is before 'other' in the operation list
268 /// of the parent block.
269 /// Note: This function has an average complexity of O(1), but worst case may
270 /// take O(N) where N is the number of operations within the parent block.
272  assert(block && "Operations without parent blocks have no order.");
273  assert(other && other->block == block &&
274  "Expected other operation to have the same parent block.");
275  // If the order of the block is already invalid, directly recompute the
276  // parent.
277  if (!block->isOpOrderValid()) {
278  block->recomputeOpOrder();
279  } else {
280  // Update the order either operation if necessary.
281  updateOrderIfNecessary();
282  other->updateOrderIfNecessary();
283  }
284 
285  return orderIndex < other->orderIndex;
286 }
287 
288 /// Update the order index of this operation of this operation if necessary,
289 /// potentially recomputing the order of the parent block.
290 void Operation::updateOrderIfNecessary() {
291  assert(block && "expected valid parent");
292 
293  // If the order is valid for this operation there is nothing to do.
294  if (hasValidOrder())
295  return;
296  Operation *blockFront = &block->front();
297  Operation *blockBack = &block->back();
298 
299  // This method is expected to only be invoked on blocks with more than one
300  // operation.
301  assert(blockFront != blockBack && "expected more than one operation");
302 
303  // If the operation is at the end of the block.
304  if (this == blockBack) {
305  Operation *prevNode = getPrevNode();
306  if (!prevNode->hasValidOrder())
307  return block->recomputeOpOrder();
308 
309  // Add the stride to the previous operation.
310  orderIndex = prevNode->orderIndex + kOrderStride;
311  return;
312  }
313 
314  // If this is the first operation try to use the next operation to compute the
315  // ordering.
316  if (this == blockFront) {
317  Operation *nextNode = getNextNode();
318  if (!nextNode->hasValidOrder())
319  return block->recomputeOpOrder();
320  // There is no order to give this operation.
321  if (nextNode->orderIndex == 0)
322  return block->recomputeOpOrder();
323 
324  // If we can't use the stride, just take the middle value left. This is safe
325  // because we know there is at least one valid index to assign to.
326  if (nextNode->orderIndex <= kOrderStride)
327  orderIndex = (nextNode->orderIndex / 2);
328  else
329  orderIndex = kOrderStride;
330  return;
331  }
332 
333  // Otherwise, this operation is between two others. Place this operation in
334  // the middle of the previous and next if possible.
335  Operation *prevNode = getPrevNode(), *nextNode = getNextNode();
336  if (!prevNode->hasValidOrder() || !nextNode->hasValidOrder())
337  return block->recomputeOpOrder();
338  unsigned prevOrder = prevNode->orderIndex, nextOrder = nextNode->orderIndex;
339 
340  // Check to see if there is a valid order between the two.
341  if (prevOrder + 1 == nextOrder)
342  return block->recomputeOpOrder();
343  orderIndex = prevOrder + ((nextOrder - prevOrder) / 2);
344 }
345 
346 //===----------------------------------------------------------------------===//
347 // ilist_traits for Operation
348 //===----------------------------------------------------------------------===//
349 
350 auto llvm::ilist_detail::SpecificNodeAccess<
351  typename llvm::ilist_detail::compute_node_options<
352  ::mlir::Operation>::type>::getNodePtr(pointer n) -> node_type * {
353  return NodeAccess::getNodePtr<OptionsT>(n);
354 }
355 
356 auto llvm::ilist_detail::SpecificNodeAccess<
357  typename llvm::ilist_detail::compute_node_options<
358  ::mlir::Operation>::type>::getNodePtr(const_pointer n)
359  -> const node_type * {
360  return NodeAccess::getNodePtr<OptionsT>(n);
361 }
362 
363 auto llvm::ilist_detail::SpecificNodeAccess<
364  typename llvm::ilist_detail::compute_node_options<
365  ::mlir::Operation>::type>::getValuePtr(node_type *n) -> pointer {
366  return NodeAccess::getValuePtr<OptionsT>(n);
367 }
368 
369 auto llvm::ilist_detail::SpecificNodeAccess<
370  typename llvm::ilist_detail::compute_node_options<
371  ::mlir::Operation>::type>::getValuePtr(const node_type *n)
372  -> const_pointer {
373  return NodeAccess::getValuePtr<OptionsT>(n);
374 }
375 
377  op->destroy();
378 }
379 
380 Block *llvm::ilist_traits<::mlir::Operation>::getContainingBlock() {
381  size_t offset(size_t(&((Block *)nullptr->*Block::getSublistAccess(nullptr))));
382  iplist<Operation> *anchor(static_cast<iplist<Operation> *>(this));
383  return reinterpret_cast<Block *>(reinterpret_cast<char *>(anchor) - offset);
384 }
385 
386 /// This is a trait method invoked when an operation is added to a block. We
387 /// keep the block pointer up to date.
389  assert(!op->getBlock() && "already in an operation block!");
390  op->block = getContainingBlock();
391 
392  // Invalidate the order on the operation.
393  op->orderIndex = Operation::kInvalidOrderIdx;
394 }
395 
396 /// This is a trait method invoked when an operation is removed from a block.
397 /// We keep the block pointer up to date.
399  assert(op->block && "not already in an operation block!");
400  op->block = nullptr;
401 }
402 
403 /// This is a trait method invoked when an operation is moved from one block
404 /// to another. We keep the block pointer up to date.
406  ilist_traits<Operation> &otherList, op_iterator first, op_iterator last) {
407  Block *curParent = getContainingBlock();
408 
409  // Invalidate the ordering of the parent block.
410  curParent->invalidateOpOrder();
411 
412  // If we are transferring operations within the same block, the block
413  // pointer doesn't need to be updated.
414  if (curParent == otherList.getContainingBlock())
415  return;
416 
417  // Update the 'block' member of each operation.
418  for (; first != last; ++first)
419  first->block = curParent;
420 }
421 
422 /// Remove this operation (and its descendants) from its Block and delete
423 /// all of them.
425  if (auto *parent = getBlock())
426  parent->getOperations().erase(this);
427  else
428  destroy();
429 }
430 
431 /// Remove the operation from its parent block, but don't delete it.
433  if (Block *parent = getBlock())
434  parent->getOperations().remove(this);
435 }
436 
437 /// Unlink this operation from its current block and insert it right before
438 /// `existingOp` which may be in the same or another block in the same
439 /// function.
440 void Operation::moveBefore(Operation *existingOp) {
441  moveBefore(existingOp->getBlock(), existingOp->getIterator());
442 }
443 
444 /// Unlink this operation from its current basic block and insert it right
445 /// before `iterator` in the specified basic block.
447  llvm::iplist<Operation>::iterator iterator) {
448  block->getOperations().splice(iterator, getBlock()->getOperations(),
449  getIterator());
450 }
451 
452 /// Unlink this operation from its current block and insert it right after
453 /// `existingOp` which may be in the same or another block in the same function.
454 void Operation::moveAfter(Operation *existingOp) {
455  moveAfter(existingOp->getBlock(), existingOp->getIterator());
456 }
457 
458 /// Unlink this operation from its current block and insert it right after
459 /// `iterator` in the specified block.
461  llvm::iplist<Operation>::iterator iterator) {
462  assert(iterator != block->end() && "cannot move after end of block");
463  moveBefore(block, std::next(iterator));
464 }
465 
466 /// This drops all operand uses from this operation, which is an essential
467 /// step in breaking cyclic dependences between references when they are to
468 /// be deleted.
470  for (auto &op : getOpOperands())
471  op.drop();
472 
473  for (auto &region : getRegions())
474  region.dropAllReferences();
475 
476  for (auto &dest : getBlockOperands())
477  dest.drop();
478 }
479 
480 /// This drops all uses of any values defined by this operation or its nested
481 /// regions, wherever they are located.
483  dropAllUses();
484 
485  for (auto &region : getRegions())
486  for (auto &block : region)
487  block.dropAllDefinedValueUses();
488 }
489 
490 void Operation::setSuccessor(Block *block, unsigned index) {
491  assert(index < getNumSuccessors());
492  getBlockOperands()[index].set(block);
493 }
494 
495 /// Attempt to fold this operation using the Op's registered foldHook.
498  // If we have a registered operation definition matching this one, use it to
499  // try to constant fold the operation.
501  if (info && succeeded(info->foldHook(this, operands, results)))
502  return success();
503 
504  // Otherwise, fall back on the dialect hook to handle it.
505  Dialect *dialect = getDialect();
506  if (!dialect)
507  return failure();
508 
509  auto *interface = dialect->getRegisteredInterface<DialectFoldInterface>();
510  if (!interface)
511  return failure();
512 
513  return interface->fold(this, operands, results);
514 }
515 
516 /// Emit an error with the op name prefixed, like "'dim' op " which is
517 /// convenient for verifiers.
519  return emitError() << "'" << getName() << "' op " << message;
520 }
521 
522 //===----------------------------------------------------------------------===//
523 // Operation Cloning
524 //===----------------------------------------------------------------------===//
525 
526 /// Create a deep copy of this operation but keep the operation regions empty.
527 /// Operands are remapped using `mapper` (if present), and `mapper` is updated
528 /// to contain the results.
530  SmallVector<Value, 8> operands;
531  SmallVector<Block *, 2> successors;
532 
533  // Remap the operands.
534  operands.reserve(getNumOperands());
535  for (auto opValue : getOperands())
536  operands.push_back(mapper.lookupOrDefault(opValue));
537 
538  // Remap the successors.
539  successors.reserve(getNumSuccessors());
540  for (Block *successor : getSuccessors())
541  successors.push_back(mapper.lookupOrDefault(successor));
542 
543  // Create the new operation.
544  auto *newOp = create(getLoc(), getName(), getResultTypes(), operands, attrs,
545  successors, getNumRegions());
546 
547  // Remember the mapping of any results.
548  for (unsigned i = 0, e = getNumResults(); i != e; ++i)
549  mapper.map(getResult(i), newOp->getResult(i));
550 
551  return newOp;
552 }
553 
555  BlockAndValueMapping mapper;
556  return cloneWithoutRegions(mapper);
557 }
558 
559 /// Create a deep copy of this operation, remapping any operands that use
560 /// values outside of the operation using the map that is provided (leaving
561 /// them alone if no entry is present). Replaces references to cloned
562 /// sub-operations to the corresponding operation that is copied, and adds
563 /// those mappings to the map.
565  auto *newOp = cloneWithoutRegions(mapper);
566 
567  // Clone the regions.
568  for (unsigned i = 0; i != numRegions; ++i)
569  getRegion(i).cloneInto(&newOp->getRegion(i), mapper);
570 
571  return newOp;
572 }
573 
575  BlockAndValueMapping mapper;
576  return clone(mapper);
577 }
578 
579 //===----------------------------------------------------------------------===//
580 // OpState trait class.
581 //===----------------------------------------------------------------------===//
582 
583 // The fallback for the parser is to try for a dialect operation parser.
584 // Otherwise, reject the custom assembly form.
586  if (auto parseFn = result.name.getDialect()->getParseOperationHook(
587  result.name.getStringRef()))
588  return (*parseFn)(parser, result);
589  return parser.emitError(parser.getNameLoc(), "has no custom assembly form");
590 }
591 
592 // The fallback for the printer is to try for a dialect operation printer.
593 // Otherwise, it prints the generic form.
594 void OpState::print(Operation *op, OpAsmPrinter &p, StringRef defaultDialect) {
595  if (auto printFn = op->getDialect()->getOperationPrinter(op)) {
596  printOpName(op, p, defaultDialect);
597  printFn(op, p);
598  } else {
599  p.printGenericOp(op);
600  }
601 }
602 
603 /// Print an operation name, eliding the dialect prefix if necessary.
605  StringRef defaultDialect) {
606  StringRef name = op->getName().getStringRef();
607  if (name.startswith((defaultDialect + ".").str()))
608  name = name.drop_front(defaultDialect.size() + 1);
609  // TODO: remove this special case (and update test/IR/parser.mlir)
610  else if ((defaultDialect.empty() || defaultDialect == "builtin") &&
611  name.startswith("std."))
612  name = name.drop_front(4);
613  p.getStream() << name;
614 }
615 
616 /// Emit an error about fatal conditions with this operation, reporting up to
617 /// any diagnostic handlers that may be listening.
618 InFlightDiagnostic OpState::emitError(const Twine &message) {
619  return getOperation()->emitError(message);
620 }
621 
622 /// Emit an error with the op name prefixed, like "'dim' op " which is
623 /// convenient for verifiers.
625  return getOperation()->emitOpError(message);
626 }
627 
628 /// Emit a warning about this operation, reporting up to any diagnostic
629 /// handlers that may be listening.
631  return getOperation()->emitWarning(message);
632 }
633 
634 /// Emit a remark about this operation, reporting up to any diagnostic
635 /// handlers that may be listening.
637  return getOperation()->emitRemark(message);
638 }
639 
640 //===----------------------------------------------------------------------===//
641 // Op Trait implementations
642 //===----------------------------------------------------------------------===//
643 
645  if (op->getNumOperands() == 1) {
646  auto *argumentOp = op->getOperand(0).getDefiningOp();
647  if (argumentOp && op->getName() == argumentOp->getName()) {
648  // Replace the outer operation output with the inner operation.
649  return op->getOperand(0);
650  }
651  } else if (op->getOperand(0) == op->getOperand(1)) {
652  return op->getOperand(0);
653  }
654 
655  return {};
656 }
657 
659  auto *argumentOp = op->getOperand(0).getDefiningOp();
660  if (argumentOp && op->getName() == argumentOp->getName()) {
661  // Replace the outer involutions output with inner's input.
662  return argumentOp->getOperand(0);
663  }
664 
665  return {};
666 }
667 
669  if (op->getNumOperands() != 0)
670  return op->emitOpError() << "requires zero operands";
671  return success();
672 }
673 
675  if (op->getNumOperands() != 1)
676  return op->emitOpError() << "requires a single operand";
677  return success();
678 }
679 
681  unsigned numOperands) {
682  if (op->getNumOperands() != numOperands) {
683  return op->emitOpError() << "expected " << numOperands
684  << " operands, but found " << op->getNumOperands();
685  }
686  return success();
687 }
688 
690  unsigned numOperands) {
691  if (op->getNumOperands() < numOperands)
692  return op->emitOpError()
693  << "expected " << numOperands << " or more operands, but found "
694  << op->getNumOperands();
695  return success();
696 }
697 
698 /// If this is a vector type, or a tensor type, return the scalar element type
699 /// that it is built around, otherwise return the type unmodified.
701  if (auto vec = type.dyn_cast<VectorType>())
702  return vec.getElementType();
703 
704  // Look through tensor<vector<...>> to find the underlying element type.
705  if (auto tensor = type.dyn_cast<TensorType>())
706  return getTensorOrVectorElementType(tensor.getElementType());
707  return type;
708 }
709 
711  // FIXME: Add back check for no side effects on operation.
712  // Currently adding it would cause the shared library build
713  // to fail since there would be a dependency of IR on SideEffectInterfaces
714  // which is cyclical.
715  return success();
716 }
717 
719  // FIXME: Add back check for no side effects on operation.
720  // Currently adding it would cause the shared library build
721  // to fail since there would be a dependency of IR on SideEffectInterfaces
722  // which is cyclical.
723  return success();
724 }
725 
728  for (auto opType : op->getOperandTypes()) {
729  auto type = getTensorOrVectorElementType(opType);
730  if (!type.isSignlessIntOrIndex())
731  return op->emitOpError() << "requires an integer or index type";
732  }
733  return success();
734 }
735 
737  for (auto opType : op->getOperandTypes()) {
738  auto type = getTensorOrVectorElementType(opType);
739  if (!type.isa<FloatType>())
740  return op->emitOpError("requires a float type");
741  }
742  return success();
743 }
744 
746  // Zero or one operand always have the "same" type.
747  unsigned nOperands = op->getNumOperands();
748  if (nOperands < 2)
749  return success();
750 
751  auto type = op->getOperand(0).getType();
752  for (auto opType : llvm::drop_begin(op->getOperandTypes(), 1))
753  if (opType != type)
754  return op->emitOpError() << "requires all operands to have the same type";
755  return success();
756 }
757 
759  if (op->getNumRegions() != 0)
760  return op->emitOpError() << "requires zero regions";
761  return success();
762 }
763 
765  if (op->getNumRegions() != 1)
766  return op->emitOpError() << "requires one region";
767  return success();
768 }
769 
771  unsigned numRegions) {
772  if (op->getNumRegions() != numRegions)
773  return op->emitOpError() << "expected " << numRegions << " regions";
774  return success();
775 }
776 
778  unsigned numRegions) {
779  if (op->getNumRegions() < numRegions)
780  return op->emitOpError() << "expected " << numRegions << " or more regions";
781  return success();
782 }
783 
785  if (op->getNumResults() != 0)
786  return op->emitOpError() << "requires zero results";
787  return success();
788 }
789 
791  if (op->getNumResults() != 1)
792  return op->emitOpError() << "requires one result";
793  return success();
794 }
795 
797  unsigned numOperands) {
798  if (op->getNumResults() != numOperands)
799  return op->emitOpError() << "expected " << numOperands << " results";
800  return success();
801 }
802 
804  unsigned numOperands) {
805  if (op->getNumResults() < numOperands)
806  return op->emitOpError()
807  << "expected " << numOperands << " or more results";
808  return success();
809 }
810 
812  if (failed(verifyAtLeastNOperands(op, 1)))
813  return failure();
814 
816  return op->emitOpError() << "requires the same shape for all operands";
817 
818  return success();
819 }
820 
822  if (failed(verifyAtLeastNOperands(op, 1)) ||
824  return failure();
825 
827  types.append(llvm::to_vector<4>(op->getResultTypes()));
828 
829  if (failed(verifyCompatibleShapes(types)))
830  return op->emitOpError()
831  << "requires the same shape for all operands and results";
832 
833  return success();
834 }
835 
837  if (failed(verifyAtLeastNOperands(op, 1)))
838  return failure();
839  auto elementType = getElementTypeOrSelf(op->getOperand(0));
840 
841  for (auto operand : llvm::drop_begin(op->getOperands(), 1)) {
842  if (getElementTypeOrSelf(operand) != elementType)
843  return op->emitOpError("requires the same element type for all operands");
844  }
845 
846  return success();
847 }
848 
851  if (failed(verifyAtLeastNOperands(op, 1)) ||
853  return failure();
854 
855  auto elementType = getElementTypeOrSelf(op->getResult(0));
856 
857  // Verify result element type matches first result's element type.
858  for (auto result : llvm::drop_begin(op->getResults(), 1)) {
859  if (getElementTypeOrSelf(result) != elementType)
860  return op->emitOpError(
861  "requires the same element type for all operands and results");
862  }
863 
864  // Verify operand's element type matches first result's element type.
865  for (auto operand : op->getOperands()) {
866  if (getElementTypeOrSelf(operand) != elementType)
867  return op->emitOpError(
868  "requires the same element type for all operands and results");
869  }
870 
871  return success();
872 }
873 
875  if (failed(verifyAtLeastNOperands(op, 1)) ||
877  return failure();
878 
879  auto type = op->getResult(0).getType();
880  auto elementType = getElementTypeOrSelf(type);
881  for (auto resultType : llvm::drop_begin(op->getResultTypes())) {
882  if (getElementTypeOrSelf(resultType) != elementType ||
883  failed(verifyCompatibleShape(resultType, type)))
884  return op->emitOpError()
885  << "requires the same type for all operands and results";
886  }
887  for (auto opType : op->getOperandTypes()) {
888  if (getElementTypeOrSelf(opType) != elementType ||
889  failed(verifyCompatibleShape(opType, type)))
890  return op->emitOpError()
891  << "requires the same type for all operands and results";
892  }
893  return success();
894 }
895 
897  Block *block = op->getBlock();
898  // Verify that the operation is at the end of the respective parent block.
899  if (!block || &block->back() != op)
900  return op->emitOpError("must be the last operation in the parent block");
901  return success();
902 }
903 
905  auto *parent = op->getParentRegion();
906 
907  // Verify that the operands lines up with the BB arguments in the successor.
908  for (Block *succ : op->getSuccessors())
909  if (succ->getParent() != parent)
910  return op->emitError("reference to block defined in another region");
911  return success();
912 }
913 
915  if (op->getNumSuccessors() != 0) {
916  return op->emitOpError("requires 0 successors but found ")
917  << op->getNumSuccessors();
918  }
919  return success();
920 }
921 
923  if (op->getNumSuccessors() != 1) {
924  return op->emitOpError("requires 1 successor but found ")
925  << op->getNumSuccessors();
926  }
927  return verifyTerminatorSuccessors(op);
928 }
930  unsigned numSuccessors) {
931  if (op->getNumSuccessors() != numSuccessors) {
932  return op->emitOpError("requires ")
933  << numSuccessors << " successors but found "
934  << op->getNumSuccessors();
935  }
936  return verifyTerminatorSuccessors(op);
937 }
939  unsigned numSuccessors) {
940  if (op->getNumSuccessors() < numSuccessors) {
941  return op->emitOpError("requires at least ")
942  << numSuccessors << " successors but found "
943  << op->getNumSuccessors();
944  }
945  return verifyTerminatorSuccessors(op);
946 }
947 
949  for (auto resultType : op->getResultTypes()) {
950  auto elementType = getTensorOrVectorElementType(resultType);
951  bool isBoolType = elementType.isInteger(1);
952  if (!isBoolType)
953  return op->emitOpError() << "requires a bool result type";
954  }
955 
956  return success();
957 }
958 
960  for (auto resultType : op->getResultTypes())
961  if (!getTensorOrVectorElementType(resultType).isa<FloatType>())
962  return op->emitOpError() << "requires a floating point type";
963 
964  return success();
965 }
966 
969  for (auto resultType : op->getResultTypes())
971  return op->emitOpError() << "requires an integer or index type";
972  return success();
973 }
974 
976  StringRef attrName,
977  StringRef valueGroupName,
978  size_t expectedCount) {
979  auto sizeAttr = op->getAttrOfType<DenseIntElementsAttr>(attrName);
980  if (!sizeAttr)
981  return op->emitOpError("requires 1D i32 elements attribute '")
982  << attrName << "'";
983 
984  auto sizeAttrType = sizeAttr.getType();
985  if (sizeAttrType.getRank() != 1 ||
986  !sizeAttrType.getElementType().isInteger(32))
987  return op->emitOpError("requires 1D i32 elements attribute '")
988  << attrName << "'";
989 
990  if (llvm::any_of(sizeAttr.getValues<APInt>(), [](const APInt &element) {
991  return !element.isNonNegative();
992  }))
993  return op->emitOpError("'")
994  << attrName << "' attribute cannot have negative elements";
995 
996  size_t totalCount = std::accumulate(
997  sizeAttr.begin(), sizeAttr.end(), 0,
998  [](unsigned all, const APInt &one) { return all + one.getZExtValue(); });
999 
1000  if (totalCount != expectedCount)
1001  return op->emitOpError()
1002  << valueGroupName << " count (" << expectedCount
1003  << ") does not match with the total size (" << totalCount
1004  << ") specified in attribute '" << attrName << "'";
1005  return success();
1006 }
1007 
1009  StringRef attrName) {
1010  return verifyValueSizeAttr(op, attrName, "operand", op->getNumOperands());
1011 }
1012 
1014  StringRef attrName) {
1015  return verifyValueSizeAttr(op, attrName, "result", op->getNumResults());
1016 }
1017 
1019  for (Region &region : op->getRegions()) {
1020  if (region.empty())
1021  continue;
1022 
1023  if (region.getNumArguments() != 0) {
1024  if (op->getNumRegions() > 1)
1025  return op->emitOpError("region #")
1026  << region.getRegionNumber() << " should have no arguments";
1027  return op->emitOpError("region should have no arguments");
1028  }
1029  }
1030  return success();
1031 }
1032 
1034  auto isMappableType = [](Type type) {
1035  return type.isa<VectorType, TensorType>();
1036  };
1037  auto resultMappableTypes = llvm::to_vector<1>(
1038  llvm::make_filter_range(op->getResultTypes(), isMappableType));
1039  auto operandMappableTypes = llvm::to_vector<2>(
1040  llvm::make_filter_range(op->getOperandTypes(), isMappableType));
1041 
1042  // If the op only has scalar operand/result types, then we have nothing to
1043  // check.
1044  if (resultMappableTypes.empty() && operandMappableTypes.empty())
1045  return success();
1046 
1047  if (!resultMappableTypes.empty() && operandMappableTypes.empty())
1048  return op->emitOpError("if a result is non-scalar, then at least one "
1049  "operand must be non-scalar");
1050 
1051  assert(!operandMappableTypes.empty());
1052 
1053  if (resultMappableTypes.empty())
1054  return op->emitOpError("if an operand is non-scalar, then there must be at "
1055  "least one non-scalar result");
1056 
1057  if (resultMappableTypes.size() != op->getNumResults())
1058  return op->emitOpError(
1059  "if an operand is non-scalar, then all results must be non-scalar");
1060 
1061  SmallVector<Type, 4> types = llvm::to_vector<2>(
1062  llvm::concat<Type>(operandMappableTypes, resultMappableTypes));
1063  TypeID expectedBaseTy = types.front().getTypeID();
1064  if (!llvm::all_of(types,
1065  [&](Type t) { return t.getTypeID() == expectedBaseTy; }) ||
1066  failed(verifyCompatibleShapes(types))) {
1067  return op->emitOpError() << "all non-scalar operands/results must have the "
1068  "same shape and base type";
1069  }
1070 
1071  return success();
1072 }
1073 
1074 /// Check for any values used by operations regions attached to the
1075 /// specified "IsIsolatedFromAbove" operation defined outside of it.
1077  assert(isolatedOp->hasTrait<OpTrait::IsIsolatedFromAbove>() &&
1078  "Intended to check IsolatedFromAbove ops");
1079 
1080  // List of regions to analyze. Each region is processed independently, with
1081  // respect to the common `limit` region, so we can look at them in any order.
1082  // Therefore, use a simple vector and push/pop back the current region.
1083  SmallVector<Region *, 8> pendingRegions;
1084  for (auto &region : isolatedOp->getRegions()) {
1085  pendingRegions.push_back(&region);
1086 
1087  // Traverse all operations in the region.
1088  while (!pendingRegions.empty()) {
1089  for (Operation &op : pendingRegions.pop_back_val()->getOps()) {
1090  for (Value operand : op.getOperands()) {
1091  // operand should be non-null here if the IR is well-formed. But
1092  // we don't assert here as this function is called from the verifier
1093  // and so could be called on invalid IR.
1094  if (!operand)
1095  return op.emitOpError("operation's operand is null");
1096 
1097  // Check that any value that is used by an operation is defined in the
1098  // same region as either an operation result.
1099  auto *operandRegion = operand.getParentRegion();
1100  if (!region.isAncestor(operandRegion)) {
1101  return op.emitOpError("using value defined outside the region")
1102  .attachNote(isolatedOp->getLoc())
1103  << "required by region isolation constraints";
1104  }
1105  }
1106 
1107  // Schedule any regions in the operation for further checking. Don't
1108  // recurse into other IsolatedFromAbove ops, because they will check
1109  // themselves.
1110  if (op.getNumRegions() &&
1111  !op.hasTrait<OpTrait::IsIsolatedFromAbove>()) {
1112  for (Region &subRegion : op.getRegions())
1113  pendingRegions.push_back(&subRegion);
1114  }
1115  }
1116  }
1117  }
1118 
1119  return success();
1120 }
1121 
1123  return op->hasTrait<Elementwise>() && op->hasTrait<Scalarizable>() &&
1124  op->hasTrait<Vectorizable>() && op->hasTrait<Tensorizable>();
1125 }
1126 
1127 //===----------------------------------------------------------------------===//
1128 // BinaryOp implementation
1129 //===----------------------------------------------------------------------===//
1130 
1131 // These functions are out-of-line implementations of the methods in BinaryOp,
1132 // which avoids them being template instantiated/duplicated.
1133 
1135  Value rhs) {
1136  assert(lhs.getType() == rhs.getType());
1137  result.addOperands({lhs, rhs});
1138  result.types.push_back(lhs.getType());
1139 }
1140 
1142  OperationState &result) {
1144  Type type;
1145  // If the operand list is in-between parentheses, then we have a generic form.
1146  // (see the fallback in `printOneResultOp`).
1147  llvm::SMLoc loc = parser.getCurrentLocation();
1148  if (!parser.parseOptionalLParen()) {
1149  if (parser.parseOperandList(ops) || parser.parseRParen() ||
1150  parser.parseOptionalAttrDict(result.attributes) ||
1151  parser.parseColon() || parser.parseType(type))
1152  return failure();
1153  auto fnType = type.dyn_cast<FunctionType>();
1154  if (!fnType) {
1155  parser.emitError(loc, "expected function type");
1156  return failure();
1157  }
1158  if (parser.resolveOperands(ops, fnType.getInputs(), loc, result.operands))
1159  return failure();
1160  result.addTypes(fnType.getResults());
1161  return success();
1162  }
1163  return failure(parser.parseOperandList(ops) ||
1164  parser.parseOptionalAttrDict(result.attributes) ||
1165  parser.parseColonType(type) ||
1166  parser.resolveOperands(ops, type, result.operands) ||
1167  parser.addTypeToList(type, result.types));
1168 }
1169 
1171  assert(op->getNumResults() == 1 && "op should have one result");
1172 
1173  // If not all the operand and result types are the same, just use the
1174  // generic assembly form to avoid omitting information in printing.
1175  auto resultType = op->getResult(0).getType();
1176  if (llvm::any_of(op->getOperandTypes(),
1177  [&](Type type) { return type != resultType; })) {
1178  p.printGenericOp(op, /*printOpName=*/false);
1179  return;
1180  }
1181 
1182  p << ' ';
1183  p.printOperands(op->getOperands());
1185  // Now we can output only one type for all operands and the result.
1186  p << " : " << resultType;
1187 }
1188 
1189 //===----------------------------------------------------------------------===//
1190 // CastOp implementation
1191 //===----------------------------------------------------------------------===//
1192 
1193 /// Attempt to fold the given cast operation.
1196  SmallVectorImpl<OpFoldResult> &foldResults) {
1197  OperandRange operands = op->getOperands();
1198  if (operands.empty())
1199  return failure();
1200  ResultRange results = op->getResults();
1201 
1202  // Check for the case where the input and output types match 1-1.
1203  if (operands.getTypes() == results.getTypes()) {
1204  foldResults.append(operands.begin(), operands.end());
1205  return success();
1206  }
1207 
1208  return failure();
1209 }
1210 
1211 /// Attempt to verify the given cast operation.
1213  Operation *op, function_ref<bool(TypeRange, TypeRange)> areCastCompatible) {
1214  auto resultTypes = op->getResultTypes();
1215  if (llvm::empty(resultTypes))
1216  return op->emitOpError()
1217  << "expected at least one result for cast operation";
1218 
1219  auto operandTypes = op->getOperandTypes();
1220  if (!areCastCompatible(operandTypes, resultTypes)) {
1221  InFlightDiagnostic diag = op->emitOpError("operand type");
1222  if (llvm::empty(operandTypes))
1223  diag << "s []";
1224  else if (llvm::size(operandTypes) == 1)
1225  diag << " " << *operandTypes.begin();
1226  else
1227  diag << "s " << operandTypes;
1228  return diag << " and result type" << (resultTypes.size() == 1 ? " " : "s ")
1229  << resultTypes << " are cast incompatible";
1230  }
1231 
1232  return success();
1233 }
1234 
1235 void impl::buildCastOp(OpBuilder &builder, OperationState &result, Value source,
1236  Type destType) {
1237  result.addOperands(source);
1238  result.addTypes(destType);
1239 }
1240 
1242  OpAsmParser::OperandType srcInfo;
1243  Type srcType, dstType;
1244  return failure(parser.parseOperand(srcInfo) ||
1245  parser.parseOptionalAttrDict(result.attributes) ||
1246  parser.parseColonType(srcType) ||
1247  parser.resolveOperand(srcInfo, srcType, result.operands) ||
1248  parser.parseKeywordType("to", dstType) ||
1249  parser.addTypeToList(dstType, result.types));
1250 }
1251 
1253  p << ' ' << op->getOperand(0);
1255  p << " : " << op->getOperand(0).getType() << " to "
1256  << op->getResult(0).getType();
1257 }
1258 
1260  // Identity cast
1261  if (op->getOperand(0).getType() == op->getResult(0).getType())
1262  return op->getOperand(0);
1263  return nullptr;
1264 }
1265 
1268  function_ref<bool(Type, Type)> areCastCompatible) {
1269  auto opType = op->getOperand(0).getType();
1270  auto resType = op->getResult(0).getType();
1271  if (!areCastCompatible(opType, resType))
1272  return op->emitError("operand type ")
1273  << opType << " and result type " << resType
1274  << " are cast incompatible";
1275 
1276  return success();
1277 }
1278 
1279 //===----------------------------------------------------------------------===//
1280 // Misc. utils
1281 //===----------------------------------------------------------------------===//
1282 
1283 /// Insert an operation, generated by `buildTerminatorOp`, at the end of the
1284 /// region's only block if it does not have a terminator already. If the region
1285 /// is empty, insert a new block first. `buildTerminatorOp` should return the
1286 /// terminator operation to insert.
1288  Region &region, OpBuilder &builder, Location loc,
1289  function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp) {
1290  OpBuilder::InsertionGuard guard(builder);
1291  if (region.empty())
1292  builder.createBlock(&region);
1293 
1294  Block &block = region.back();
1295  if (!block.empty() && block.back().hasTrait<OpTrait::IsTerminator>())
1296  return;
1297 
1298  builder.setInsertionPointToEnd(&block);
1299  builder.insert(buildTerminatorOp(builder, loc));
1300 }
1301 
1302 /// Create a simple OpBuilder and forward to the OpBuilder version of this
1303 /// function.
1305  Region &region, Builder &builder, Location loc,
1306  function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp) {
1307  OpBuilder opBuilder(builder.getContext());
1308  ensureRegionTerminator(region, opBuilder, loc, buildTerminatorOp);
1309 }
virtual ParseResult parseOperand(OperandType &result)=0
Parse a single operand.
This is the representation of an operand reference.
void moveBefore(Operation *existingOp)
Unlink this operation from its current block and insert it right before existingOp which may be in th...
Definition: Operation.cpp:440
Include the generated interface declarations.
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, ArrayRef< NamedAttribute > attributes, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
Definition: Operation.cpp:27
This class contains a list of basic blocks and a link to the parent operation it is attached to...
Definition: Region.h:26
void removeNodeFromList(Operation *op)
This is a trait method invoked when an operation is removed from a block.
Definition: Operation.cpp:398
ParseResult resolveOperands(ArrayRef< OperandType > operands, Type type, SmallVectorImpl< Value > &result)
Resolve a list of operands to SSA values, emitting an error on failure, or appending the results to t...
static std::string diag(llvm::Value &v)
MLIRContext * getContext() const
Definition: Builders.h:54
LogicalResult verifyCastOp(Operation *op, function_ref< bool(Type, Type)> areCastCompatible)
Definition: Operation.cpp:1267
void buildCastOp(OpBuilder &builder, OperationState &result, Value source, Type destType)
Definition: Operation.cpp:1235
virtual raw_ostream & getStream() const
Return the raw output stream used by this printer.
LogicalResult verifyNSuccessors(Operation *op, unsigned numSuccessors)
Definition: Operation.cpp:929
LogicalResult verifyCompatibleShape(ArrayRef< int64_t > shape1, ArrayRef< int64_t > shape2)
Returns success if the given two shapes are compatible.
Operation is a basic unit of execution within MLIR.
Definition: Operation.h:28
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:423
LogicalResult verifyZeroOperands(Operation *op)
Definition: Operation.cpp:668
SmallVector< Block *, 1 > successors
Successors of this operation and their respective operands.
Operation & back()
Definition: Block.h:143
LogicalResult verifyElementwise(Operation *op)
Definition: Operation.cpp:1033
LogicalResult verifyResultsAreFloatLike(Operation *op)
Definition: Operation.cpp:959
operand_range getOperands()
Returns an iterator on the underlying Value&#39;s.
Definition: Operation.h:247
unsigned getNumRegions()
Returns the number of regions held by this operation.
Definition: Operation.h:420
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:301
void setOperands(ValueRange operands)
Replace the current operands of this operation with the ones provided in &#39;operands&#39;.
Definition: Operation.cpp:200
LogicalResult foldCastInterfaceOp(Operation *op, ArrayRef< Attribute > attrOperands, SmallVectorImpl< OpFoldResult > &foldResults)
Attempt to fold the given cast operation.
Definition: Operation.cpp:1195
LogicalResult verifyResultSizeAttr(Operation *op, StringRef sizeAttrName)
Definition: Operation.cpp:1013
Block represents an ordered list of Operations.
Definition: Block.h:29
LogicalResult verifyIsInvolution(Operation *op)
Definition: Operation.cpp:718
LogicalResult verifySameOperandsAndResultShape(Operation *op)
Definition: Operation.cpp:821
void addNodeToList(Operation *op)
This is a trait method invoked when an operation is added to a block.
Definition: Operation.cpp:388
LogicalResult verifyIsIsolatedFromAbove(Operation *op)
Check for any values used by operations regions attached to the specified "IsIsolatedFromAbove" opera...
Definition: Operation.cpp:1076
OpFoldResult foldIdempotent(Operation *op)
Definition: Operation.cpp:644
This class represents a single result from folding an operation.
Definition: OpDefinition.h:244
ArrayRef< NamedAttribute > getAttrs()
Return all of the attributes on this operation.
Definition: Operation.h:308
Value getOperand(unsigned idx)
Definition: Operation.h:219
AttrClass getAttrOfType(StringAttr name)
Definition: Operation.h:327
bool hasElementwiseMappableTraits(Operation *op)
Together, Elementwise, Scalarizable, Vectorizable, and Tensorizable provide an easy way for scalar op...
Definition: Operation.cpp:1122
OpListType & getOperations()
Definition: Block.h:128
LogicalResult verifyNOperands(Operation *op, unsigned numOperands)
Definition: Operation.cpp:680
void invalidateOpOrder()
Invalidates the current ordering of operations.
Definition: Block.cpp:95
void print(raw_ostream &os, OpPrintingFlags flags=llvm::None)
Print the operation to the given stream.
Definition: OpDefinition.h:112
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
Definition: LogicalResult.h:72
unsigned getNumOperands()
Definition: Operation.h:215
LogicalResult verifySameOperandsElementType(Operation *op)
Definition: Operation.cpp:836
virtual ParseResult parseOptionalLParen()=0
Parse a ( token if present.
bool mightHaveTrait()
Returns true if the operation might have the provided trait.
Definition: Operation.h:477
A block operand represents an operand that holds a reference to a Block, e.g.
Definition: BlockSupport.h:30
ParseResult parseCastOp(OpAsmParser &parser, OperationState &result)
Definition: Operation.cpp:1241
void transferNodesFromList(ilist_traits< Operation > &otherList, op_iterator first, op_iterator last)
This is a trait method invoked when an operation is moved from one block to another.
Definition: Operation.cpp:405
operand_type_range getOperandTypes()
Definition: Operation.h:266
OpFoldResult foldInvolution(Operation *op)
Definition: Operation.cpp:658
LogicalResult verifyCastInterfaceOp(Operation *op, function_ref< bool(TypeRange, TypeRange)> areCastCompatible)
Attempt to verify the given cast operation.
Definition: Operation.cpp:1212
bool isBeforeInBlock(Operation *other)
Given an operation &#39;other&#39; that is within the same parent block, return whether the current operation...
Definition: Operation.cpp:271
DictionaryAttr getDictionary(MLIRContext *context) const
Return a dictionary attribute for the underlying dictionary.
virtual llvm::unique_function< void(Operation *, OpAsmPrinter &printer)> getOperationPrinter(Operation *op) const
Print an operation registered to this dialect.
Definition: Dialect.cpp:174
ParseResult addTypeToList(Type type, SmallVectorImpl< Type > &result)
Add the specified type to the end of the specified type list and return success.
LogicalResult verifyZeroResult(Operation *op)
Definition: Operation.cpp:784
This class implements the result iterators for the Operation class.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value...
Definition: LogicalResult.h:68
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:706
type_range getTypes() const
unsigned getNumSuccessors()
Definition: Operation.h:449
Operation & front()
Definition: Block.h:144
The OpAsmParser has methods for interacting with the asm parser: parsing things from it...
LogicalResult verifyAtLeastNSuccessors(Operation *op, unsigned numSuccessors)
Definition: Operation.cpp:938
Block * getBlock()
Returns the operation block that contains this operation.
Definition: Operation.h:96
LogicalResult verifySameOperandsAndResultElementType(Operation *op)
Definition: Operation.cpp:850
void insertOperands(unsigned index, ValueRange operands)
Insert the given operands into the operand list at the given &#39;index&#39;.
Definition: Operation.cpp:219
LogicalResult verifyOperandsAreFloatLike(Operation *op)
Definition: Operation.cpp:736
LogicalResult verifyResultsAreBoolLike(Operation *op)
Definition: Operation.cpp:948
void destroy()
Destroys this operation and its subclass data.
Definition: Operation.cpp:171
void takeBody(Region &other)
Takes body of another region (that region will have no body after this operation completes).
Definition: Region.h:237
void printOperands(const ContainerType &container)
Print a comma separated list of operands.
virtual llvm::SMLoc getNameLoc() const =0
Return the location of the original name token.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
LogicalResult verifySameOperandsAndResultType(Operation *op)
Definition: Operation.cpp:874
void erase()
Remove this operation from its parent block and delete it.
Definition: Operation.cpp:424
SmallVector< Value, 4 > operands
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:52
void setSuccessor(Block *block, unsigned index)
Definition: Operation.cpp:490
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:48
LogicalResult verifyOneOperand(Operation *op)
Definition: Operation.cpp:674
static ParseResult parse(OpAsmParser &parser, OperationState &result)
Parse the custom form of an operation.
Definition: Operation.cpp:585
virtual ParseResult parseOperandList(SmallVectorImpl< OperandType > &result, int requiredOperandCount=-1, Delimiter delimiter=Delimiter::None)=0
Parse zero or more SSA comma-separated operand references with a specified surrounding delimiter...
LogicalResult verifyAtLeastNResults(Operation *op, unsigned numOperands)
Definition: Operation.cpp:803
LogicalResult verifySameTypeOperands(Operation *op)
Definition: Operation.cpp:745
void map(Block *from, Block *to)
Inserts a new mapping for &#39;from&#39; to &#39;to&#39;.
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:99
LogicalResult verifyNRegions(Operation *op, unsigned numRegions)
Definition: Operation.cpp:770
bool hasTrait() const
Returns true if the operation was registered with a particular trait, e.g.
MutableArrayRef< OpOperand > getOpOperands()
Definition: Operation.h:252
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
virtual ParseResult parseColon()=0
Parse a : token.
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 verifyOneResult(Operation *op)
Definition: Operation.cpp:790
virtual ParseResult resolveOperand(const OperandType &operand, Type type, SmallVectorImpl< Value > &result)=0
Resolve an operand to an SSA value, emitting an error on failure.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
This trait tags Elementwise operatons that can be systematically tensorized.
Operation * clone()
Definition: Operation.cpp:574
bool empty()
Definition: Region.h:60
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:618
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.
void addOperands(ValueRange newOperands)
void ensureRegionTerminator(Region &region, OpBuilder &builder, Location loc, function_ref< Operation *(OpBuilder &, Location)> buildTerminatorOp)
Insert an operation, generated by buildTerminatorOp, at the end of the region&#39;s only block if it does...
Definition: Operation.cpp:1287
virtual llvm::SMLoc getCurrentLocation()=0
Get the location of the next token and store it into the argument.
InFlightDiagnostic emitRemark(const Twine &message={})
Emit a remark about this operation, reporting up to any diagnostic handlers that may be listening...
Definition: Operation.cpp:636
U dyn_cast() const
Definition: Types.h:244
Operation * insert(Operation *op)
Insert the given operation at the current insertion point and return it.
Definition: Builders.cpp:344
void setOperands(Operation *owner, ValueRange values)
Replace the operands contained in the storage with the ones provided in &#39;values&#39;. ...
LogicalResult verifyAtLeastNRegions(Operation *op, unsigned numRegions)
Definition: Operation.cpp:777
Diagnostic & attachNote(Optional< Location > noteLoc=llvm::None)
Attaches a note to this diagnostic.
Definition: Diagnostics.h:335
iterator end()
Definition: Block.h:135
ParseResult parseKeywordType(const char *keyword, Type &result)
Parse a keyword followed by a type.
simple_ilist< Operation >::iterator op_iterator
Definition: BlockSupport.h:230
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:470
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:117
LogicalResult verifyValueSizeAttr(Operation *op, StringRef attrName, StringRef valueGroupName, size_t expectedCount)
Definition: Operation.cpp:975
bool isSignlessIntOrIndex() const
Return true if this is a signless integer or index type.
Definition: Types.cpp:73
virtual void printGenericOp(Operation *op, bool printOpName=true)=0
Print the entire operation with the default generic assembly form.
virtual ParseResult parseRParen()=0
Parse a ) token.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:42
void printOneResultOp(Operation *op, OpAsmPrinter &p)
Definition: Operation.cpp:1170
Block & back()
Definition: Region.h:64
OpResult getResult(unsigned idx)
Get the &#39;idx&#39;th result of this operation.
Definition: Operation.h:276
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:38
void addTypes(ArrayRef< Type > newTypes)
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
virtual Optional< ParseOpHook > getParseOperationHook(StringRef opName) const
Return the hook to parse an operation registered to this dialect, if any.
Definition: Dialect.cpp:169
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:106
This represents an operation in an abstracted form, suitable for use with the builder APIs...
MutableArrayRef< BlockOperand > getBlockOperands()
Definition: Operation.h:438
LogicalResult verifyZeroRegion(Operation *op)
Definition: Operation.cpp:758
LogicalResult verifyOneSuccessor(Operation *op)
Definition: Operation.cpp:922
Diagnostic & append(Arg1 &&arg1, Arg2 &&arg2, Args &&... args)
Append arguments to the diagnostic.
Definition: Diagnostics.h:232
void dropAllDefinedValueUses()
Drop uses of all values defined by this operation or its nested regions.
Definition: Operation.cpp:482
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening...
Definition: Operation.cpp:243
void cloneInto(Region *dest, BlockAndValueMapping &mapper)
Clone the internal blocks from this region into dest.
Definition: Region.cpp:70
Tensor types represent multi-dimensional arrays, and have two variants: RankedTensorType and Unranked...
Definition: BuiltinTypes.h:73
InFlightDiagnostic emitRemark(const Twine &message={})
Emit a remark about this operation, reporting up to any diagnostic handlers that may be listening...
Definition: Operation.cpp:252
void dropAllDefinedValueUses()
This drops all uses of values defined in this block or in the blocks of nested regions wherever the u...
Definition: Block.cpp:82
This trait tags element-wise ops on vectors or tensors.
void dropAllUses()
Drop all uses of results of this operation.
Definition: Operation.h:552
bool empty()
Definition: Block.h:139
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
bool use_empty()
Returns true if this operation has no uses.
Definition: Operation.h:570
Value foldCastOp(Operation *op)
Definition: Operation.cpp:1259
bool isOpOrderValid()
Returns true if the ordering of the child operations is valid, false otherwise.
Definition: Block.cpp:92
LogicalResult verifySameOperandsShape(Operation *op)
Definition: Operation.cpp:811
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:84
LogicalResult verifyZeroSuccessor(Operation *op)
Definition: Operation.cpp:914
static OpListType Block::* getSublistAccess(Operation *)
Returns pointer to member of operation list.
Definition: Block.h:336
void remove()
Remove the operation from its parent block, but don&#39;t delete it.
Definition: Operation.cpp:432
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening...
Definition: Operation.cpp:630
LogicalResult verifyAtLeastNOperands(Operation *op, unsigned numOperands)
Definition: Operation.cpp:689
LogicalResult verifyResultsAreSignlessIntegerLike(Operation *op)
Definition: Operation.cpp:968
MLIRContext * getContext() const
Get the context held by this operation state.
void dropAllReferences()
This drops all operand uses from this operation, which is an essential step in breaking cyclic depend...
Definition: Operation.cpp:469
void moveAfter(Operation *existingOp)
Unlink this operation from its current block and insert it right after existingOp which may be in the...
Definition: Operation.cpp:454
NamedAttrList attributes
SuccessorRange getSuccessors()
Definition: Operation.h:446
virtual InFlightDiagnostic emitError(llvm::SMLoc loc, const Twine &message={})=0
Emit a diagnostic at the specified location and return failure.
virtual void printOptionalAttrDict(ArrayRef< NamedAttribute > attrs, ArrayRef< StringRef > elidedAttrs={})=0
If the specified operation has attributes, print out an attribute dictionary with their values...
RAII guard to reset the insertion point of the builder when destroyed.
Definition: Builders.h:279
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Set of flags used to control the behavior of the various IR print methods (e.g.
MLIRContext * getContext() const
Return the context this location is uniqued in.
Definition: Location.h:58
static LogicalResult verifyTerminatorSuccessors(Operation *op)
Definition: Operation.cpp:904
This class is a general helper class for creating context-global objects like types, attributes, and affine expressions.
Definition: Builders.h:49
Type getType() const
Return the type of this value.
Definition: Value.h:117
ParseResult parseOneResultSameOperandTypeOp(OpAsmParser &parser, OperationState &result)
Definition: Operation.cpp:1141
TypeID getTypeID()
Return a unique identifier for the concrete type.
Definition: Types.h:108
This class provides the API for ops that are known to be isolated from above.
LogicalResult verifyCompatibleShapes(TypeRange types1, TypeRange types2)
Returns success if the given two arrays have the same number of elements and each pair wise entries h...
This class provides the implementation for an operation result whose index cannot be represented "inl...
Definition: Value.h:393
Dialect * getDialect()
Return the dialect this operation is associated with, or nullptr if the associated dialect is not loa...
Definition: Operation.h:103
void recomputeOpOrder()
Recomputes the ordering of child operations within the block.
Definition: Block.cpp:124
This trait tags Elementwise operatons that can be systematically scalarized.
virtual ParseResult parseType(Type &result)=0
Parse a type.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Definition: Value.cpp:20
Block * lookupOrDefault(Block *from) const
Lookup a mapped value within the map.
This class provides the API for ops that are known to have no SSA operand.
Definition: OpDefinition.h:383
LogicalResult verifyNoRegionArguments(Operation *op)
Definition: Operation.cpp:1018
This class represents an operand of an operation.
Definition: Value.h:249
This class provides an abstraction over the different types of ranges over Blocks.
Definition: BlockSupport.h:104
This class provides an abstraction over the different types of ranges over Regions.
Definition: Region.h:322
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:624
LogicalResult verifyOperandsAreSignlessIntegerLike(Operation *op)
Definition: Operation.cpp:727
This class implements the operand iterators for the Operation class.
void printCastOp(Operation *op, OpAsmPrinter &p)
Definition: Operation.cpp:1252
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Definition: Builders.h:367
Dialect * getDialect() const
Return the dialect this operation is registered to if the dialect is loaded in the context...
Region * getParentRegion()
Returns the region to which the instruction belongs.
Definition: Operation.h:113
LogicalResult verifyIsIdempotent(Operation *op)
Definition: Operation.cpp:710
LogicalResult fold(ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results)
Attempt to fold this operation with the specified constant operand values.
Definition: Operation.cpp:496
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.h:273
void buildBinaryOp(OpBuilder &builder, OperationState &result, Value lhs, Value rhs)
Definition: Operation.cpp:1134
virtual ParseResult parseOptionalAttrDict(NamedAttrList &result)=0
Parse a named dictionary into &#39;result&#39; if it is present.
InFlightDiagnostic emitRemark(Location loc)
Utility method to emit a remark message using this location.
SmallVector< std::unique_ptr< Region >, 1 > regions
Regions that the op will hold.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=llvm::None, ArrayRef< Location > locs=llvm::None)
Add new block with &#39;argTypes&#39; arguments and set the insertion point to the end of it...
Definition: Builders.cpp:353
LogicalResult verifyNResults(Operation *op, unsigned numOperands)
Definition: Operation.cpp:796
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:518
Optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
Definition: Operation.h:61
This trait tags Elementwise operatons that can be systematically vectorized.
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:57
bool isa() const
Definition: Types.h:234
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:231
This class represents success/failure for operation parsing.
Definition: OpDefinition.h:36
user_range getUsers()
Returns a range of all users.
Definition: Operation.h:591
void replaceUsesOfWith(Value from, Value to)
Replace any uses of &#39;from&#39; with &#39;to&#39; within this operation.
Definition: Operation.cpp:190
result_range getResults()
Definition: Operation.h:284
This class helps build Operations.
Definition: Builders.h:177
This class provides an abstraction over the different types of ranges over Values.
static void deleteNode(Operation *op)
Definition: Operation.cpp:376
Diagnostic & appendOp(Operation &val, const OpPrintingFlags &flags)
Append an operation with the given printing flags.
result_type_range getResultTypes()
Definition: Operation.h:297
bool isProperAncestor(Operation *other)
Return true if this operation is a proper ancestor of the other operation.
Definition: Operation.cpp:182
This class provides the implementation for an operation result whose index can be represented "inline...
Definition: Value.h:376
LogicalResult verifyOperandSizeAttr(Operation *op, StringRef sizeAttrName)
Definition: Operation.cpp:1008
Region & getRegion(unsigned index)
Returns the region held by this operation at position &#39;index&#39;.
Definition: Operation.h:429
LogicalResult verifyIsTerminator(Operation *op)
Definition: Operation.cpp:896
LogicalResult verifyOneRegion(Operation *op)
Definition: Operation.cpp:764
virtual ParseResult parseColonType(Type &result)=0
Parse a colon followed by a type.
Operation * cloneWithoutRegions()
Create a partial copy of this operation without traversing into attached regions. ...
Definition: Operation.cpp:554
An attribute that represents a reference to a dense integer vector or tensor object.
static Type getTensorOrVectorElementType(Type type)
If this is a vector type, or a tensor type, return the scalar element type that it is built around...
Definition: Operation.cpp:700
type_range getTypes() const
SmallVector< Type, 4 > types
Types of the results of this operation.
static void printOpName(Operation *op, OpAsmPrinter &p, StringRef defaultDialect)
Print an operation name, eliding the dialect prefix if necessary.
Definition: Operation.cpp:604
This class handles the management of operation operands.