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