1//===-- SideEffectInterfaceBase.td - Side Effect Base ------*- tablegen -*-===//
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 contains base class definitions for side effect interfaces, i.e.
10// the customizable interfaces that provide information about which effects are
11// applied by an operation.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef MLIR_INTERFACES_SIDEEFFECTS_BASE
16#define MLIR_INTERFACES_SIDEEFFECTS_BASE
17
18include "mlir/IR/OpBase.td"
19
20//===----------------------------------------------------------------------===//
21// Resource Bindings
22//===----------------------------------------------------------------------===//
23
24// A generic resource that can be attached to a general base side effect.
25class Resource<string resourceName> {
26  /// The resource that the associated effect is being applied to.
27  string name = resourceName;
28}
29
30// An intrinsic resource that lives in the ::mlir::SideEffects namespace.
31class IntrinsicResource<string resourceName> :
32  Resource<!strconcat("::mlir::SideEffects::", resourceName)> {
33}
34
35// A link to the DefaultResource class.
36def DefaultResource : IntrinsicResource<"DefaultResource">;
37// A link to the AutomaticAllocationScopeResource class.
38def AutomaticAllocationScopeResource :
39  IntrinsicResource<"AutomaticAllocationScopeResource">;
40
41//===----------------------------------------------------------------------===//
42// EffectOpInterface
43//===----------------------------------------------------------------------===//
44
45// A base interface used to query information about the side effects applied to
46// an operation. This template class takes the name of the derived interface
47// class, as well as the name of the base effect class.
48class EffectOpInterfaceBase<string name, string baseEffect>
49    : OpInterface<name> {
50  let methods = [
51    InterfaceMethod<[{
52        Collects all of the operation's effects into `effects`.
53      }],
54      "void", "getEffects",
55         (ins "SmallVectorImpl<::mlir::SideEffects::EffectInstance<"
56              # baseEffect # ">> &":$effects)
57    >,
58  ];
59
60  let extraClassDeclaration = [{
61    /// Collect all of the effect instances that correspond to the given
62    /// `Effect` and place them in 'effects'.
63    template <typename Effect> void getEffects(
64      SmallVectorImpl<::mlir::SideEffects::EffectInstance<
65                                              }] # baseEffect # [{>> &effects) {
66      getEffects(effects);
67      llvm::erase_if(effects, [&](auto &it) {
68        return !llvm::isa<Effect>(it.getEffect());
69      });
70    }
71
72    /// Returns true if this operation exhibits the given effect.
73    template <typename Effect> bool hasEffect() {
74      SmallVector<SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
75      getEffects(effects);
76      return llvm::any_of(effects, [](const auto &it) {
77        return llvm::isa<Effect>(it.getEffect());
78      });
79    }
80
81    /// Returns true if this operation only has the given effect.
82    template <typename Effect> bool onlyHasEffect() {
83      SmallVector<SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
84      getEffects(effects);
85      return !effects.empty() && llvm::all_of(effects, [](const auto &it) {
86        return isa<Effect>(it.getEffect());
87      });
88    }
89
90    /// Returns true if this operation has no effects.
91    bool hasNoEffect() {
92      SmallVector<::mlir::SideEffects::EffectInstance<}] # baseEffect # [{>, 4> effects;
93      getEffects(effects);
94      return effects.empty();
95    }
96
97    /// Returns true if the given operation has no effects for this interface.
98    static bool hasNoEffect(Operation *op) {
99      if (auto interface = dyn_cast<}] # name # [{>(op))
100        return interface.hasNoEffect();
101      return op->hasTrait<::mlir::OpTrait::HasRecursiveSideEffects>();
102    }
103
104    /// Collect all of the effect instances that operate on the provided value
105    /// and place them in 'effects'.
106    void getEffectsOnValue(::mlir::Value value,
107              llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
108              }] # baseEffect # [{>> & effects) {
109      getEffects(effects);
110      llvm::erase_if(effects, [&](auto &it) { return it.getValue() != value; });
111    }
112
113    /// Collect all of the effect instances that operate on the provided symbol
114    /// reference and place them in 'effects'.
115    void getEffectsOnSymbol(::mlir::SymbolRefAttr value,
116              llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
117              }] # baseEffect # [{>> & effects) {
118      getEffects(effects);
119      llvm::erase_if(effects, [&](auto &it) {
120        return it.getSymbolRef() != value;
121      });
122    }
123
124    /// Collect all of the effect instances that operate on the provided
125    /// resource and place them in 'effects'.
126    void getEffectsOnResource(::mlir::SideEffects::Resource *resource,
127              llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
128              }] # baseEffect # [{>> & effects) {
129      getEffects(effects);
130      llvm::erase_if(effects, [&](auto &it) {
131        return it.getResource() != resource;
132      });
133    }
134  }];
135
136  // The base effect name of this interface.
137  string baseEffectName = baseEffect;
138}
139
140// This class is the general base side effect class. This is used by derived
141// effect interfaces to define their effects.
142class SideEffect<EffectOpInterfaceBase interface, string effectName,
143                 Resource resourceReference> : OpVariableDecorator {
144  /// The name of the base effects class.
145  string baseEffectName = interface.baseEffectName;
146
147  /// The parent interface that the effect belongs to.
148  string interfaceTrait = interface.trait;
149
150  /// The cpp namespace of the interface trait.
151  string cppNamespace = interface.cppNamespace;
152
153  /// The derived effect that is being applied.
154  string effect = effectName;
155
156  /// The resource that the effect is being applied to.
157  string resource = resourceReference.name;
158}
159
160// This class is the base used for specifying effects applied to an operation.
161class SideEffectsTraitBase<EffectOpInterfaceBase parentInterface,
162                           list<SideEffect> staticEffects>
163    : OpInterfaceTrait<""> {
164  /// The name of the interface trait to use.
165  let trait = parentInterface.trait;
166
167  /// The cpp namespace of the interface trait.
168  string cppNamespace = parentInterface.cppNamespace;
169
170  /// The name of the base effects class.
171  string baseEffectName = parentInterface.baseEffectName;
172
173  /// The derived effects being applied.
174  list<SideEffect> effects = staticEffects;
175}
176
177#endif // MLIR_INTERFACES_SIDEEFFECTS_BASE
178