MLIR  17.0.0git
OpDefinition.h
Go to the documentation of this file.
1 //===- OpDefinition.h - Classes for defining concrete Op types --*- C++ -*-===//
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 helper classes for implementing the "Op" types. This
10 // includes the Op type, which is the base class for Op class definitions,
11 // as well as number of traits in the OpTrait namespace that provide a
12 // declarative way to specify properties of Ops.
13 //
14 // The purpose of these types are to allow light-weight implementation of
15 // concrete ops (like DimOp) with very little boilerplate.
16 //
17 //===----------------------------------------------------------------------===//
18 
19 #ifndef MLIR_IR_OPDEFINITION_H
20 #define MLIR_IR_OPDEFINITION_H
21 
22 #include "mlir/IR/Dialect.h"
23 #include "mlir/IR/Operation.h"
24 #include "llvm/Support/PointerLikeTypeTraits.h"
25 
26 #include <type_traits>
27 #include <optional>
28 
29 namespace mlir {
30 class Builder;
31 class OpBuilder;
32 
33 /// This class implements `Optional` functionality for ParseResult. We don't
34 /// directly use Optional here, because it provides an implicit conversion
35 /// to 'bool' which we want to avoid. This class is used to implement tri-state
36 /// 'parseOptional' functions that may have a failure mode when parsing that
37 /// shouldn't be attributed to "not present".
39 public:
40  OptionalParseResult() = default;
41  OptionalParseResult(LogicalResult result) : impl(result) {}
42  OptionalParseResult(ParseResult result) : impl(result) {}
45  OptionalParseResult(std::nullopt_t) : impl(std::nullopt) {}
46 
47  /// Returns true if we contain a valid ParseResult value.
48  bool has_value() const { return impl.has_value(); }
49 
50  /// Access the internal ParseResult value.
51  ParseResult value() const { return *impl; }
52  ParseResult operator*() const { return value(); }
53 
54 private:
55  std::optional<ParseResult> impl;
56 };
57 
58 // These functions are out-of-line utilities, which avoids them being template
59 // instantiated/duplicated.
60 namespace impl {
61 /// Insert an operation, generated by `buildTerminatorOp`, at the end of the
62 /// region's only block if it does not have a terminator already. If the region
63 /// is empty, insert a new block first. `buildTerminatorOp` should return the
64 /// terminator operation to insert.
66  Region &region, OpBuilder &builder, Location loc,
67  function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp);
69  Region &region, Builder &builder, Location loc,
70  function_ref<Operation *(OpBuilder &, Location)> buildTerminatorOp);
71 
72 } // namespace impl
73 
74 /// This is the concrete base class that holds the operation pointer and has
75 /// non-generic methods that only depend on State (to avoid having them
76 /// instantiated on template types that don't affect them.
77 ///
78 /// This also has the fallback implementations of customization hooks for when
79 /// they aren't customized.
80 class OpState {
81 public:
82  /// Ops are pointer-like, so we allow conversion to bool.
83  explicit operator bool() { return getOperation() != nullptr; }
84 
85  /// This implicitly converts to Operation*.
86  operator Operation *() const { return state; }
87 
88  /// Shortcut of `->` to access a member of Operation.
89  Operation *operator->() const { return state; }
90 
91  /// Return the operation that this refers to.
92  Operation *getOperation() { return state; }
93 
94  /// Return the context this operation belongs to.
96 
97  /// Print the operation to the given stream.
98  void print(raw_ostream &os, OpPrintingFlags flags = std::nullopt) {
99  state->print(os, flags);
100  }
101  void print(raw_ostream &os, AsmState &asmState) {
102  state->print(os, asmState);
103  }
104 
105  /// Dump this operation.
106  void dump() { state->dump(); }
107 
108  /// The source location the operation was defined or derived from.
109  Location getLoc() { return state->getLoc(); }
110 
111  /// Return true if there are no users of any results of this operation.
112  bool use_empty() { return state->use_empty(); }
113 
114  /// Remove this operation from its parent block and delete it.
115  void erase() { state->erase(); }
116 
117  /// Emit an error with the op name prefixed, like "'dim' op " which is
118  /// convenient for verifiers.
119  InFlightDiagnostic emitOpError(const Twine &message = {});
120 
121  /// Emit an error about fatal conditions with this operation, reporting up to
122  /// any diagnostic handlers that may be listening.
123  InFlightDiagnostic emitError(const Twine &message = {});
124 
125  /// Emit a warning about this operation, reporting up to any diagnostic
126  /// handlers that may be listening.
127  InFlightDiagnostic emitWarning(const Twine &message = {});
128 
129  /// Emit a remark about this operation, reporting up to any diagnostic
130  /// handlers that may be listening.
131  InFlightDiagnostic emitRemark(const Twine &message = {});
132 
133  /// Walk the operation by calling the callback for each nested operation
134  /// (including this one), block or region, depending on the callback provided.
135  /// The order in which regions, blocks and operations the same nesting level
136  /// are visited (e.g., lexicographical or reverse lexicographical order) is
137  /// determined by 'Iterator'. The walk order for enclosing regions, blocks
138  /// and operations with respect to their nested ones is specified by 'Order'
139  /// (post-order by default). A callback on a block or operation is allowed to
140  /// erase that block or operation if either:
141  /// * the walk is in post-order, or
142  /// * the walk is in pre-order and the walk is skipped after the erasure.
143  /// See Operation::walk for more details.
144  template <WalkOrder Order = WalkOrder::PostOrder,
145  typename Iterator = ForwardIterator, typename FnT,
146  typename RetT = detail::walkResultType<FnT>>
147  std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 1,
148  RetT>
149  walk(FnT &&callback) {
150  return state->walk<Order, Iterator>(std::forward<FnT>(callback));
151  }
152 
153  /// Generic walker with a stage aware callback. Walk the operation by calling
154  /// the callback for each nested operation (including this one) N+1 times,
155  /// where N is the number of regions attached to that operation.
156  ///
157  /// The callback method can take any of the following forms:
158  /// void(Operation *, const WalkStage &) : Walk all operation opaquely
159  /// * op.walk([](Operation *nestedOp, const WalkStage &stage) { ...});
160  /// void(OpT, const WalkStage &) : Walk all operations of the given derived
161  /// type.
162  /// * op.walk([](ReturnOp returnOp, const WalkStage &stage) { ...});
163  /// WalkResult(Operation*|OpT, const WalkStage &stage) : Walk operations,
164  /// but allow for interruption/skipping.
165  /// * op.walk([](... op, const WalkStage &stage) {
166  /// // Skip the walk of this op based on some invariant.
167  /// if (some_invariant)
168  /// return WalkResult::skip();
169  /// // Interrupt, i.e cancel, the walk based on some invariant.
170  /// if (another_invariant)
171  /// return WalkResult::interrupt();
172  /// return WalkResult::advance();
173  /// });
174  template <typename FnT, typename RetT = detail::walkResultType<FnT>>
175  std::enable_if_t<llvm::function_traits<std::decay_t<FnT>>::num_args == 2,
176  RetT>
177  walk(FnT &&callback) {
178  return state->walk(std::forward<FnT>(callback));
179  }
180 
181  // These are default implementations of customization hooks.
182 public:
183  /// This hook returns any canonicalization pattern rewrites that the operation
184  /// supports, for use by the canonicalization pass.
186  MLIRContext *context) {}
187 
188  /// This hook populates any unset default attrs.
190 
191 protected:
192  /// If the concrete type didn't implement a custom verifier hook, just fall
193  /// back to this one which accepts everything.
194  LogicalResult verify() { return success(); }
196 
197  /// Parse the custom form of an operation. Unless overridden, this method will
198  /// first try to get an operation parser from the op's dialect. Otherwise the
199  /// custom assembly form of an op is always rejected. Op implementations
200  /// should implement this to return failure. On success, they should fill in
201  /// result with the fields to use.
202  static ParseResult parse(OpAsmParser &parser, OperationState &result);
203 
204  /// Print the operation. Unless overridden, this method will first try to get
205  /// an operation printer from the dialect. Otherwise, it prints the operation
206  /// in generic form.
207  static void print(Operation *op, OpAsmPrinter &p, StringRef defaultDialect);
208 
209  /// Print an operation name, eliding the dialect prefix if necessary.
210  static void printOpName(Operation *op, OpAsmPrinter &p,
211  StringRef defaultDialect);
212 
213  /// Mutability management is handled by the OpWrapper/OpConstWrapper classes,
214  /// so we can cast it away here.
215  explicit OpState(Operation *state) : state(state) {}
216 
217 private:
218  Operation *state;
219 
220  /// Allow access to internal hook implementation methods.
222 };
223 
224 // Allow comparing operators.
225 inline bool operator==(OpState lhs, OpState rhs) {
226  return lhs.getOperation() == rhs.getOperation();
227 }
228 inline bool operator!=(OpState lhs, OpState rhs) {
229  return lhs.getOperation() != rhs.getOperation();
230 }
231 
232 raw_ostream &operator<<(raw_ostream &os, OpFoldResult ofr);
233 
234 /// This class represents a single result from folding an operation.
235 class OpFoldResult : public PointerUnion<Attribute, Value> {
237 
238 public:
239  void dump() const { llvm::errs() << *this << "\n"; }
240 };
241 
242 /// Allow printing to a stream.
243 inline raw_ostream &operator<<(raw_ostream &os, OpFoldResult ofr) {
244  if (Value value = ofr.dyn_cast<Value>())
245  value.print(os);
246  else
247  ofr.dyn_cast<Attribute>().print(os);
248  return os;
249 }
250 
251 /// Allow printing to a stream.
252 inline raw_ostream &operator<<(raw_ostream &os, OpState op) {
253  op.print(os, OpPrintingFlags().useLocalScope());
254  return os;
255 }
256 
257 //===----------------------------------------------------------------------===//
258 // Operation Trait Types
259 //===----------------------------------------------------------------------===//
260 
261 namespace OpTrait {
262 
263 // These functions are out-of-line implementations of the methods in the
264 // corresponding trait classes. This avoids them being template
265 // instantiated/duplicated.
266 namespace impl {
267 OpFoldResult foldIdempotent(Operation *op);
268 OpFoldResult foldInvolution(Operation *op);
269 LogicalResult verifyZeroOperands(Operation *op);
270 LogicalResult verifyOneOperand(Operation *op);
271 LogicalResult verifyNOperands(Operation *op, unsigned numOperands);
272 LogicalResult verifyIsIdempotent(Operation *op);
273 LogicalResult verifyIsInvolution(Operation *op);
274 LogicalResult verifyAtLeastNOperands(Operation *op, unsigned numOperands);
275 LogicalResult verifyOperandsAreFloatLike(Operation *op);
276 LogicalResult verifyOperandsAreSignlessIntegerLike(Operation *op);
277 LogicalResult verifySameTypeOperands(Operation *op);
278 LogicalResult verifyZeroRegions(Operation *op);
279 LogicalResult verifyOneRegion(Operation *op);
280 LogicalResult verifyNRegions(Operation *op, unsigned numRegions);
281 LogicalResult verifyAtLeastNRegions(Operation *op, unsigned numRegions);
282 LogicalResult verifyZeroResults(Operation *op);
283 LogicalResult verifyOneResult(Operation *op);
284 LogicalResult verifyNResults(Operation *op, unsigned numOperands);
285 LogicalResult verifyAtLeastNResults(Operation *op, unsigned numOperands);
286 LogicalResult verifySameOperandsShape(Operation *op);
287 LogicalResult verifySameOperandsAndResultShape(Operation *op);
288 LogicalResult verifySameOperandsElementType(Operation *op);
289 LogicalResult verifySameOperandsAndResultElementType(Operation *op);
290 LogicalResult verifySameOperandsAndResultType(Operation *op);
291 LogicalResult verifyResultsAreBoolLike(Operation *op);
292 LogicalResult verifyResultsAreFloatLike(Operation *op);
293 LogicalResult verifyResultsAreSignlessIntegerLike(Operation *op);
294 LogicalResult verifyIsTerminator(Operation *op);
295 LogicalResult verifyZeroSuccessors(Operation *op);
296 LogicalResult verifyOneSuccessor(Operation *op);
297 LogicalResult verifyNSuccessors(Operation *op, unsigned numSuccessors);
298 LogicalResult verifyAtLeastNSuccessors(Operation *op, unsigned numSuccessors);
299 LogicalResult verifyValueSizeAttr(Operation *op, StringRef attrName,
300  StringRef valueGroupName,
301  size_t expectedCount);
302 LogicalResult verifyOperandSizeAttr(Operation *op, StringRef sizeAttrName);
303 LogicalResult verifyResultSizeAttr(Operation *op, StringRef sizeAttrName);
304 LogicalResult verifyNoRegionArguments(Operation *op);
305 LogicalResult verifyElementwise(Operation *op);
306 LogicalResult verifyIsIsolatedFromAbove(Operation *op);
307 } // namespace impl
308 
309 /// Helper class for implementing traits. Clients are not expected to interact
310 /// with this directly, so its members are all protected.
311 template <typename ConcreteType, template <typename> class TraitType>
312 class TraitBase {
313 protected:
314  /// Return the ultimate Operation being worked on.
316  auto *concrete = static_cast<ConcreteType *>(this);
317  return concrete->getOperation();
318  }
319 };
320 
321 //===----------------------------------------------------------------------===//
322 // Operand Traits
323 
324 namespace detail {
325 /// Utility trait base that provides accessors for derived traits that have
326 /// multiple operands.
327 template <typename ConcreteType, template <typename> class TraitType>
328 struct MultiOperandTraitBase : public TraitBase<ConcreteType, TraitType> {
333 
334  /// Return the number of operands.
335  unsigned getNumOperands() { return this->getOperation()->getNumOperands(); }
336 
337  /// Return the operand at index 'i'.
338  Value getOperand(unsigned i) { return this->getOperation()->getOperand(i); }
339 
340  /// Set the operand at index 'i' to 'value'.
341  void setOperand(unsigned i, Value value) {
342  this->getOperation()->setOperand(i, value);
343  }
344 
345  /// Operand iterator access.
347  return this->getOperation()->operand_begin();
348  }
351 
352  /// Operand type access.
354  return this->getOperation()->operand_type_begin();
355  }
357  return this->getOperation()->operand_type_end();
358  }
360  return this->getOperation()->getOperandTypes();
361  }
362 };
363 } // namespace detail
364 
365 /// `verifyInvariantsImpl` verifies the invariants like the types, attrs, .etc.
366 /// It should be run after core traits and before any other user defined traits.
367 /// In order to run it in the correct order, wrap it with OpInvariants trait so
368 /// that tblgen will be able to put it in the right order.
369 template <typename ConcreteType>
370 class OpInvariants : public TraitBase<ConcreteType, OpInvariants> {
371 public:
373  return cast<ConcreteType>(op).verifyInvariantsImpl();
374  }
375 };
376 
377 /// This class provides the API for ops that are known to have no
378 /// SSA operand.
379 template <typename ConcreteType>
380 class ZeroOperands : public TraitBase<ConcreteType, ZeroOperands> {
381 public:
383  return impl::verifyZeroOperands(op);
384  }
385 
386 private:
387  // Disable these.
388  void getOperand() {}
389  void setOperand() {}
390 };
391 
392 /// This class provides the API for ops that are known to have exactly one
393 /// SSA operand.
394 template <typename ConcreteType>
395 class OneOperand : public TraitBase<ConcreteType, OneOperand> {
396 public:
397  Value getOperand() { return this->getOperation()->getOperand(0); }
398 
399  void setOperand(Value value) { this->getOperation()->setOperand(0, value); }
400 
402  return impl::verifyOneOperand(op);
403  }
404 };
405 
406 /// This class provides the API for ops that are known to have a specified
407 /// number of operands. This is used as a trait like this:
408 ///
409 /// class FooOp : public Op<FooOp, OpTrait::NOperands<2>::Impl> {
410 ///
411 template <unsigned N>
412 class NOperands {
413 public:
414  static_assert(N > 1, "use ZeroOperands/OneOperand for N < 2");
415 
416  template <typename ConcreteType>
417  class Impl
418  : public detail::MultiOperandTraitBase<ConcreteType, NOperands<N>::Impl> {
419  public:
421  return impl::verifyNOperands(op, N);
422  }
423  };
424 };
425 
426 /// This class provides the API for ops that are known to have a at least a
427 /// specified number of operands. This is used as a trait like this:
428 ///
429 /// class FooOp : public Op<FooOp, OpTrait::AtLeastNOperands<2>::Impl> {
430 ///
431 template <unsigned N>
433 public:
434  template <typename ConcreteType>
435  class Impl : public detail::MultiOperandTraitBase<ConcreteType,
436  AtLeastNOperands<N>::Impl> {
437  public:
439  return impl::verifyAtLeastNOperands(op, N);
440  }
441  };
442 };
443 
444 /// This class provides the API for ops which have an unknown number of
445 /// SSA operands.
446 template <typename ConcreteType>
448  : public detail::MultiOperandTraitBase<ConcreteType, VariadicOperands> {};
449 
450 //===----------------------------------------------------------------------===//
451 // Region Traits
452 
453 /// This class provides verification for ops that are known to have zero
454 /// regions.
455 template <typename ConcreteType>
456 class ZeroRegions : public TraitBase<ConcreteType, ZeroRegions> {
457 public:
459  return impl::verifyZeroRegions(op);
460  }
461 };
462 
463 namespace detail {
464 /// Utility trait base that provides accessors for derived traits that have
465 /// multiple regions.
466 template <typename ConcreteType, template <typename> class TraitType>
467 struct MultiRegionTraitBase : public TraitBase<ConcreteType, TraitType> {
470 
471  /// Return the number of regions.
472  unsigned getNumRegions() { return this->getOperation()->getNumRegions(); }
473 
474  /// Return the region at `index`.
475  Region &getRegion(unsigned i) { return this->getOperation()->getRegion(i); }
476 
477  /// Region iterator access.
479  return this->getOperation()->region_begin();
480  }
481  region_iterator region_end() { return this->getOperation()->region_end(); }
483 };
484 } // namespace detail
485 
486 /// This class provides APIs for ops that are known to have a single region.
487 template <typename ConcreteType>
488 class OneRegion : public TraitBase<ConcreteType, OneRegion> {
489 public:
490  Region &getRegion() { return this->getOperation()->getRegion(0); }
491 
492  /// Returns a range of operations within the region of this operation.
493  auto getOps() { return getRegion().getOps(); }
494  template <typename OpT>
495  auto getOps() {
496  return getRegion().template getOps<OpT>();
497  }
498 
500  return impl::verifyOneRegion(op);
501  }
502 };
503 
504 /// This class provides the API for ops that are known to have a specified
505 /// number of regions.
506 template <unsigned N>
507 class NRegions {
508 public:
509  static_assert(N > 1, "use ZeroRegions/OneRegion for N < 2");
510 
511  template <typename ConcreteType>
512  class Impl
513  : public detail::MultiRegionTraitBase<ConcreteType, NRegions<N>::Impl> {
514  public:
516  return impl::verifyNRegions(op, N);
517  }
518  };
519 };
520 
521 /// This class provides APIs for ops that are known to have at least a specified
522 /// number of regions.
523 template <unsigned N>
525 public:
526  template <typename ConcreteType>
527  class Impl : public detail::MultiRegionTraitBase<ConcreteType,
528  AtLeastNRegions<N>::Impl> {
529  public:
531  return impl::verifyAtLeastNRegions(op, N);
532  }
533  };
534 };
535 
536 /// This class provides the API for ops which have an unknown number of
537 /// regions.
538 template <typename ConcreteType>
540  : public detail::MultiRegionTraitBase<ConcreteType, VariadicRegions> {};
541 
542 //===----------------------------------------------------------------------===//
543 // Result Traits
544 
545 /// This class provides return value APIs for ops that are known to have
546 /// zero results.
547 template <typename ConcreteType>
548 class ZeroResults : public TraitBase<ConcreteType, ZeroResults> {
549 public:
551  return impl::verifyZeroResults(op);
552  }
553 };
554 
555 namespace detail {
556 /// Utility trait base that provides accessors for derived traits that have
557 /// multiple results.
558 template <typename ConcreteType, template <typename> class TraitType>
559 struct MultiResultTraitBase : public TraitBase<ConcreteType, TraitType> {
564 
565  /// Return the number of results.
566  unsigned getNumResults() { return this->getOperation()->getNumResults(); }
567 
568  /// Return the result at index 'i'.
569  Value getResult(unsigned i) { return this->getOperation()->getResult(i); }
570 
571  /// Replace all uses of results of this operation with the provided 'values'.
572  /// 'values' may correspond to an existing operation, or a range of 'Value'.
573  template <typename ValuesT>
574  void replaceAllUsesWith(ValuesT &&values) {
575  this->getOperation()->replaceAllUsesWith(std::forward<ValuesT>(values));
576  }
577 
578  /// Return the type of the `i`-th result.
579  Type getType(unsigned i) { return getResult(i).getType(); }
580 
581  /// Result iterator access.
583  return this->getOperation()->result_begin();
584  }
587 
588  /// Result type access.
590  return this->getOperation()->result_type_begin();
591  }
593  return this->getOperation()->result_type_end();
594  }
596  return this->getOperation()->getResultTypes();
597  }
598 };
599 } // namespace detail
600 
601 /// This class provides return value APIs for ops that are known to have a
602 /// single result. ResultType is the concrete type returned by getType().
603 template <typename ConcreteType>
604 class OneResult : public TraitBase<ConcreteType, OneResult> {
605 public:
606  /// Replace all uses of 'this' value with the new value, updating anything
607  /// in the IR that uses 'this' to use the other value instead. When this
608  /// returns there are zero uses of 'this'.
609  void replaceAllUsesWith(Value newValue) {
610  this->getOperation()->getResult(0).replaceAllUsesWith(newValue);
611  }
612 
613  /// Replace all uses of 'this' value with the result of 'op'.
615  this->getOperation()->replaceAllUsesWith(op);
616  }
617 
619  return impl::verifyOneResult(op);
620  }
621 };
622 
623 /// This trait is used for return value APIs for ops that are known to have a
624 /// specific type other than `Type`. This allows the "getType()" member to be
625 /// more specific for an op. This should be used in conjunction with OneResult,
626 /// and occur in the trait list before OneResult.
627 template <typename ResultType>
629 public:
630  /// This class provides return value APIs for ops that are known to have a
631  /// single result. ResultType is the concrete type returned by getType().
632  template <typename ConcreteType>
633  class Impl
634  : public TraitBase<ConcreteType, OneTypedResult<ResultType>::Impl> {
635  public:
637  return cast<mlir::TypedValue<ResultType>>(
638  this->getOperation()->getResult(0));
639  }
640 
641  /// If the operation returns a single value, then the Op can be implicitly
642  /// converted to a Value. This yields the value of the only result.
643  operator mlir::TypedValue<ResultType>() { return getResult(); }
644 
645  ResultType getType() { return getResult().getType(); }
646  };
647 };
648 
649 /// This class provides the API for ops that are known to have a specified
650 /// number of results. This is used as a trait like this:
651 ///
652 /// class FooOp : public Op<FooOp, OpTrait::NResults<2>::Impl> {
653 ///
654 template <unsigned N>
655 class NResults {
656 public:
657  static_assert(N > 1, "use ZeroResults/OneResult for N < 2");
658 
659  template <typename ConcreteType>
660  class Impl
661  : public detail::MultiResultTraitBase<ConcreteType, NResults<N>::Impl> {
662  public:
664  return impl::verifyNResults(op, N);
665  }
666  };
667 };
668 
669 /// This class provides the API for ops that are known to have at least a
670 /// specified number of results. This is used as a trait like this:
671 ///
672 /// class FooOp : public Op<FooOp, OpTrait::AtLeastNResults<2>::Impl> {
673 ///
674 template <unsigned N>
676 public:
677  template <typename ConcreteType>
678  class Impl : public detail::MultiResultTraitBase<ConcreteType,
679  AtLeastNResults<N>::Impl> {
680  public:
682  return impl::verifyAtLeastNResults(op, N);
683  }
684  };
685 };
686 
687 /// This class provides the API for ops which have an unknown number of
688 /// results.
689 template <typename ConcreteType>
691  : public detail::MultiResultTraitBase<ConcreteType, VariadicResults> {};
692 
693 //===----------------------------------------------------------------------===//
694 // Terminator Traits
695 
696 /// This class indicates that the regions associated with this op don't have
697 /// terminators.
698 template <typename ConcreteType>
699 class NoTerminator : public TraitBase<ConcreteType, NoTerminator> {};
700 
701 /// This class provides the API for ops that are known to be terminators.
702 template <typename ConcreteType>
703 class IsTerminator : public TraitBase<ConcreteType, IsTerminator> {
704 public:
706  return impl::verifyIsTerminator(op);
707  }
708 };
709 
710 /// This class provides verification for ops that are known to have zero
711 /// successors.
712 template <typename ConcreteType>
713 class ZeroSuccessors : public TraitBase<ConcreteType, ZeroSuccessors> {
714 public:
716  return impl::verifyZeroSuccessors(op);
717  }
718 };
719 
720 namespace detail {
721 /// Utility trait base that provides accessors for derived traits that have
722 /// multiple successors.
723 template <typename ConcreteType, template <typename> class TraitType>
724 struct MultiSuccessorTraitBase : public TraitBase<ConcreteType, TraitType> {
727 
728  /// Return the number of successors.
729  unsigned getNumSuccessors() {
730  return this->getOperation()->getNumSuccessors();
731  }
732 
733  /// Return the successor at `index`.
734  Block *getSuccessor(unsigned i) {
735  return this->getOperation()->getSuccessor(i);
736  }
737 
738  /// Set the successor at `index`.
739  void setSuccessor(Block *block, unsigned i) {
740  return this->getOperation()->setSuccessor(block, i);
741  }
742 
743  /// Successor iterator access.
744  succ_iterator succ_begin() { return this->getOperation()->succ_begin(); }
745  succ_iterator succ_end() { return this->getOperation()->succ_end(); }
747 };
748 } // namespace detail
749 
750 /// This class provides APIs for ops that are known to have a single successor.
751 template <typename ConcreteType>
752 class OneSuccessor : public TraitBase<ConcreteType, OneSuccessor> {
753 public:
754  Block *getSuccessor() { return this->getOperation()->getSuccessor(0); }
755  void setSuccessor(Block *succ) {
756  this->getOperation()->setSuccessor(succ, 0);
757  }
758 
760  return impl::verifyOneSuccessor(op);
761  }
762 };
763 
764 /// This class provides the API for ops that are known to have a specified
765 /// number of successors.
766 template <unsigned N>
767 class NSuccessors {
768 public:
769  static_assert(N > 1, "use ZeroSuccessors/OneSuccessor for N < 2");
770 
771  template <typename ConcreteType>
772  class Impl : public detail::MultiSuccessorTraitBase<ConcreteType,
773  NSuccessors<N>::Impl> {
774  public:
776  return impl::verifyNSuccessors(op, N);
777  }
778  };
779 };
780 
781 /// This class provides APIs for ops that are known to have at least a specified
782 /// number of successors.
783 template <unsigned N>
785 public:
786  template <typename ConcreteType>
787  class Impl
788  : public detail::MultiSuccessorTraitBase<ConcreteType,
789  AtLeastNSuccessors<N>::Impl> {
790  public:
792  return impl::verifyAtLeastNSuccessors(op, N);
793  }
794  };
795 };
796 
797 /// This class provides the API for ops which have an unknown number of
798 /// successors.
799 template <typename ConcreteType>
801  : public detail::MultiSuccessorTraitBase<ConcreteType, VariadicSuccessors> {
802 };
803 
804 //===----------------------------------------------------------------------===//
805 // SingleBlock
806 
807 /// This class provides APIs and verifiers for ops with regions having a single
808 /// block.
809 template <typename ConcreteType>
810 struct SingleBlock : public TraitBase<ConcreteType, SingleBlock> {
811 public:
813  for (unsigned i = 0, e = op->getNumRegions(); i < e; ++i) {
814  Region &region = op->getRegion(i);
815 
816  // Empty regions are fine.
817  if (region.empty())
818  continue;
819 
820  // Non-empty regions must contain a single basic block.
821  if (!llvm::hasSingleElement(region))
822  return op->emitOpError("expects region #")
823  << i << " to have 0 or 1 blocks";
824 
825  if (!ConcreteType::template hasTrait<NoTerminator>()) {
826  Block &block = region.front();
827  if (block.empty())
828  return op->emitOpError() << "expects a non-empty block";
829  }
830  }
831  return success();
832  }
833 
834  Block *getBody(unsigned idx = 0) {
835  Region &region = this->getOperation()->getRegion(idx);
836  assert(!region.empty() && "unexpected empty region");
837  return &region.front();
838  }
839  Region &getBodyRegion(unsigned idx = 0) {
840  return this->getOperation()->getRegion(idx);
841  }
842 
843  //===------------------------------------------------------------------===//
844  // Single Region Utilities
845  //===------------------------------------------------------------------===//
846 
847  /// The following are a set of methods only enabled when the parent
848  /// operation has a single region. Each of these methods take an additional
849  /// template parameter that represents the concrete operation so that we
850  /// can use SFINAE to disable the methods for non-single region operations.
851  template <typename OpT, typename T = void>
853  std::enable_if_t<OpT::template hasTrait<OneRegion>(), T>;
854 
855  template <typename OpT = ConcreteType>
857  return getBody()->begin();
858  }
859  template <typename OpT = ConcreteType>
861  return getBody()->end();
862  }
863  template <typename OpT = ConcreteType>
865  return *begin();
866  }
867 
868  /// Insert the operation into the back of the body.
869  template <typename OpT = ConcreteType>
871  insert(Block::iterator(getBody()->end()), op);
872  }
873 
874  /// Insert the operation at the given insertion point.
875  template <typename OpT = ConcreteType>
877  insert(Block::iterator(insertPt), op);
878  }
879  template <typename OpT = ConcreteType>
881  getBody()->getOperations().insert(insertPt, op);
882  }
883 };
884 
885 //===----------------------------------------------------------------------===//
886 // SingleBlockImplicitTerminator
887 
888 /// This class provides APIs and verifiers for ops with regions having a single
889 /// block that must terminate with `TerminatorOpType`.
890 template <typename TerminatorOpType>
892  template <typename ConcreteType>
893  class Impl : public SingleBlock<ConcreteType> {
894  private:
896  /// Builds a terminator operation without relying on OpBuilder APIs to avoid
897  /// cyclic header inclusion.
898  static Operation *buildTerminator(OpBuilder &builder, Location loc) {
899  OperationState state(loc, TerminatorOpType::getOperationName());
900  TerminatorOpType::build(builder, state);
901  return Operation::create(state);
902  }
903 
904  public:
905  /// The type of the operation used as the implicit terminator type.
906  using ImplicitTerminatorOpT = TerminatorOpType;
907 
909  if (failed(Base::verifyTrait(op)))
910  return failure();
911  for (unsigned i = 0, e = op->getNumRegions(); i < e; ++i) {
912  Region &region = op->getRegion(i);
913  // Empty regions are fine.
914  if (region.empty())
915  continue;
916  Operation &terminator = region.front().back();
917  if (isa<TerminatorOpType>(terminator))
918  continue;
919 
920  return op->emitOpError("expects regions to end with '" +
921  TerminatorOpType::getOperationName() +
922  "', found '" +
923  terminator.getName().getStringRef() + "'")
924  .attachNote()
925  << "in custom textual format, the absence of terminator implies "
926  "'"
927  << TerminatorOpType::getOperationName() << '\'';
928  }
929 
930  return success();
931  }
932 
933  /// Ensure that the given region has the terminator required by this trait.
934  /// If OpBuilder is provided, use it to build the terminator and notify the
935  /// OpBuilder listeners accordingly. If only a Builder is provided, locally
936  /// construct an OpBuilder with no listeners; this should only be used if no
937  /// OpBuilder is available at the call site, e.g., in the parser.
938  static void ensureTerminator(Region &region, Builder &builder,
939  Location loc) {
940  ::mlir::impl::ensureRegionTerminator(region, builder, loc,
941  buildTerminator);
942  }
943  static void ensureTerminator(Region &region, OpBuilder &builder,
944  Location loc) {
945  ::mlir::impl::ensureRegionTerminator(region, builder, loc,
946  buildTerminator);
947  }
948 
949  //===------------------------------------------------------------------===//
950  // Single Region Utilities
951  //===------------------------------------------------------------------===//
952  using Base::getBody;
953 
954  template <typename OpT, typename T = void>
956  std::enable_if_t<OpT::template hasTrait<OneRegion>(), T>;
957 
958  /// Insert the operation into the back of the body, before the terminator.
959  template <typename OpT = ConcreteType>
961  insert(Block::iterator(getBody()->getTerminator()), op);
962  }
963 
964  /// Insert the operation at the given insertion point. Note: The operation
965  /// is never inserted after the terminator, even if the insertion point is
966  /// end().
967  template <typename OpT = ConcreteType>
969  insert(Block::iterator(insertPt), op);
970  }
971  template <typename OpT = ConcreteType>
973  Operation *op) {
974  auto *body = getBody();
975  if (insertPt == body->end())
976  insertPt = Block::iterator(body->getTerminator());
977  body->getOperations().insert(insertPt, op);
978  }
979  };
980 };
981 
982 /// Check is an op defines the `ImplicitTerminatorOpT` member. This is intended
983 /// to be used with `llvm::is_detected`.
984 template <class T>
985 using has_implicit_terminator_t = typename T::ImplicitTerminatorOpT;
986 
987 /// Support to check if an operation has the SingleBlockImplicitTerminator
988 /// trait. We can't just use `hasTrait` because this class is templated on a
989 /// specific terminator op.
990 template <class Op, bool hasTerminator =
991  llvm::is_detected<has_implicit_terminator_t, Op>::value>
993  static constexpr bool value = std::is_base_of<
995  typename Op::ImplicitTerminatorOpT>::template Impl<Op>,
996  Op>::value;
997 };
998 template <class Op>
1000  static constexpr bool value = false;
1001 };
1002 
1003 //===----------------------------------------------------------------------===//
1004 // Misc Traits
1005 
1006 /// This class provides verification for ops that are known to have the same
1007 /// operand shape: all operands are scalars, vectors/tensors of the same
1008 /// shape.
1009 template <typename ConcreteType>
1010 class SameOperandsShape : public TraitBase<ConcreteType, SameOperandsShape> {
1011 public:
1013  return impl::verifySameOperandsShape(op);
1014  }
1015 };
1016 
1017 /// This class provides verification for ops that are known to have the same
1018 /// operand and result shape: both are scalars, vectors/tensors of the same
1019 /// shape.
1020 template <typename ConcreteType>
1022  : public TraitBase<ConcreteType, SameOperandsAndResultShape> {
1023 public:
1026  }
1027 };
1028 
1029 /// This class provides verification for ops that are known to have the same
1030 /// operand element type (or the type itself if it is scalar).
1031 ///
1032 template <typename ConcreteType>
1034  : public TraitBase<ConcreteType, SameOperandsElementType> {
1035 public:
1038  }
1039 };
1040 
1041 /// This class provides verification for ops that are known to have the same
1042 /// operand and result element type (or the type itself if it is scalar).
1043 ///
1044 template <typename ConcreteType>
1046  : public TraitBase<ConcreteType, SameOperandsAndResultElementType> {
1047 public:
1050  }
1051 };
1052 
1053 /// This class provides verification for ops that are known to have the same
1054 /// operand and result type.
1055 ///
1056 /// Note: this trait subsumes the SameOperandsAndResultShape and
1057 /// SameOperandsAndResultElementType traits.
1058 template <typename ConcreteType>
1060  : public TraitBase<ConcreteType, SameOperandsAndResultType> {
1061 public:
1064  }
1065 };
1066 
1067 /// This class verifies that any results of the specified op have a boolean
1068 /// type, a vector thereof, or a tensor thereof.
1069 template <typename ConcreteType>
1070 class ResultsAreBoolLike : public TraitBase<ConcreteType, ResultsAreBoolLike> {
1071 public:
1073  return impl::verifyResultsAreBoolLike(op);
1074  }
1075 };
1076 
1077 /// This class verifies that any results of the specified op have a floating
1078 /// point type, a vector thereof, or a tensor thereof.
1079 template <typename ConcreteType>
1081  : public TraitBase<ConcreteType, ResultsAreFloatLike> {
1082 public:
1085  }
1086 };
1087 
1088 /// This class verifies that any results of the specified op have a signless
1089 /// integer or index type, a vector thereof, or a tensor thereof.
1090 template <typename ConcreteType>
1092  : public TraitBase<ConcreteType, ResultsAreSignlessIntegerLike> {
1093 public:
1096  }
1097 };
1098 
1099 /// This class adds property that the operation is commutative.
1100 template <typename ConcreteType>
1101 class IsCommutative : public TraitBase<ConcreteType, IsCommutative> {};
1102 
1103 /// This class adds property that the operation is an involution.
1104 /// This means a unary to unary operation "f" that satisfies f(f(x)) = x
1105 template <typename ConcreteType>
1106 class IsInvolution : public TraitBase<ConcreteType, IsInvolution> {
1107 public:
1109  static_assert(ConcreteType::template hasTrait<OneResult>(),
1110  "expected operation to produce one result");
1111  static_assert(ConcreteType::template hasTrait<OneOperand>(),
1112  "expected operation to take one operand");
1113  static_assert(ConcreteType::template hasTrait<SameOperandsAndResultType>(),
1114  "expected operation to preserve type");
1115  // Involution requires the operation to be side effect free as well
1116  // but currently this check is under a FIXME and is not actually done.
1117  return impl::verifyIsInvolution(op);
1118  }
1119 
1121  return impl::foldInvolution(op);
1122  }
1123 };
1124 
1125 /// This class adds property that the operation is idempotent.
1126 /// This means a unary to unary operation "f" that satisfies f(f(x)) = f(x),
1127 /// or a binary operation "g" that satisfies g(x, x) = x.
1128 template <typename ConcreteType>
1129 class IsIdempotent : public TraitBase<ConcreteType, IsIdempotent> {
1130 public:
1132  static_assert(ConcreteType::template hasTrait<OneResult>(),
1133  "expected operation to produce one result");
1134  static_assert(ConcreteType::template hasTrait<OneOperand>() ||
1135  ConcreteType::template hasTrait<NOperands<2>::Impl>(),
1136  "expected operation to take one or two operands");
1137  static_assert(ConcreteType::template hasTrait<SameOperandsAndResultType>(),
1138  "expected operation to preserve type");
1139  // Idempotent requires the operation to be side effect free as well
1140  // but currently this check is under a FIXME and is not actually done.
1141  return impl::verifyIsIdempotent(op);
1142  }
1143 
1145  return impl::foldIdempotent(op);
1146  }
1147 };
1148 
1149 /// This class verifies that all operands of the specified op have a float type,
1150 /// a vector thereof, or a tensor thereof.
1151 template <typename ConcreteType>
1153  : public TraitBase<ConcreteType, OperandsAreFloatLike> {
1154 public:
1157  }
1158 };
1159 
1160 /// This class verifies that all operands of the specified op have a signless
1161 /// integer or index type, a vector thereof, or a tensor thereof.
1162 template <typename ConcreteType>
1164  : public TraitBase<ConcreteType, OperandsAreSignlessIntegerLike> {
1165 public:
1168  }
1169 };
1170 
1171 /// This class verifies that all operands of the specified op have the same
1172 /// type.
1173 template <typename ConcreteType>
1174 class SameTypeOperands : public TraitBase<ConcreteType, SameTypeOperands> {
1175 public:
1177  return impl::verifySameTypeOperands(op);
1178  }
1179 };
1180 
1181 /// This class provides the API for a sub-set of ops that are known to be
1182 /// constant-like. These are non-side effecting operations with one result and
1183 /// zero operands that can always be folded to a specific attribute value.
1184 template <typename ConcreteType>
1185 class ConstantLike : public TraitBase<ConcreteType, ConstantLike> {
1186 public:
1188  static_assert(ConcreteType::template hasTrait<OneResult>(),
1189  "expected operation to produce one result");
1190  static_assert(ConcreteType::template hasTrait<ZeroOperands>(),
1191  "expected operation to take zero operands");
1192  // TODO: We should verify that the operation can always be folded, but this
1193  // requires that the attributes of the op already be verified. We should add
1194  // support for verifying traits "after" the operation to enable this use
1195  // case.
1196  return success();
1197  }
1198 };
1199 
1200 /// This class provides the API for ops that are known to be isolated from
1201 /// above.
1202 template <typename ConcreteType>
1204  : public TraitBase<ConcreteType, IsIsolatedFromAbove> {
1205 public:
1208  }
1209 };
1210 
1211 /// A trait of region holding operations that defines a new scope for polyhedral
1212 /// optimization purposes. Any SSA values of 'index' type that either dominate
1213 /// such an operation or are used at the top-level of such an operation
1214 /// automatically become valid symbols for the polyhedral scope defined by that
1215 /// operation. For more details, see `Traits.md#AffineScope`.
1216 template <typename ConcreteType>
1217 class AffineScope : public TraitBase<ConcreteType, AffineScope> {
1218 public:
1220  static_assert(!ConcreteType::template hasTrait<ZeroRegions>(),
1221  "expected operation to have one or more regions");
1222  return success();
1223  }
1224 };
1225 
1226 /// A trait of region holding operations that define a new scope for automatic
1227 /// allocations, i.e., allocations that are freed when control is transferred
1228 /// back from the operation's region. Any operations performing such allocations
1229 /// (for eg. memref.alloca) will have their allocations automatically freed at
1230 /// their closest enclosing operation with this trait.
1231 template <typename ConcreteType>
1233  : public TraitBase<ConcreteType, AutomaticAllocationScope> {
1234 public:
1236  static_assert(!ConcreteType::template hasTrait<ZeroRegions>(),
1237  "expected operation to have one or more regions");
1238  return success();
1239  }
1240 };
1241 
1242 /// This class provides a verifier for ops that are expecting their parent
1243 /// to be one of the given parent ops
1244 template <typename... ParentOpTypes>
1245 struct HasParent {
1246  template <typename ConcreteType>
1247  class Impl : public TraitBase<ConcreteType, Impl> {
1248  public:
1250  if (llvm::isa_and_nonnull<ParentOpTypes...>(op->getParentOp()))
1251  return success();
1252 
1253  return op->emitOpError()
1254  << "expects parent op "
1255  << (sizeof...(ParentOpTypes) != 1 ? "to be one of '" : "'")
1256  << llvm::ArrayRef({ParentOpTypes::getOperationName()...}) << "'";
1257  }
1258  };
1259 };
1260 
1261 /// A trait for operations that have an attribute specifying operand segments.
1262 ///
1263 /// Certain operations can have multiple variadic operands and their size
1264 /// relationship is not always known statically. For such cases, we need
1265 /// a per-op-instance specification to divide the operands into logical groups
1266 /// or segments. This can be modeled by attributes. The attribute will be named
1267 /// as `operand_segment_sizes`.
1268 ///
1269 /// This trait verifies the attribute for specifying operand segments has
1270 /// the correct type (1D vector) and values (non-negative), etc.
1271 template <typename ConcreteType>
1273  : public TraitBase<ConcreteType, AttrSizedOperandSegments> {
1274 public:
1275  static StringRef getOperandSegmentSizeAttr() {
1276  return "operand_segment_sizes";
1277  }
1278 
1282  }
1283 };
1284 
1285 /// Similar to AttrSizedOperandSegments but used for results.
1286 template <typename ConcreteType>
1288  : public TraitBase<ConcreteType, AttrSizedResultSegments> {
1289 public:
1290  static StringRef getResultSegmentSizeAttr() { return "result_segment_sizes"; }
1291 
1294  op, getResultSegmentSizeAttr());
1295  }
1296 };
1297 
1298 /// This trait provides a verifier for ops that are expecting their regions to
1299 /// not have any arguments
1300 template <typename ConcrentType>
1301 struct NoRegionArguments : public TraitBase<ConcrentType, NoRegionArguments> {
1304  }
1305 };
1306 
1307 // This trait is used to flag operations that consume or produce
1308 // values of `MemRef` type where those references can be 'normalized'.
1309 // TODO: Right now, the operands of an operation are either all normalizable,
1310 // or not. In the future, we may want to allow some of the operands to be
1311 // normalizable.
1312 template <typename ConcrentType>
1314  : public TraitBase<ConcrentType, MemRefsNormalizable> {};
1315 
1316 /// This trait tags element-wise ops on vectors or tensors.
1317 ///
1318 /// NOTE: Not all ops that are "elementwise" in some abstract sense satisfy this
1319 /// trait. In particular, broadcasting behavior is not allowed.
1320 ///
1321 /// An `Elementwise` op must satisfy the following properties:
1322 ///
1323 /// 1. If any result is a vector/tensor then at least one operand must also be a
1324 /// vector/tensor.
1325 /// 2. If any operand is a vector/tensor then there must be at least one result
1326 /// and all results must be vectors/tensors.
1327 /// 3. All operand and result vector/tensor types must be of the same shape. The
1328 /// shape may be dynamic in which case the op's behaviour is undefined for
1329 /// non-matching shapes.
1330 /// 4. The operation must be elementwise on its vector/tensor operands and
1331 /// results. When applied to single-element vectors/tensors, the result must
1332 /// be the same per elememnt.
1333 ///
1334 /// TODO: Avoid hardcoding vector/tensor, and generalize this trait to a new
1335 /// interface `ElementwiseTypeInterface` that describes the container types for
1336 /// which the operation is elementwise.
1337 ///
1338 /// Rationale:
1339 /// - 1. and 2. guarantee a well-defined iteration space and exclude the cases
1340 /// of 0 non-scalar operands or 0 non-scalar results, which complicate a
1341 /// generic definition of the iteration space.
1342 /// - 3. guarantees that folding can be done across scalars/vectors/tensors with
1343 /// the same pattern, as otherwise lots of special handling for type
1344 /// mismatches would be needed.
1345 /// - 4. guarantees that no error handling is needed. Higher-level dialects
1346 /// should reify any needed guards or error handling code before lowering to
1347 /// an `Elementwise` op.
1348 template <typename ConcreteType>
1349 struct Elementwise : public TraitBase<ConcreteType, Elementwise> {
1352  }
1353 };
1354 
1355 /// This trait tags `Elementwise` operatons that can be systematically
1356 /// scalarized. All vector/tensor operands and results are then replaced by
1357 /// scalars of the respective element type. Semantically, this is the operation
1358 /// on a single element of the vector/tensor.
1359 ///
1360 /// Rationale:
1361 /// Allow to define the vector/tensor semantics of elementwise operations based
1362 /// on the same op's behavior on scalars. This provides a constructive procedure
1363 /// for IR transformations to, e.g., create scalar loop bodies from tensor ops.
1364 ///
1365 /// Example:
1366 /// ```
1367 /// %tensor_select = "arith.select"(%pred_tensor, %true_val, %false_val)
1368 /// : (tensor<?xi1>, tensor<?xf32>, tensor<?xf32>)
1369 /// -> tensor<?xf32>
1370 /// ```
1371 /// can be scalarized to
1372 ///
1373 /// ```
1374 /// %scalar_select = "arith.select"(%pred, %true_val_scalar, %false_val_scalar)
1375 /// : (i1, f32, f32) -> f32
1376 /// ```
1377 template <typename ConcreteType>
1378 struct Scalarizable : public TraitBase<ConcreteType, Scalarizable> {
1380  static_assert(
1381  ConcreteType::template hasTrait<Elementwise>(),
1382  "`Scalarizable` trait is only applicable to `Elementwise` ops.");
1383  return success();
1384  }
1385 };
1386 
1387 /// This trait tags `Elementwise` operatons that can be systematically
1388 /// vectorized. All scalar operands and results are then replaced by vectors
1389 /// with the respective element type. Semantically, this is the operation on
1390 /// multiple elements simultaneously. See also `Tensorizable`.
1391 ///
1392 /// Rationale:
1393 /// Provide the reverse to `Scalarizable` which, when chained together, allows
1394 /// reasoning about the relationship between the tensor and vector case.
1395 /// Additionally, it permits reasoning about promoting scalars to vectors via
1396 /// broadcasting in cases like `%select_scalar_pred` below.
1397 template <typename ConcreteType>
1398 struct Vectorizable : public TraitBase<ConcreteType, Vectorizable> {
1400  static_assert(
1401  ConcreteType::template hasTrait<Elementwise>(),
1402  "`Vectorizable` trait is only applicable to `Elementwise` ops.");
1403  return success();
1404  }
1405 };
1406 
1407 /// This trait tags `Elementwise` operatons that can be systematically
1408 /// tensorized. All scalar operands and results are then replaced by tensors
1409 /// with the respective element type. Semantically, this is the operation on
1410 /// multiple elements simultaneously. See also `Vectorizable`.
1411 ///
1412 /// Rationale:
1413 /// Provide the reverse to `Scalarizable` which, when chained together, allows
1414 /// reasoning about the relationship between the tensor and vector case.
1415 /// Additionally, it permits reasoning about promoting scalars to tensors via
1416 /// broadcasting in cases like `%select_scalar_pred` below.
1417 ///
1418 /// Examples:
1419 /// ```
1420 /// %scalar = "arith.addf"(%a, %b) : (f32, f32) -> f32
1421 /// ```
1422 /// can be tensorized to
1423 /// ```
1424 /// %tensor = "arith.addf"(%a, %b) : (tensor<?xf32>, tensor<?xf32>)
1425 /// -> tensor<?xf32>
1426 /// ```
1427 ///
1428 /// ```
1429 /// %scalar_pred = "arith.select"(%pred, %true_val, %false_val)
1430 /// : (i1, tensor<?xf32>, tensor<?xf32>) -> tensor<?xf32>
1431 /// ```
1432 /// can be tensorized to
1433 /// ```
1434 /// %tensor_pred = "arith.select"(%pred, %true_val, %false_val)
1435 /// : (tensor<?xi1>, tensor<?xf32>, tensor<?xf32>)
1436 /// -> tensor<?xf32>
1437 /// ```
1438 template <typename ConcreteType>
1439 struct Tensorizable : public TraitBase<ConcreteType, Tensorizable> {
1441  static_assert(
1442  ConcreteType::template hasTrait<Elementwise>(),
1443  "`Tensorizable` trait is only applicable to `Elementwise` ops.");
1444  return success();
1445  }
1446 };
1447 
1448 /// Together, `Elementwise`, `Scalarizable`, `Vectorizable`, and `Tensorizable`
1449 /// provide an easy way for scalar operations to conveniently generalize their
1450 /// behavior to vectors/tensors, and systematize conversion between these forms.
1452 
1453 } // namespace OpTrait
1454 
1455 //===----------------------------------------------------------------------===//
1456 // Internal Trait Utilities
1457 //===----------------------------------------------------------------------===//
1458 
1459 namespace op_definition_impl {
1460 //===----------------------------------------------------------------------===//
1461 // Trait Existence
1462 
1463 /// Returns true if this given Trait ID matches the IDs of any of the provided
1464 /// trait types `Traits`.
1465 template <template <typename T> class... Traits>
1466 static bool hasTrait(TypeID traitID) {
1467  TypeID traitIDs[] = {TypeID::get<Traits>()...};
1468  for (unsigned i = 0, e = sizeof...(Traits); i != e; ++i)
1469  if (traitIDs[i] == traitID)
1470  return true;
1471  return false;
1472 }
1473 
1474 //===----------------------------------------------------------------------===//
1475 // Trait Folding
1476 
1477 /// Trait to check if T provides a 'foldTrait' method for single result
1478 /// operations.
1479 template <typename T, typename... Args>
1481  std::declval<Operation *>(), std::declval<ArrayRef<Attribute>>()));
1482 template <typename T>
1484  llvm::is_detected<has_single_result_fold_trait, T>;
1485 /// Trait to check if T provides a general 'foldTrait' method.
1486 template <typename T, typename... Args>
1488  decltype(T::foldTrait(std::declval<Operation *>(),
1489  std::declval<ArrayRef<Attribute>>(),
1490  std::declval<SmallVectorImpl<OpFoldResult> &>()));
1491 template <typename T>
1492 using detect_has_fold_trait = llvm::is_detected<has_fold_trait, T>;
1493 /// Trait to check if T provides any `foldTrait` method.
1494 template <typename T>
1496  std::disjunction<detect_has_fold_trait<T>,
1498 
1499 /// Returns the result of folding a trait that implements a `foldTrait` function
1500 /// that is specialized for operations that have a single result.
1501 template <typename Trait>
1502 static std::enable_if_t<detect_has_single_result_fold_trait<Trait>::value,
1503  LogicalResult>
1505  SmallVectorImpl<OpFoldResult> &results) {
1506  assert(op->hasTrait<OpTrait::OneResult>() &&
1507  "expected trait on non single-result operation to implement the "
1508  "general `foldTrait` method");
1509  // If a previous trait has already been folded and replaced this operation, we
1510  // fail to fold this trait.
1511  if (!results.empty())
1512  return failure();
1513 
1514  if (OpFoldResult result = Trait::foldTrait(op, operands)) {
1515  if (result.template dyn_cast<Value>() != op->getResult(0))
1516  results.push_back(result);
1517  return success();
1518  }
1519  return failure();
1520 }
1521 /// Returns the result of folding a trait that implements a generalized
1522 /// `foldTrait` function that is supports any operation type.
1523 template <typename Trait>
1524 static std::enable_if_t<detect_has_fold_trait<Trait>::value, LogicalResult>
1526  SmallVectorImpl<OpFoldResult> &results) {
1527  // If a previous trait has already been folded and replaced this operation, we
1528  // fail to fold this trait.
1529  return results.empty() ? Trait::foldTrait(op, operands, results) : failure();
1530 }
1531 template <typename Trait>
1532 static inline std::enable_if_t<!detect_has_any_fold_trait<Trait>::value,
1533  LogicalResult>
1535  return failure();
1536 }
1537 
1538 /// Given a tuple type containing a set of traits, return the result of folding
1539 /// the given operation.
1540 template <typename... Ts>
1542  SmallVectorImpl<OpFoldResult> &results) {
1543  return success((succeeded(foldTrait<Ts>(op, operands, results)) || ...));
1544 }
1545 
1546 //===----------------------------------------------------------------------===//
1547 // Trait Verification
1548 
1549 /// Trait to check if T provides a `verifyTrait` method.
1550 template <typename T, typename... Args>
1551 using has_verify_trait = decltype(T::verifyTrait(std::declval<Operation *>()));
1552 template <typename T>
1553 using detect_has_verify_trait = llvm::is_detected<has_verify_trait, T>;
1554 
1555 /// Trait to check if T provides a `verifyTrait` method.
1556 template <typename T, typename... Args>
1558  decltype(T::verifyRegionTrait(std::declval<Operation *>()));
1559 template <typename T>
1561  llvm::is_detected<has_verify_region_trait, T>;
1562 
1563 /// Verify the given trait if it provides a verifier.
1564 template <typename T>
1565 std::enable_if_t<detect_has_verify_trait<T>::value, LogicalResult>
1567  return T::verifyTrait(op);
1568 }
1569 template <typename T>
1570 inline std::enable_if_t<!detect_has_verify_trait<T>::value, LogicalResult>
1572  return success();
1573 }
1574 
1575 /// Given a set of traits, return the result of verifying the given operation.
1576 template <typename... Ts>
1578  return success((succeeded(verifyTrait<Ts>(op)) && ...));
1579 }
1580 
1581 /// Verify the given trait if it provides a region verifier.
1582 template <typename T>
1583 std::enable_if_t<detect_has_verify_region_trait<T>::value, LogicalResult>
1585  return T::verifyRegionTrait(op);
1586 }
1587 template <typename T>
1588 inline std::enable_if_t<!detect_has_verify_region_trait<T>::value,
1589  LogicalResult>
1591  return success();
1592 }
1593 
1594 /// Given a set of traits, return the result of verifying the regions of the
1595 /// given operation.
1596 template <typename... Ts>
1598  return success((succeeded(verifyRegionTrait<Ts>(op)) && ...));
1599 }
1600 } // namespace op_definition_impl
1601 
1602 //===----------------------------------------------------------------------===//
1603 // Operation Definition classes
1604 //===----------------------------------------------------------------------===//
1605 
1606 /// This provides public APIs that all operations should have. The template
1607 /// argument 'ConcreteType' should be the concrete type by CRTP and the others
1608 /// are base classes by the policy pattern.
1609 template <typename ConcreteType, template <typename T> class... Traits>
1610 class Op : public OpState, public Traits<ConcreteType>... {
1611 public:
1612  /// Inherit getOperation from `OpState`.
1616 
1617  /// Return if this operation contains the provided trait.
1618  template <template <typename T> class Trait>
1619  static constexpr bool hasTrait() {
1620  return llvm::is_one_of<Trait<ConcreteType>, Traits<ConcreteType>...>::value;
1621  }
1622 
1623  /// Create a deep copy of this operation.
1624  ConcreteType clone() { return cast<ConcreteType>(getOperation()->clone()); }
1625 
1626  /// Create a partial copy of this operation without traversing into attached
1627  /// regions. The new operation will have the same number of regions as the
1628  /// original one, but they will be left empty.
1629  ConcreteType cloneWithoutRegions() {
1630  return cast<ConcreteType>(getOperation()->cloneWithoutRegions());
1631  }
1632 
1633  /// Return true if this "op class" can match against the specified operation.
1634  static bool classof(Operation *op) {
1635  if (auto info = op->getRegisteredInfo())
1636  return TypeID::get<ConcreteType>() == info->getTypeID();
1637 #ifndef NDEBUG
1638  if (op->getName().getStringRef() == ConcreteType::getOperationName())
1639  llvm::report_fatal_error(
1640  "classof on '" + ConcreteType::getOperationName() +
1641  "' failed due to the operation not being registered");
1642 #endif
1643  return false;
1644  }
1645  /// Provide `classof` support for other OpBase derived classes, such as
1646  /// Interfaces.
1647  template <typename T>
1648  static std::enable_if_t<std::is_base_of<OpState, T>::value, bool>
1649  classof(const T *op) {
1650  return classof(const_cast<T *>(op)->getOperation());
1651  }
1652 
1653  /// Expose the type we are instantiated on to template machinery that may want
1654  /// to introspect traits on this operation.
1655  using ConcreteOpType = ConcreteType;
1656 
1657  /// This is a public constructor. Any op can be initialized to null.
1658  explicit Op() : OpState(nullptr) {}
1659  Op(std::nullptr_t) : OpState(nullptr) {}
1660 
1661  /// This is a public constructor to enable access via the llvm::cast family of
1662  /// methods. This should not be used directly.
1663  explicit Op(Operation *state) : OpState(state) {}
1664 
1665  /// Methods for supporting PointerLikeTypeTraits.
1666  const void *getAsOpaquePointer() const {
1667  return static_cast<const void *>((Operation *)*this);
1668  }
1669  static ConcreteOpType getFromOpaquePointer(const void *pointer) {
1670  return ConcreteOpType(
1671  reinterpret_cast<Operation *>(const_cast<void *>(pointer)));
1672  }
1673 
1674  /// Attach the given models as implementations of the corresponding
1675  /// interfaces for the concrete operation.
1676  template <typename... Models>
1677  static void attachInterface(MLIRContext &context) {
1678  std::optional<RegisteredOperationName> info =
1679  RegisteredOperationName::lookup(ConcreteType::getOperationName(),
1680  &context);
1681  if (!info)
1682  llvm::report_fatal_error(
1683  "Attempting to attach an interface to an unregistered operation " +
1684  ConcreteType::getOperationName() + ".");
1685  (checkInterfaceTarget<Models>(), ...);
1686  info->attachInterface<Models...>();
1687  }
1688 
1689 private:
1690  /// Trait to check if T provides a 'fold' method for a single result op.
1691  template <typename T, typename... Args>
1692  using has_single_result_fold_t =
1693  decltype(std::declval<T>().fold(std::declval<ArrayRef<Attribute>>()));
1694  template <typename T>
1695  constexpr static bool has_single_result_fold_v =
1696  llvm::is_detected<has_single_result_fold_t, T>::value;
1697  /// Trait to check if T provides a general 'fold' method.
1698  template <typename T, typename... Args>
1699  using has_fold_t = decltype(std::declval<T>().fold(
1700  std::declval<ArrayRef<Attribute>>(),
1701  std::declval<SmallVectorImpl<OpFoldResult> &>()));
1702  template <typename T>
1703  constexpr static bool has_fold_v = llvm::is_detected<has_fold_t, T>::value;
1704  /// Trait to check if T provides a 'fold' method with a FoldAdaptor for a
1705  /// single result op.
1706  template <typename T, typename... Args>
1707  using has_fold_adaptor_single_result_fold_t =
1708  decltype(std::declval<T>().fold(std::declval<typename T::FoldAdaptor>()));
1709  template <class T>
1710  constexpr static bool has_fold_adaptor_single_result_v =
1711  llvm::is_detected<has_fold_adaptor_single_result_fold_t, T>::value;
1712  /// Trait to check if T provides a general 'fold' method with a FoldAdaptor.
1713  template <typename T, typename... Args>
1714  using has_fold_adaptor_fold_t = decltype(std::declval<T>().fold(
1715  std::declval<typename T::FoldAdaptor>(),
1716  std::declval<SmallVectorImpl<OpFoldResult> &>()));
1717  template <class T>
1718  constexpr static bool has_fold_adaptor_v =
1719  llvm::is_detected<has_fold_adaptor_fold_t, T>::value;
1720 
1721  /// Trait to check if T provides a 'print' method.
1722  template <typename T, typename... Args>
1723  using has_print =
1724  decltype(std::declval<T>().print(std::declval<OpAsmPrinter &>()));
1725  template <typename T>
1726  using detect_has_print = llvm::is_detected<has_print, T>;
1727 
1728  /// Trait to check if T provides a 'ConcreteEntity' type alias.
1729  template <typename T>
1730  using has_concrete_entity_t = typename T::ConcreteEntity;
1731 
1732  /// A struct-wrapped type alias to T::ConcreteEntity if provided and to
1733  /// ConcreteType otherwise. This is akin to std::conditional but doesn't fail
1734  /// on the missing typedef. Useful for checking if the interface is targeting
1735  /// the right class.
1736  template <typename T,
1737  bool = llvm::is_detected<has_concrete_entity_t, T>::value>
1738  struct InterfaceTargetOrOpT {
1739  using type = typename T::ConcreteEntity;
1740  };
1741  template <typename T>
1742  struct InterfaceTargetOrOpT<T, false> {
1743  using type = ConcreteType;
1744  };
1745 
1746  /// A hook for static assertion that the external interface model T is
1747  /// targeting the concrete type of this op. The model can also be a fallback
1748  /// model that works for every op.
1749  template <typename T>
1750  static void checkInterfaceTarget() {
1751  static_assert(std::is_same<typename InterfaceTargetOrOpT<T>::type,
1752  ConcreteType>::value,
1753  "attaching an interface to the wrong op kind");
1754  }
1755 
1756  /// Returns an interface map containing the interfaces registered to this
1757  /// operation.
1758  static detail::InterfaceMap getInterfaceMap() {
1759  return detail::InterfaceMap::template get<Traits<ConcreteType>...>();
1760  }
1761 
1762  /// Return the internal implementations of each of the OperationName
1763  /// hooks.
1764  /// Implementation of `FoldHookFn` OperationName hook.
1765  static OperationName::FoldHookFn getFoldHookFn() {
1766  // If the operation is single result and defines a `fold` method.
1767  if constexpr (llvm::is_one_of<OpTrait::OneResult<ConcreteType>,
1768  Traits<ConcreteType>...>::value &&
1769  (has_single_result_fold_v<ConcreteType> ||
1770  has_fold_adaptor_single_result_v<ConcreteType>))
1771  return [](Operation *op, ArrayRef<Attribute> operands,
1772  SmallVectorImpl<OpFoldResult> &results) {
1773  return foldSingleResultHook<ConcreteType>(op, operands, results);
1774  };
1775  // The operation is not single result and defines a `fold` method.
1776  if constexpr (has_fold_v<ConcreteType> || has_fold_adaptor_v<ConcreteType>)
1777  return [](Operation *op, ArrayRef<Attribute> operands,
1778  SmallVectorImpl<OpFoldResult> &results) {
1779  return foldHook<ConcreteType>(op, operands, results);
1780  };
1781  // The operation does not define a `fold` method.
1782  return [](Operation *op, ArrayRef<Attribute> operands,
1783  SmallVectorImpl<OpFoldResult> &results) {
1784  // In this case, we only need to fold the traits of the operation.
1785  return op_definition_impl::foldTraits<Traits<ConcreteType>...>(
1786  op, operands, results);
1787  };
1788  }
1789  /// Return the result of folding a single result operation that defines a
1790  /// `fold` method.
1791  template <typename ConcreteOpT>
1792  static LogicalResult
1793  foldSingleResultHook(Operation *op, ArrayRef<Attribute> operands,
1794  SmallVectorImpl<OpFoldResult> &results) {
1795  OpFoldResult result;
1796  if constexpr (has_fold_adaptor_single_result_v<ConcreteOpT>)
1797  result = cast<ConcreteOpT>(op).fold(typename ConcreteOpT::FoldAdaptor(
1798  operands, op->getAttrDictionary(), op->getRegions()));
1799  else
1800  result = cast<ConcreteOpT>(op).fold(operands);
1801 
1802  // If the fold failed or was in-place, try to fold the traits of the
1803  // operation.
1804  if (!result || result.template dyn_cast<Value>() == op->getResult(0)) {
1805  if (succeeded(op_definition_impl::foldTraits<Traits<ConcreteType>...>(
1806  op, operands, results)))
1807  return success();
1808  return success(static_cast<bool>(result));
1809  }
1810  results.push_back(result);
1811  return success();
1812  }
1813  /// Return the result of folding an operation that defines a `fold` method.
1814  template <typename ConcreteOpT>
1815  static LogicalResult foldHook(Operation *op, ArrayRef<Attribute> operands,
1816  SmallVectorImpl<OpFoldResult> &results) {
1817  auto result = LogicalResult::failure();
1818  if constexpr (has_fold_adaptor_v<ConcreteOpT>) {
1819  result = cast<ConcreteOpT>(op).fold(
1820  typename ConcreteOpT::FoldAdaptor(operands, op->getAttrDictionary(),
1821  op->getRegions()),
1822  results);
1823  } else {
1824  result = cast<ConcreteOpT>(op).fold(operands, results);
1825  }
1826 
1827  // If the fold failed or was in-place, try to fold the traits of the
1828  // operation.
1829  if (failed(result) || results.empty()) {
1830  if (succeeded(op_definition_impl::foldTraits<Traits<ConcreteType>...>(
1831  op, operands, results)))
1832  return success();
1833  }
1834  return result;
1835  }
1836 
1837  /// Implementation of `GetHasTraitFn`
1838  static OperationName::HasTraitFn getHasTraitFn() {
1839  return
1840  [](TypeID id) { return op_definition_impl::hasTrait<Traits...>(id); };
1841  }
1842  /// Implementation of `PrintAssemblyFn` OperationName hook.
1843  static OperationName::PrintAssemblyFn getPrintAssemblyFn() {
1844  if constexpr (detect_has_print<ConcreteType>::value)
1845  return [](Operation *op, OpAsmPrinter &p, StringRef defaultDialect) {
1846  OpState::printOpName(op, p, defaultDialect);
1847  return cast<ConcreteType>(op).print(p);
1848  };
1849  return [](Operation *op, OpAsmPrinter &printer, StringRef defaultDialect) {
1850  return OpState::print(op, printer, defaultDialect);
1851  };
1852  }
1853 
1854  /// Implementation of `PopulateDefaultAttrsFn` OperationName hook.
1855  static OperationName::PopulateDefaultAttrsFn getPopulateDefaultAttrsFn() {
1856  return ConcreteType::populateDefaultAttrs;
1857  }
1858  /// Implementation of `VerifyInvariantsFn` OperationName hook.
1859  static LogicalResult verifyInvariants(Operation *op) {
1860  static_assert(hasNoDataMembers(),
1861  "Op class shouldn't define new data members");
1862  return failure(
1863  failed(op_definition_impl::verifyTraits<Traits<ConcreteType>...>(op)) ||
1864  failed(cast<ConcreteType>(op).verify()));
1865  }
1866  static OperationName::VerifyInvariantsFn getVerifyInvariantsFn() {
1867  return static_cast<LogicalResult (*)(Operation *)>(&verifyInvariants);
1868  }
1869  /// Implementation of `VerifyRegionInvariantsFn` OperationName hook.
1870  static LogicalResult verifyRegionInvariants(Operation *op) {
1871  static_assert(hasNoDataMembers(),
1872  "Op class shouldn't define new data members");
1873  return failure(
1874  failed(op_definition_impl::verifyRegionTraits<Traits<ConcreteType>...>(
1875  op)) ||
1876  failed(cast<ConcreteType>(op).verifyRegions()));
1877  }
1878  static OperationName::VerifyRegionInvariantsFn getVerifyRegionInvariantsFn() {
1879  return static_cast<LogicalResult (*)(Operation *)>(&verifyRegionInvariants);
1880  }
1881 
1882  static constexpr bool hasNoDataMembers() {
1883  // Checking that the derived class does not define any member by comparing
1884  // its size to an ad-hoc EmptyOp.
1885  class EmptyOp : public Op<EmptyOp, Traits...> {};
1886  return sizeof(ConcreteType) == sizeof(EmptyOp);
1887  }
1888 
1889  /// Allow access to internal implementation methods.
1890  friend RegisteredOperationName;
1891 };
1892 
1893 /// This class represents the base of an operation interface. See the definition
1894 /// of `detail::Interface` for requirements on the `Traits` type.
1895 template <typename ConcreteType, typename Traits>
1897  : public detail::Interface<ConcreteType, Operation *, Traits,
1898  Op<ConcreteType>, OpTrait::TraitBase> {
1899 public:
1901  using InterfaceBase = detail::Interface<ConcreteType, Operation *, Traits,
1903 
1904  /// Inherit the base class constructor.
1906 
1907 protected:
1908  /// Returns the impl interface instance for the given operation.
1910  OperationName name = op->getName();
1911 
1912  // Access the raw interface from the operation info.
1913  if (std::optional<RegisteredOperationName> rInfo =
1914  name.getRegisteredInfo()) {
1915  if (auto *opIface = rInfo->getInterface<ConcreteType>())
1916  return opIface;
1917  // Fallback to the dialect to provide it with a chance to implement this
1918  // interface for this operation.
1919  return rInfo->getDialect().getRegisteredInterfaceForOp<ConcreteType>(
1920  op->getName());
1921  }
1922  // Fallback to the dialect to provide it with a chance to implement this
1923  // interface for this operation.
1924  if (Dialect *dialect = name.getDialect())
1925  return dialect->getRegisteredInterfaceForOp<ConcreteType>(name);
1926  return nullptr;
1927  }
1928 
1929  /// Allow access to `getInterfaceFor`.
1931 };
1932 
1933 //===----------------------------------------------------------------------===//
1934 // CastOpInterface utilities
1935 //===----------------------------------------------------------------------===//
1936 
1937 // These functions are out-of-line implementations of the methods in
1938 // CastOpInterface, which avoids them being template instantiated/duplicated.
1939 namespace impl {
1940 /// Attempt to fold the given cast operation.
1942  ArrayRef<Attribute> attrOperands,
1943  SmallVectorImpl<OpFoldResult> &foldResults);
1944 /// Attempt to verify the given cast operation.
1946  Operation *op, function_ref<bool(TypeRange, TypeRange)> areCastCompatible);
1947 } // namespace impl
1948 } // namespace mlir
1949 
1950 namespace llvm {
1951 
1952 template <typename T>
1953 struct DenseMapInfo<T,
1954  std::enable_if_t<std::is_base_of<mlir::OpState, T>::value &&
1955  !mlir::detail::IsInterface<T>::value>> {
1956  static inline T getEmptyKey() {
1957  auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
1958  return T::getFromOpaquePointer(pointer);
1959  }
1960  static inline T getTombstoneKey() {
1962  return T::getFromOpaquePointer(pointer);
1963  }
1964  static unsigned getHashValue(T val) {
1965  return hash_value(val.getAsOpaquePointer());
1966  }
1967  static bool isEqual(T lhs, T rhs) { return lhs == rhs; }
1968 };
1969 
1970 } // namespace llvm
1971 
1972 #endif
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
This class provides management for the lifetime of the state used when printing the IR.
Definition: AsmState.h:525
Attributes are known-constant values of operations.
Definition: Attributes.h:25
Block represents an ordered list of Operations.
Definition: Block.h:30
OpListType::iterator iterator
Definition: Block.h:129
bool empty()
Definition: Block.h:137
Operation & back()
Definition: Block.h:141
OpListType & getOperations()
Definition: Block.h:126
iterator end()
Definition: Block.h:133
iterator begin()
Definition: Block.h:132
This class is a general helper class for creating context-global objects like types,...
Definition: Builders.h:50
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
virtual void * getRegisteredInterfaceForOp(TypeID interfaceID, OperationName opName)
Lookup an op interface for the given ID if one is registered, otherwise nullptr.
Definition: Dialect.h:173
This class represents a diagnostic that is inflight and set to be reported.
Definition: Diagnostics.h:308
Diagnostic & attachNote(std::optional< Location > noteLoc=std::nullopt)
Attaches a note to this diagnostic.
Definition: Diagnostics.h:346
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
NamedAttrList is array of NamedAttributes that tracks whether it is sorted and does some basic work t...
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
This class helps build Operations.
Definition: Builders.h:202
This class represents a single result from folding an operation.
Definition: OpDefinition.h:235
void dump() const
Definition: OpDefinition.h:239
This class represents the base of an operation interface.
friend InterfaceBase
Allow access to getInterfaceFor.
static InterfaceBase::Concept * getInterfaceFor(Operation *op)
Returns the impl interface instance for the given operation.
Set of flags used to control the behavior of the various IR print methods (e.g.
This is the concrete base class that holds the operation pointer and has non-generic methods that onl...
Definition: OpDefinition.h:80
void dump()
Dump this operation.
Definition: OpDefinition.h:106
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==2, RetT > walk(FnT &&callback)
Generic walker with a stage aware callback.
Definition: OpDefinition.h:177
MLIRContext * getContext()
Return the context this operation belongs to.
Definition: OpDefinition.h:95
void erase()
Remove this operation from its parent block and delete it.
Definition: OpDefinition.h:115
bool use_empty()
Return true if there are no users of any results of this operation.
Definition: OpDefinition.h:112
LogicalResult verify()
If the concrete type didn't implement a custom verifier hook, just fall back to this one which accept...
Definition: OpDefinition.h:194
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Definition: OpDefinition.h:149
void print(raw_ostream &os, AsmState &asmState)
Definition: OpDefinition.h:101
static void printOpName(Operation *op, OpAsmPrinter &p, StringRef defaultDialect)
Print an operation name, eliding the dialect prefix if necessary.
Definition: Operation.cpp:631
LogicalResult verifyRegions()
Definition: OpDefinition.h:195
InFlightDiagnostic emitError(const Twine &message={})
Emit an error about fatal conditions with this operation, reporting up to any diagnostic handlers tha...
Definition: Operation.cpp:641
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:647
InFlightDiagnostic emitWarning(const Twine &message={})
Emit a warning about this operation, reporting up to any diagnostic handlers that may be listening.
Definition: Operation.cpp:653
Operation * getOperation()
Return the operation that this refers to.
Definition: OpDefinition.h:92
static void getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context)
This hook returns any canonicalization pattern rewrites that the operation supports,...
Definition: OpDefinition.h:185
static ParseResult parse(OpAsmParser &parser, OperationState &result)
Parse the custom form of an operation.
Definition: Operation.cpp:611
InFlightDiagnostic emitRemark(const Twine &message={})
Emit a remark about this operation, reporting up to any diagnostic handlers that may be listening.
Definition: Operation.cpp:659
OpState(Operation *state)
Mutability management is handled by the OpWrapper/OpConstWrapper classes, so we can cast it away here...
Definition: OpDefinition.h:215
Location getLoc()
The source location the operation was defined or derived from.
Definition: OpDefinition.h:109
static void populateDefaultAttrs(const OperationName &, NamedAttrList &)
This hook populates any unset default attrs.
Definition: OpDefinition.h:189
void print(raw_ostream &os, OpPrintingFlags flags=std::nullopt)
Print the operation to the given stream.
Definition: OpDefinition.h:98
Operation * operator->() const
Shortcut of -> to access a member of Operation.
Definition: OpDefinition.h:89
A trait of region holding operations that defines a new scope for polyhedral optimization purposes.
static LogicalResult verifyTrait(Operation *op)
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:438
This class provides the API for ops that are known to have a at least a specified number of operands.
Definition: OpDefinition.h:432
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:530
This class provides APIs for ops that are known to have at least a specified number of regions.
Definition: OpDefinition.h:524
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:681
This class provides the API for ops that are known to have at least a specified number of results.
Definition: OpDefinition.h:675
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:791
This class provides APIs for ops that are known to have at least a specified number of successors.
Definition: OpDefinition.h:784
A trait for operations that have an attribute specifying operand segments.
static LogicalResult verifyTrait(Operation *op)
Similar to AttrSizedOperandSegments but used for results.
static LogicalResult verifyTrait(Operation *op)
A trait of region holding operations that define a new scope for automatic allocations,...
static LogicalResult verifyTrait(Operation *op)
This class provides the API for a sub-set of ops that are known to be constant-like.
static LogicalResult verifyTrait(Operation *op)
static LogicalResult verifyTrait(Operation *op)
This class adds property that the operation is commutative.
This class adds property that the operation is idempotent.
static OpFoldResult foldTrait(Operation *op, ArrayRef< Attribute > operands)
static LogicalResult verifyTrait(Operation *op)
This class adds property that the operation is an involution.
static LogicalResult verifyTrait(Operation *op)
static OpFoldResult foldTrait(Operation *op, ArrayRef< Attribute > operands)
This class provides the API for ops that are known to be isolated from above.
static LogicalResult verifyRegionTrait(Operation *op)
This class provides the API for ops that are known to be terminators.
Definition: OpDefinition.h:703
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:705
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:420
This class provides the API for ops that are known to have a specified number of operands.
Definition: OpDefinition.h:412
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:515
This class provides the API for ops that are known to have a specified number of regions.
Definition: OpDefinition.h:507
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:663
This class provides the API for ops that are known to have a specified number of results.
Definition: OpDefinition.h:655
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:775
This class provides the API for ops that are known to have a specified number of successors.
Definition: OpDefinition.h:767
This class indicates that the regions associated with this op don't have terminators.
Definition: OpDefinition.h:699
This class provides the API for ops that are known to have exactly one SSA operand.
Definition: OpDefinition.h:395
void setOperand(Value value)
Definition: OpDefinition.h:399
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:401
This class provides APIs for ops that are known to have a single region.
Definition: OpDefinition.h:488
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:499
auto getOps()
Returns a range of operations within the region of this operation.
Definition: OpDefinition.h:493
This class provides return value APIs for ops that are known to have a single result.
Definition: OpDefinition.h:604
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:618
void replaceAllUsesWith(Operation *op)
Replace all uses of 'this' value with the result of 'op'.
Definition: OpDefinition.h:614
void replaceAllUsesWith(Value newValue)
Replace all uses of 'this' value with the new value, updating anything in the IR that uses 'this' to ...
Definition: OpDefinition.h:609
This class provides APIs for ops that are known to have a single successor.
Definition: OpDefinition.h:752
void setSuccessor(Block *succ)
Definition: OpDefinition.h:755
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:759
This class provides return value APIs for ops that are known to have a single result.
Definition: OpDefinition.h:634
mlir::TypedValue< ResultType > getResult()
Definition: OpDefinition.h:636
This trait is used for return value APIs for ops that are known to have a specific type other than Ty...
Definition: OpDefinition.h:628
verifyInvariantsImpl verifies the invariants like the types, attrs, .etc.
Definition: OpDefinition.h:370
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:372
This class verifies that all operands of the specified op have a float type, a vector thereof,...
static LogicalResult verifyTrait(Operation *op)
This class verifies that all operands of the specified op have a signless integer or index type,...
static LogicalResult verifyTrait(Operation *op)
This class verifies that any results of the specified op have a boolean type, a vector thereof,...
static LogicalResult verifyTrait(Operation *op)
This class verifies that any results of the specified op have a floating point type,...
static LogicalResult verifyTrait(Operation *op)
This class verifies that any results of the specified op have a signless integer or index type,...
static LogicalResult verifyTrait(Operation *op)
This class provides verification for ops that are known to have the same operand and result element t...
static LogicalResult verifyTrait(Operation *op)
This class provides verification for ops that are known to have the same operand and result shape: bo...
static LogicalResult verifyTrait(Operation *op)
This class provides verification for ops that are known to have the same operand and result type.
static LogicalResult verifyTrait(Operation *op)
This class provides verification for ops that are known to have the same operand element type (or the...
static LogicalResult verifyTrait(Operation *op)
This class provides verification for ops that are known to have the same operand shape: all operands ...
static LogicalResult verifyTrait(Operation *op)
This class verifies that all operands of the specified op have the same type.
static LogicalResult verifyTrait(Operation *op)
static void ensureTerminator(Region &region, OpBuilder &builder, Location loc)
Definition: OpDefinition.h:943
enable_if_single_region< OpT > insert(Operation *insertPt, Operation *op)
Insert the operation at the given insertion point.
Definition: OpDefinition.h:968
static void ensureTerminator(Region &region, Builder &builder, Location loc)
Ensure that the given region has the terminator required by this trait.
Definition: OpDefinition.h:938
enable_if_single_region< OpT > push_back(Operation *op)
Insert the operation into the back of the body, before the terminator.
Definition: OpDefinition.h:960
static LogicalResult verifyRegionTrait(Operation *op)
Definition: OpDefinition.h:908
TerminatorOpType ImplicitTerminatorOpT
The type of the operation used as the implicit terminator type.
Definition: OpDefinition.h:906
enable_if_single_region< OpT > insert(Block::iterator insertPt, Operation *op)
Definition: OpDefinition.h:972
Helper class for implementing traits.
Definition: OpDefinition.h:312
Operation * getOperation()
Return the ultimate Operation being worked on.
Definition: OpDefinition.h:315
This class provides the API for ops which have an unknown number of SSA operands.
Definition: OpDefinition.h:448
This class provides the API for ops which have an unknown number of regions.
Definition: OpDefinition.h:540
This class provides the API for ops which have an unknown number of results.
Definition: OpDefinition.h:691
This class provides the API for ops which have an unknown number of successors.
Definition: OpDefinition.h:801
This class provides the API for ops that are known to have no SSA operand.
Definition: OpDefinition.h:380
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:382
This class provides verification for ops that are known to have zero regions.
Definition: OpDefinition.h:456
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:458
This class provides return value APIs for ops that are known to have zero results.
Definition: OpDefinition.h:548
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:550
This class provides verification for ops that are known to have zero successors.
Definition: OpDefinition.h:713
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:715
This provides public APIs that all operations should have.
static bool classof(Operation *op)
Return true if this "op class" can match against the specified operation.
Op(std::nullptr_t)
static ConcreteOpType getFromOpaquePointer(const void *pointer)
LogicalResult verify()
If the concrete type didn't implement a custom verifier hook, just fall back to this one which accept...
Definition: OpDefinition.h:194
Op(Operation *state)
This is a public constructor to enable access via the llvm::cast family of methods.
ConcreteType ConcreteOpType
Expose the type we are instantiated on to template machinery that may want to introspect traits on th...
LogicalResult verifyRegions()
Definition: OpDefinition.h:195
ConcreteType clone()
Create a deep copy of this operation.
static std::enable_if_t< std::is_base_of< OpState, T >::value, bool > classof(const T *op)
Provide classof support for other OpBase derived classes, such as Interfaces.
Operation * getOperation()
Inherit getOperation from OpState.
Definition: OpDefinition.h:92
static constexpr bool hasTrait()
Return if this operation contains the provided trait.
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
Op()
This is a public constructor. Any op can be initialized to null.
static void attachInterface(MLIRContext &context)
Attach the given models as implementations of the corresponding interfaces for the concrete operation...
ConcreteType cloneWithoutRegions()
Create a partial copy of this operation without traversing into attached regions.
This class implements the operand iterators for the Operation class.
Definition: ValueRange.h:42
llvm::unique_function< LogicalResult(Operation *) const > VerifyInvariantsFn
StringRef getStringRef() const
Return the name of this operation. This always succeeds.
llvm::unique_function< bool(TypeID) const > HasTraitFn
Dialect * getDialect() const
Return the dialect this operation is registered to if the dialect is loaded in the context,...
llvm::unique_function< LogicalResult(Operation *) const > VerifyRegionInvariantsFn
std::optional< RegisteredOperationName > getRegisteredInfo() const
If this operation is registered, returns the registered information, std::nullopt otherwise.
llvm::unique_function< void(Operation *, OpAsmPrinter &, StringRef) const > PrintAssemblyFn
llvm::unique_function< LogicalResult(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &) const > FoldHookFn
llvm::unique_function< void(const OperationName &, NamedAttrList &) const > PopulateDefaultAttrsFn
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:75
ResultRange result_range
Support result iteration.
Definition: Operation.h:389
bool use_empty()
Returns true if this operation has no uses.
Definition: Operation.h:695
Value getOperand(unsigned idx)
Definition: Operation.h:329
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Definition: Operation.h:592
operand_range::type_range operand_type_range
Definition: Operation.h:373
void setOperand(unsigned idx, Value value)
Definition: Operation.h:330
Block * getSuccessor(unsigned index)
Definition: Operation.h:572
unsigned getNumSuccessors()
Definition: Operation.h:570
result_iterator result_begin()
Definition: Operation.h:392
result_range::iterator result_iterator
Definition: Operation.h:390
operand_iterator operand_begin()
Definition: Operation.h:353
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:386
std::enable_if_t< llvm::function_traits< std::decay_t< FnT > >::num_args==1, RetT > walk(FnT &&callback)
Walk the operation by calling the callback for each nested operation (including this one),...
Definition: Operation.h:640
void print(raw_ostream &os, const OpPrintingFlags &flags=std::nullopt)
operand_range::type_iterator operand_type_iterator
Definition: Operation.h:372
operand_type_iterator operand_type_end()
Definition: Operation.h:375
result_range::type_range result_type_range
Definition: Operation.h:404
MLIRContext * getContext()
Return the context this operation is associated with.
Definition: Operation.h:200
unsigned getNumRegions()
Returns the number of regions held by this operation.
Definition: Operation.h:537
std::optional< RegisteredOperationName > getRegisteredInfo()
If this operation has a registered operation description, return it.
Definition: Operation.h:107
Location getLoc()
The source location the operation was defined or derived from.
Definition: Operation.h:207
unsigned getNumOperands()
Definition: Operation.h:325
result_type_iterator result_type_end()
Definition: Operation.h:406
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
Definition: Operation.h:218
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, NamedAttrList &&attributes, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
Definition: Operation.cpp:48
OperandRange operand_range
Definition: Operation.h:350
result_range::type_iterator result_type_iterator
Support result type iteration.
Definition: Operation.h:403
operand_iterator operand_end()
Definition: Operation.h:354
Region & getRegion(unsigned index)
Returns the region held by this operation at position 'index'.
Definition: Operation.h:550
result_type_iterator result_type_begin()
Definition: Operation.h:405
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
Definition: Operation.h:540
OperationName getName()
The name of an operation is the key identifier for it.
Definition: Operation.h:103
operand_type_range getOperandTypes()
Definition: Operation.h:376
result_iterator result_end()
Definition: Operation.h:393
result_type_range getResultTypes()
Definition: Operation.h:407
operand_range getOperands()
Returns an iterator on the underlying Value's.
Definition: Operation.h:357
void setSuccessor(Block *block, unsigned index)
Definition: Operation.cpp:493
void replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this operation with the provided 'values'.
Definition: Operation.h:256
SuccessorRange getSuccessors()
Definition: Operation.h:567
result_range getResults()
Definition: Operation.h:394
SuccessorRange::iterator succ_iterator
Definition: Operation.h:564
operand_range::iterator operand_iterator
Definition: Operation.h:351
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
Definition: Operation.cpp:520
void erase()
Remove this operation from its parent block and delete it.
Definition: Operation.cpp:427
unsigned getNumResults()
Return the number of results held by this operation.
Definition: Operation.h:383
operand_type_iterator operand_type_begin()
Definition: Operation.h:374
This class implements Optional functionality for ParseResult.
Definition: OpDefinition.h:38
ParseResult value() const
Access the internal ParseResult value.
Definition: OpDefinition.h:51
OptionalParseResult(ParseResult result)
Definition: OpDefinition.h:42
OptionalParseResult(std::nullopt_t)
Definition: OpDefinition.h:45
OptionalParseResult(const InFlightDiagnostic &)
Definition: OpDefinition.h:43
OptionalParseResult(LogicalResult result)
Definition: OpDefinition.h:41
bool has_value() const
Returns true if we contain a valid ParseResult value.
Definition: OpDefinition.h:48
ParseResult operator*() const
Definition: OpDefinition.h:52
This class represents success/failure for parsing-like operations that find it important to chain tog...
This class provides an abstraction over the different types of ranges over Regions.
Definition: Region.h:334
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Definition: Region.h:26
iterator_range< OpIterator > getOps()
Definition: Region.h:172
bool empty()
Definition: Region.h:60
Block & front()
Definition: Region.h:65
This is a "type erased" representation of a registered operation.
static std::optional< RegisteredOperationName > lookup(StringRef name, MLIRContext *ctx)
Lookup the registered operation information for the given operation.
This class implements the result iterators for the Operation class.
Definition: ValueRange.h:231
This class implements the successor iterators for Block.
Definition: BlockSupport.h:73
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
This class provides an abstraction over the various different ranges of value types.
Definition: TypeRange.h:36
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:74
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:118
This class implements iteration on the types of a given range of values.
Definition: TypeRange.h:131
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
Type getType() const
Return the type of this value.
Definition: Value.h:122
void replaceAllUsesWith(Value newValue) const
Replace all uses of 'this' value with the new value, updating anything in the IR that uses 'this' to ...
Definition: Value.h:166
This class represents an abstract interface.
Interface< ConcreteType, Operation *, Traits, Op< ConcreteType >, OpTrait::TraitBase > InterfaceBase
Include the generated interface declarations.
Definition: CallGraph.h:229
OpFoldResult foldIdempotent(Operation *op)
Definition: Operation.cpp:667
LogicalResult verifyResultsAreFloatLike(Operation *op)
Definition: Operation.cpp:995
LogicalResult verifyAtLeastNResults(Operation *op, unsigned numOperands)
Definition: Operation.cpp:826
LogicalResult verifyIsIdempotent(Operation *op)
Definition: Operation.cpp:733
LogicalResult verifyOperandsAreSignlessIntegerLike(Operation *op)
Definition: Operation.cpp:750
LogicalResult verifyNOperands(Operation *op, unsigned numOperands)
Definition: Operation.cpp:703
LogicalResult verifyNoRegionArguments(Operation *op)
Definition: Operation.cpp:1047
LogicalResult verifyResultsAreSignlessIntegerLike(Operation *op)
Definition: Operation.cpp:1004
LogicalResult verifyIsInvolution(Operation *op)
Definition: Operation.cpp:741
LogicalResult verifyOperandsAreFloatLike(Operation *op)
Definition: Operation.cpp:759
LogicalResult verifyZeroRegions(Operation *op)
Definition: Operation.cpp:781
LogicalResult verifyNSuccessors(Operation *op, unsigned numSuccessors)
Definition: Operation.cpp:965
LogicalResult verifyOperandSizeAttr(Operation *op, StringRef sizeAttrName)
Definition: Operation.cpp:1037
LogicalResult verifyAtLeastNRegions(Operation *op, unsigned numRegions)
Definition: Operation.cpp:800
LogicalResult verifyValueSizeAttr(Operation *op, StringRef attrName, StringRef valueGroupName, size_t expectedCount)
Definition: Operation.cpp:1011
LogicalResult verifyZeroResults(Operation *op)
Definition: Operation.cpp:807
LogicalResult verifySameOperandsAndResultType(Operation *op)
Definition: Operation.cpp:897
LogicalResult verifySameOperandsShape(Operation *op)
Definition: Operation.cpp:834
LogicalResult verifyAtLeastNSuccessors(Operation *op, unsigned numSuccessors)
Definition: Operation.cpp:974
LogicalResult verifyIsTerminator(Operation *op)
Definition: Operation.cpp:932
LogicalResult verifyAtLeastNOperands(Operation *op, unsigned numOperands)
Definition: Operation.cpp:712
LogicalResult verifyZeroOperands(Operation *op)
Definition: Operation.cpp:691
LogicalResult verifyElementwise(Operation *op)
Definition: Operation.cpp:1062
LogicalResult verifyOneRegion(Operation *op)
Definition: Operation.cpp:787
LogicalResult verifyOneOperand(Operation *op)
Definition: Operation.cpp:697
LogicalResult verifyIsIsolatedFromAbove(Operation *op)
Check for any values used by operations regions attached to the specified "IsIsolatedFromAbove" opera...
Definition: Operation.cpp:1105
LogicalResult verifyZeroSuccessors(Operation *op)
Definition: Operation.cpp:950
LogicalResult verifySameOperandsElementType(Operation *op)
Definition: Operation.cpp:859
LogicalResult verifyOneSuccessor(Operation *op)
Definition: Operation.cpp:958
LogicalResult verifySameOperandsAndResultElementType(Operation *op)
Definition: Operation.cpp:873
OpFoldResult foldInvolution(Operation *op)
Definition: Operation.cpp:681
LogicalResult verifyResultsAreBoolLike(Operation *op)
Definition: Operation.cpp:984
LogicalResult verifyNResults(Operation *op, unsigned numOperands)
Definition: Operation.cpp:819
LogicalResult verifyResultSizeAttr(Operation *op, StringRef sizeAttrName)
Definition: Operation.cpp:1042
LogicalResult verifyNRegions(Operation *op, unsigned numRegions)
Definition: Operation.cpp:793
LogicalResult verifyOneResult(Operation *op)
Definition: Operation.cpp:813
LogicalResult verifySameTypeOperands(Operation *op)
Definition: Operation.cpp:768
LogicalResult verifySameOperandsAndResultShape(Operation *op)
Definition: Operation.cpp:844
bool hasElementwiseMappableTraits(Operation *op)
Together, Elementwise, Scalarizable, Vectorizable, and Tensorizable provide an easy way for scalar op...
Definition: Operation.cpp:1147
typename T::ImplicitTerminatorOpT has_implicit_terminator_t
Check is an op defines the ImplicitTerminatorOpT member.
Definition: OpDefinition.h:985
LogicalResult foldCastInterfaceOp(Operation *op, ArrayRef< Attribute > attrOperands, SmallVectorImpl< OpFoldResult > &foldResults)
Attempt to fold the given cast operation.
Definition: Operation.cpp:1158
LogicalResult verifyCastInterfaceOp(Operation *op, function_ref< bool(TypeRange, TypeRange)> areCastCompatible)
Attempt to verify the given cast operation.
Definition: Operation.cpp:1175
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's only block if it does...
Definition: Operation.cpp:1206
void ensureRegionTerminator(Region &region, Builder &builder, Location loc, function_ref< Operation *(OpBuilder &, Location)> buildTerminatorOp)
Create a simple OpBuilder and forward to the OpBuilder version of this function.
Definition: Operation.cpp:1223
NestedPattern Op(FilterFunctionType filter=defaultFilterFunction)
llvm::is_detected< has_fold_trait, T > detect_has_fold_trait
std::enable_if_t< detect_has_verify_trait< T >::value, LogicalResult > verifyTrait(Operation *op)
Verify the given trait if it provides a verifier.
llvm::is_detected< has_verify_trait, T > detect_has_verify_trait
llvm::is_detected< has_verify_region_trait, T > detect_has_verify_region_trait
LogicalResult verifyTraits(Operation *op)
Given a set of traits, return the result of verifying the given operation.
std::enable_if_t<!detect_has_verify_trait< T >::value, LogicalResult > verifyTrait(Operation *)
decltype(T::verifyTrait(std::declval< Operation * >())) has_verify_trait
Trait to check if T provides a verifyTrait method.
decltype(T::foldTrait(std::declval< Operation * >(), std::declval< ArrayRef< Attribute > >(), std::declval< SmallVectorImpl< OpFoldResult > & >())) has_fold_trait
Trait to check if T provides a general 'foldTrait' method.
static bool hasTrait(TypeID traitID)
Returns true if this given Trait ID matches the IDs of any of the provided trait types Traits.
llvm::is_detected< has_single_result_fold_trait, T > detect_has_single_result_fold_trait
std::enable_if_t< detect_has_verify_region_trait< T >::value, LogicalResult > verifyRegionTrait(Operation *op)
Verify the given trait if it provides a region verifier.
static std::enable_if_t<!detect_has_any_fold_trait< Trait >::value, LogicalResult > foldTrait(Operation *, ArrayRef< Attribute >, SmallVectorImpl< OpFoldResult > &)
std::disjunction< detect_has_fold_trait< T >, detect_has_single_result_fold_trait< T > > detect_has_any_fold_trait
Trait to check if T provides any foldTrait method.
decltype(T::verifyRegionTrait(std::declval< Operation * >())) has_verify_region_trait
Trait to check if T provides a verifyTrait method.
static LogicalResult foldTraits(Operation *op, ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results)
Given a tuple type containing a set of traits, return the result of folding the given operation.
static std::enable_if_t< detect_has_single_result_fold_trait< Trait >::value, LogicalResult > foldTrait(Operation *op, ArrayRef< Attribute > operands, SmallVectorImpl< OpFoldResult > &results)
Returns the result of folding a trait that implements a foldTrait function that is specialized for op...
decltype(T::foldTrait(std::declval< Operation * >(), std::declval< ArrayRef< Attribute > >())) has_single_result_fold_trait
Trait to check if T provides a 'foldTrait' method for single result operations.
LogicalResult verifyRegionTraits(Operation *op)
Given a set of traits, return the result of verifying the regions of the given operation.
std::enable_if_t<!detect_has_verify_region_trait< T >::value, LogicalResult > verifyRegionTrait(Operation *)
llvm::hash_code hash_value(const MPInt &x)
Redeclarations of friend declaration above to make it discoverable by lookups.
Definition: MPInt.cpp:15
This header declares functions that assit transformations in the MemRef dialect.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
llvm::function_ref< Fn > function_ref
Definition: LLVM.h:150
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.
Definition: Value.h:483
bool operator==(StringAttr lhs, std::nullptr_t)
Define comparisons for StringAttr against nullptr and itself to avoid the StringRef overloads from be...
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
Definition: LogicalResult.h:68
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition: Visitors.h:63
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
bool operator!=(StringAttr lhs, std::nullptr_t)
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Definition: AliasAnalysis.h:78
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
static LogicalResult failure(bool isFailure=true)
If isFailure is true a failure result is generated, otherwise a 'success' result is generated.
Definition: LogicalResult.h:36
This trait tags element-wise ops on vectors or tensors.
static LogicalResult verifyTrait(Operation *op)
This class provides a verifier for ops that are expecting their parent to be one of the given parent ...
This trait provides a verifier for ops that are expecting their regions to not have any arguments.
static LogicalResult verifyTrait(Operation *op)
This trait tags Elementwise operatons that can be systematically scalarized.
static LogicalResult verifyTrait(Operation *op)
This class provides APIs and verifiers for ops with regions having a single block that must terminate...
Definition: OpDefinition.h:891
This class provides APIs and verifiers for ops with regions having a single block.
Definition: OpDefinition.h:810
std::enable_if_t< OpT::template hasTrait< OneRegion >(), T > enable_if_single_region
The following are a set of methods only enabled when the parent operation has a single region.
Definition: OpDefinition.h:853
enable_if_single_region< OpT > insert(Operation *insertPt, Operation *op)
Insert the operation at the given insertion point.
Definition: OpDefinition.h:876
Region & getBodyRegion(unsigned idx=0)
Definition: OpDefinition.h:839
enable_if_single_region< OpT > push_back(Operation *op)
Insert the operation into the back of the body.
Definition: OpDefinition.h:870
enable_if_single_region< OpT, Block::iterator > begin()
Definition: OpDefinition.h:856
enable_if_single_region< OpT, Operation & > front()
Definition: OpDefinition.h:864
static LogicalResult verifyTrait(Operation *op)
Definition: OpDefinition.h:812
enable_if_single_region< OpT > insert(Block::iterator insertPt, Operation *op)
Definition: OpDefinition.h:880
Block * getBody(unsigned idx=0)
Definition: OpDefinition.h:834
enable_if_single_region< OpT, Block::iterator > end()
Definition: OpDefinition.h:860
This trait tags Elementwise operatons that can be systematically tensorized.
static LogicalResult verifyTrait(Operation *op)
This trait tags Elementwise operatons that can be systematically vectorized.
static LogicalResult verifyTrait(Operation *op)
Utility trait base that provides accessors for derived traits that have multiple operands.
Definition: OpDefinition.h:328
Value getOperand(unsigned i)
Return the operand at index 'i'.
Definition: OpDefinition.h:338
operand_type_iterator operand_type_begin()
Operand type access.
Definition: OpDefinition.h:353
unsigned getNumOperands()
Return the number of operands.
Definition: OpDefinition.h:335
operand_iterator operand_begin()
Operand iterator access.
Definition: OpDefinition.h:346
void setOperand(unsigned i, Value value)
Set the operand at index 'i' to 'value'.
Definition: OpDefinition.h:341
Operation::operand_iterator operand_iterator
Definition: OpDefinition.h:329
Utility trait base that provides accessors for derived traits that have multiple regions.
Definition: OpDefinition.h:467
unsigned getNumRegions()
Return the number of regions.
Definition: OpDefinition.h:472
Region & getRegion(unsigned i)
Return the region at index.
Definition: OpDefinition.h:475
region_iterator region_begin()
Region iterator access.
Definition: OpDefinition.h:478
Utility trait base that provides accessors for derived traits that have multiple results.
Definition: OpDefinition.h:559
result_type_iterator result_type_begin()
Result type access.
Definition: OpDefinition.h:589
Value getResult(unsigned i)
Return the result at index 'i'.
Definition: OpDefinition.h:569
void replaceAllUsesWith(ValuesT &&values)
Replace all uses of results of this operation with the provided 'values'.
Definition: OpDefinition.h:574
Operation::result_iterator result_iterator
Definition: OpDefinition.h:560
result_iterator result_begin()
Result iterator access.
Definition: OpDefinition.h:582
unsigned getNumResults()
Return the number of results.
Definition: OpDefinition.h:566
Type getType(unsigned i)
Return the type of the i-th result.
Definition: OpDefinition.h:579
Utility trait base that provides accessors for derived traits that have multiple successors.
Definition: OpDefinition.h:724
void setSuccessor(Block *block, unsigned i)
Set the successor at index.
Definition: OpDefinition.h:739
succ_iterator succ_begin()
Successor iterator access.
Definition: OpDefinition.h:744
unsigned getNumSuccessors()
Return the number of successors.
Definition: OpDefinition.h:729
Block * getSuccessor(unsigned i)
Return the successor at index.
Definition: OpDefinition.h:734
Support to check if an operation has the SingleBlockImplicitTerminator trait.
Definition: OpDefinition.h:992
This represents an operation in an abstracted form, suitable for use with the builder APIs.