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