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