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