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