xref: /llvm-project/mlir/include/mlir/Interfaces/SideEffectInterfaceBase.td (revision 0c63122713c2d719789aef4bdfaf4e0b29c3b79e)
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 "::llvm::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      ::llvm::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      ::llvm::SmallVector<::mlir::SideEffects::EffectInstance<
75                                            }] # baseEffect # [{>, 4> effects;
76      getEffects(effects);
77      return ::llvm::any_of(effects, [](const auto &it) {
78        return ::llvm::isa<Effect>(it.getEffect());
79      });
80    }
81
82    /// Returns true if this operation only has the given effect.
83    template <typename Effect> bool onlyHasEffect() {
84      ::llvm::SmallVector<::mlir::SideEffects::EffectInstance<
85                                            }] # baseEffect # [{>, 4> effects;
86      getEffects(effects);
87      return !effects.empty() && ::llvm::all_of(effects, [](const auto &it) {
88        return ::llvm::isa<Effect>(it.getEffect());
89      });
90    }
91
92    /// Returns true if this operation has no effects.
93    bool hasNoEffect() {
94      ::llvm::SmallVector<::mlir::SideEffects::EffectInstance<
95                                            }] # baseEffect # [{>, 4> effects;
96      getEffects(effects);
97      return effects.empty();
98    }
99
100    /// Collect all of the effect instances that operate on the provided value
101    /// and place them in 'effects'.
102    void getEffectsOnValue(::mlir::Value value,
103              ::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
104              }] # baseEffect # [{>> & effects) {
105      getEffects(effects);
106      ::llvm::erase_if(effects, [&](auto &it) { return it.getValue() != value; });
107    }
108
109    /// Return the effect of the given type `Effect` that is applied to the
110    /// given value, or std::nullopt if no effect exists.
111    template <typename Effect>
112    ::std::optional<::mlir::SideEffects::EffectInstance<}] # baseEffect # [{>>
113    getEffectOnValue(::mlir::Value value) {
114      ::llvm::SmallVector<::mlir::SideEffects::EffectInstance<
115              }] # baseEffect # [{>, 4> effects;
116      getEffects(effects);
117      auto it = ::llvm::find_if(effects, [&](auto &it) {
118        return ::llvm::isa<Effect>(it.getEffect()) && it.getValue() == value;
119      });
120      if (it == effects.end())
121        return std::nullopt;
122      return *it;
123    }
124
125    /// Collect all of the effect instances that operate on the provided symbol
126    /// reference and place them in 'effects'.
127    void getEffectsOnSymbol(::mlir::SymbolRefAttr value,
128              ::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
129              }] # baseEffect # [{>> & effects) {
130      getEffects(effects);
131      ::llvm::erase_if(effects, [&](auto &it) {
132        return it.getSymbolRef() != value;
133      });
134    }
135
136    /// Collect all of the effect instances that operate on the provided
137    /// resource and place them in 'effects'.
138    void getEffectsOnResource(::mlir::SideEffects::Resource *resource,
139              ::llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance<
140              }] # baseEffect # [{>> & effects) {
141      getEffects(effects);
142      ::llvm::erase_if(effects, [&](auto &it) {
143        return it.getResource() != resource;
144      });
145    }
146  }];
147
148  // The base effect name of this interface.
149  string baseEffectName = baseEffect;
150}
151
152
153class EffectRange <bits<1> val> {
154  bits<1> Value = val;
155}
156
157def FullEffect : EffectRange<1>;
158def PartialEffect : EffectRange<0>;
159
160// This class is the general base side effect class. This is used by derived
161// effect interfaces to define their effects.
162class SideEffect<EffectOpInterfaceBase interface, string effectName,
163                 Resource resourceReference, int effectStage, EffectRange range>
164    : OpVariableDecorator {
165  /// The name of the base effects class.
166  string baseEffectName = interface.baseEffectName;
167
168  /// The parent interface that the effect belongs to.
169  string interfaceTrait = interface.trait;
170
171  /// The cpp namespace of the interface trait.
172  string cppNamespace = interface.cppNamespace;
173
174  /// The derived effect that is being applied.
175  string effect = effectName;
176
177  /// The resource that the effect is being applied to.
178  string resource = resourceReference.name;
179
180  /// The stage of side effects, we use it to describe the sequence in which
181  /// effects occur.
182  int stage = effectStage;
183
184  // Does this side effect act on every single value of resource.
185  bit effectOnFullRegion = range.Value;
186}
187
188// This class is the base used for specifying effects applied to an operation.
189class SideEffectsTraitBase<EffectOpInterfaceBase parentInterface,
190                           list<SideEffect> staticEffects>
191    : OpInterfaceTrait<""> {
192  /// The name of the interface trait to use.
193  let trait = parentInterface.trait;
194
195  /// The cpp namespace of the interface trait.
196  string cppNamespace = parentInterface.cppNamespace;
197
198  /// The name of the base effects class.
199  string baseEffectName = parentInterface.baseEffectName;
200
201  /// The derived effects being applied.
202  list<SideEffect> effects = staticEffects;
203}
204
205#endif // MLIR_INTERFACES_SIDEEFFECTS_BASE
206