19 return walkImpl(attr, attrWalkFns, order);
22 return walkImpl(type, typeWalkFns, order);
25template <
typename T,
typename WalkFns>
26WalkResult AttrTypeWalker::walkImpl(T element, WalkFns &walkFns,
29 auto key = std::make_pair(element.getAsOpaquePointer(), (
int)order);
37 if (walkSubElements(element, order).wasInterrupted())
42 for (
auto &walkFn : llvm::reverse(walkFns)) {
43 WalkResult walkResult = walkFn(element);
52 if (walkSubElements(element, order).wasInterrupted())
61 auto walkFn = [&](
auto element) {
62 if (element && !
result.wasInterrupted())
63 result = walkImpl(element, order);
65 interface.walkImmediateSubElements(walkFn, walkFn);
73template <
typename Concrete>
76 attrReplacementFns.emplace_back(std::move(fn));
79template <
typename Concrete>
82 typeReplacementFns.push_back(std::move(fn));
85template <
typename Concrete>
87 Operation *op,
bool replaceAttrs,
bool replaceLocs,
bool replaceTypes) {
90 auto replaceIfDifferent = [&](
auto element) {
91 auto replacement =
static_cast<Concrete *
>(
this)->replace(element);
109 if (!replaceTypes && !replaceLocs)
115 op->
setLoc(cast<LocationAttr>(newLoc));
121 if (
Type newType = replaceIfDifferent(
result.getType()))
127 for (
Block &block : region) {
130 if (
Attribute newLoc = replaceIfDifferent(arg.getLoc()))
131 arg.setLoc(cast<LocationAttr>(newLoc));
135 if (
Type newType = replaceIfDifferent(arg.getType()))
136 arg.setType(newType);
143template <
typename Concrete>
145 Operation *op,
bool replaceAttrs,
bool replaceLocs,
bool replaceTypes) {
151template <
typename T,
typename Replacer>
154 FailureOr<bool> &changed) {
161 newElements.push_back(
nullptr);
166 if (T
result = replacer.replace(element)) {
167 newElements.push_back(
result);
175template <
typename T,
typename Replacer>
180 FailureOr<bool> changed =
false;
181 interface.walkImmediateSubElements(
194 result = interface.replaceImmediateSubElements(newAttrs, newTypes);
199template <
typename T,
typename ReplaceFns,
typename Replacer>
201 Replacer &replacer) {
204 for (
auto &replaceFn : llvm::reverse(replaceFns)) {
205 if (std::optional<std::pair<T, WalkResult>> newRes = replaceFn(element)) {
206 std::tie(
result, walkResult) = *newRes;
227template <
typename Concrete>
230 *
static_cast<Concrete *
>(
this));
233template <
typename Concrete>
236 *
static_cast<Concrete *
>(
this));
246T AttrTypeReplacer::cachedReplaceImpl(T element) {
247 const void *opaqueElement = element.getAsOpaquePointer();
248 auto [it,
inserted] = cache.try_emplace(opaqueElement, opaqueElement);
250 return T::getFromOpaquePointer(it->second);
254 cache[opaqueElement] =
result.getAsOpaquePointer();
259 return cachedReplaceImpl(attr);
271 : cache([&](
void *attr) {
return breakCycleImpl(attr); }) {}
274 attrCycleBreakerFns.emplace_back(std::move(fn));
278 typeCycleBreakerFns.emplace_back(std::move(fn));
282T CyclicAttrTypeReplacer::cachedReplaceImpl(T element) {
283 void *opaqueTaggedElement = AttrOrType(element).getOpaqueValue();
286 if (
auto resultOpt = cacheEntry.
get())
287 return T::getFromOpaquePointer(*resultOpt);
296 return cachedReplaceImpl(attr);
300 return cachedReplaceImpl(type);
303std::optional<const void *>
304CyclicAttrTypeReplacer::breakCycleImpl(
void *element) {
305 AttrOrType attrType = AttrOrType::getFromOpaqueValue(element);
306 if (
auto attr = dyn_cast<Attribute>(attrType)) {
307 for (
auto &cyclicReplaceFn : llvm::reverse(attrCycleBreakerFns)) {
308 if (std::optional<Attribute> newRes = cyclicReplaceFn(attr)) {
309 return newRes->getAsOpaquePointer();
313 auto type = dyn_cast<Type>(attrType);
314 for (
auto &cyclicReplaceFn : llvm::reverse(typeCycleBreakerFns)) {
315 if (std::optional<Type> newRes = cyclicReplaceFn(type)) {
316 return newRes->getAsOpaquePointer();
329 walkAttrsFn(element);
334 walkTypesFn(element);
static void updateSubElementImpl(T element, Replacer &replacer, SmallVectorImpl< T > &newElements, FailureOr< bool > &changed)
static T replaceElementImpl(T element, ReplaceFns &replaceFns, Replacer &replacer)
Shared implementation of replacing a given attribute or type element.
static T replaceSubElements(T interface, Replacer &replacer)
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be the output argument nBegin is set to its * replacement(set to `begin` if no invalidation happens). Since outgoing *copies could have been inserted at `end`
Attribute replace(Attribute attr)
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
void addCycleBreaker(CycleBreakerFn< Attribute > fn)
Register a cycle-breaking function.
Attribute replace(Attribute attr)
std::function< std::optional< T >(T)> CycleBreakerFn
A cycle-breaking function.
CacheEntry lookupOrInit(InT element)
Lookup the cache for a pre-calculated replacement for element.
This is a value defined by a result of an operation.
void walkInherentAttrs(Operation *op, InherentAttrVisitor visitor) const
Visit the inherent attributes stored in the properties of op.
Operation is the basic unit of execution within MLIR.
void setLoc(Location loc)
Set the source location the operation was defined or derived from.
Location getLoc()
The source location the operation was defined or derived from.
DictionaryAttr getRawDictionaryAttrs()
Return all attributes that are not stored as properties.
OperationName getName()
The name of an operation is the key identifier for it.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
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),...
result_range getResults()
int getPropertiesStorageSize() const
Returns the properties storage size.
void setDiscardableAttrs(DictionaryAttr newAttrs)
Set the discardable attribute dictionary on this operation.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
A utility result that is used to signal how to proceed with an ongoing walk:
bool wasSkipped() const
Returns true if the walk was skipped.
static WalkResult advance()
bool wasInterrupted() const
Returns true if the walk was interrupted.
static WalkResult interrupt()
This class provides a base utility for replacing attributes/types, and their sub elements.
void recursivelyReplaceElementsIn(Operation *op, bool replaceAttrs=true, bool replaceLocs=false, bool replaceTypes=false)
Replace the elements within the given operation, and all nested operations.
Attribute replaceBase(Attribute attr)
Invokes the registered replacement functions from most recently registered to least recently register...
std::function< ReplaceFnResult< T >(T)> ReplaceFn
void replaceElementsIn(Operation *op, bool replaceAttrs=true, bool replaceLocs=false, bool replaceTypes=false)
Replace the elements within the given operation.
void addReplacement(ReplaceFn< Attribute > fn)
Register a replacement function for mapping a given attribute or type.
Include the generated interface declarations.
WalkOrder
Traversal order for region, block and operation walk utilities.
A possibly unresolved cache entry.
void resolve(OutT result)
Resolve an unresolved cache entry by providing the result to be stored in the cache.
const std::optional< OutT > & get() const
Get the resolved result if one exists.