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