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 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 /// Return the effect of the given type `Effect` that is applied to the 114 /// given value, or None if no effect exists. 115 template <typename Effect> 116 ::llvm::Optional<::mlir::SideEffects::EffectInstance<}] # baseEffect # [{>> 117 getEffectOnValue(::mlir::Value value) { 118 llvm::SmallVector<::mlir::SideEffects::EffectInstance< 119 }] # baseEffect # [{>, 4> effects; 120 getEffects(effects); 121 auto it = llvm::find_if(effects, [&](auto &it) { 122 return isa<Effect>(it.getEffect()) && it.getValue() == value; 123 }); 124 if (it == effects.end()) 125 return llvm::None; 126 return *it; 127 } 128 129 /// Collect all of the effect instances that operate on the provided symbol 130 /// reference and place them in 'effects'. 131 void getEffectsOnSymbol(::mlir::SymbolRefAttr value, 132 llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance< 133 }] # baseEffect # [{>> & effects) { 134 getEffects(effects); 135 llvm::erase_if(effects, [&](auto &it) { 136 return it.getSymbolRef() != value; 137 }); 138 } 139 140 /// Collect all of the effect instances that operate on the provided 141 /// resource and place them in 'effects'. 142 void getEffectsOnResource(::mlir::SideEffects::Resource *resource, 143 llvm::SmallVectorImpl<::mlir::SideEffects::EffectInstance< 144 }] # baseEffect # [{>> & effects) { 145 getEffects(effects); 146 llvm::erase_if(effects, [&](auto &it) { 147 return it.getResource() != resource; 148 }); 149 } 150 }]; 151 152 // The base effect name of this interface. 153 string baseEffectName = baseEffect; 154} 155 156// This class is the general base side effect class. This is used by derived 157// effect interfaces to define their effects. 158class SideEffect<EffectOpInterfaceBase interface, string effectName, 159 Resource resourceReference> : OpVariableDecorator { 160 /// The name of the base effects class. 161 string baseEffectName = interface.baseEffectName; 162 163 /// The parent interface that the effect belongs to. 164 string interfaceTrait = interface.trait; 165 166 /// The cpp namespace of the interface trait. 167 string cppNamespace = interface.cppNamespace; 168 169 /// The derived effect that is being applied. 170 string effect = effectName; 171 172 /// The resource that the effect is being applied to. 173 string resource = resourceReference.name; 174} 175 176// This class is the base used for specifying effects applied to an operation. 177class SideEffectsTraitBase<EffectOpInterfaceBase parentInterface, 178 list<SideEffect> staticEffects> 179 : OpInterfaceTrait<""> { 180 /// The name of the interface trait to use. 181 let trait = parentInterface.trait; 182 183 /// The cpp namespace of the interface trait. 184 string cppNamespace = parentInterface.cppNamespace; 185 186 /// The name of the base effects class. 187 string baseEffectName = parentInterface.baseEffectName; 188 189 /// The derived effects being applied. 190 list<SideEffect> effects = staticEffects; 191} 192 193#endif // MLIR_INTERFACES_SIDEEFFECTS_BASE 194