MLIR 22.0.0git
AttrTypeSubElements.h
Go to the documentation of this file.
1//===- AttrTypeSubElements.h - Attr and Type SubElements -------*- C++ -*-===//
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 utilities for querying the sub elements of an attribute or
10// type.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef MLIR_IR_ATTRTYPESUBELEMENTS_H
15#define MLIR_IR_ATTRTYPESUBELEMENTS_H
16
17#include "mlir/IR/MLIRContext.h"
18#include "mlir/IR/Visitors.h"
20#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/DenseMap.h"
22#include <optional>
23
24namespace mlir {
25class Attribute;
26class Type;
27
28//===----------------------------------------------------------------------===//
29/// AttrTypeWalker
30//===----------------------------------------------------------------------===//
31
32/// This class provides a utility for walking attributes/types, and their sub
33/// elements. Multiple walk functions may be registered.
35public:
36 //===--------------------------------------------------------------------===//
37 // Application
38 //===--------------------------------------------------------------------===//
39
40 /// Walk the given attribute/type, and recursively walk any sub elements.
41 template <WalkOrder Order, typename T>
42 WalkResult walk(T element) {
43 return walkImpl(element, Order);
44 }
45 template <typename T>
46 WalkResult walk(T element) {
47 return walk<WalkOrder::PostOrder, T>(element);
48 }
49
50 //===--------------------------------------------------------------------===//
51 // Registration
52 //===--------------------------------------------------------------------===//
53
54 template <typename T>
55 using WalkFn = std::function<WalkResult(T)>;
56
57 /// Register a walk function for a given attribute or type. A walk function
58 /// must be convertible to any of the following forms(where `T` is a class
59 /// derived from `Type` or `Attribute`:
60 ///
61 /// * WalkResult(T)
62 /// - Returns a walk result, which can be used to control the walk
63 ///
64 /// * void(T)
65 /// - Returns void, i.e. the walk always continues.
66 ///
67 /// Note: When walking, the mostly recently added walk functions will be
68 /// invoked first.
70 attrWalkFns.emplace_back(std::move(fn));
71 }
72 void addWalk(WalkFn<Type> &&fn) { typeWalkFns.push_back(std::move(fn)); }
73
74 /// Register a replacement function that doesn't match the default signature,
75 /// either because it uses a derived parameter type, or it uses a simplified
76 /// result type.
77 template <typename FnT,
78 typename T = typename llvm::function_traits<
79 std::decay_t<FnT>>::template arg_t<0>,
80 typename BaseT = std::conditional_t<std::is_base_of_v<Attribute, T>,
82 typename ResultT = std::invoke_result_t<FnT, T>>
83 std::enable_if_t<!std::is_same_v<T, BaseT> || std::is_same_v<ResultT, void>>
84 addWalk(FnT &&callback) {
85 addWalk([callback = std::forward<FnT>(callback)](BaseT base) -> WalkResult {
86 if (auto derived = dyn_cast<T>(base)) {
87 if constexpr (std::is_convertible_v<ResultT, WalkResult>)
88 return callback(derived);
89 else
90 callback(derived);
91 }
92 return WalkResult::advance();
93 });
94 }
95
96private:
97 WalkResult walkImpl(Attribute attr, WalkOrder order);
98 WalkResult walkImpl(Type type, WalkOrder order);
99
100 /// Internal implementation of the `walk` methods above.
101 template <typename T, typename WalkFns>
102 WalkResult walkImpl(T element, WalkFns &walkFns, WalkOrder order);
103
104 /// Walk the sub elements of the given interface.
105 template <typename T>
106 WalkResult walkSubElements(T interface, WalkOrder order);
107
108 /// The set of walk functions that map sub elements.
109 std::vector<WalkFn<Attribute>> attrWalkFns;
110 std::vector<WalkFn<Type>> typeWalkFns;
111
112 /// The set of visited attributes/types.
114};
115
116//===----------------------------------------------------------------------===//
117/// AttrTypeReplacer
118//===----------------------------------------------------------------------===//
119
120namespace detail {
121
122/// This class provides a base utility for replacing attributes/types, and their
123/// sub elements. Multiple replacement functions may be registered.
124///
125/// This base utility is uncached. Users can choose between two cached versions
126/// of this replacer:
127/// * For non-cyclic replacer logic, use `AttrTypeReplacer`.
128/// * For cyclic replacer logic, use `CyclicAttrTypeReplacer`.
129///
130/// Concrete implementations implement the following `replace` entry functions:
131/// * Attribute replace(Attribute attr);
132/// * Type replace(Type type);
133template <typename Concrete>
135public:
136 //===--------------------------------------------------------------------===//
137 // Application
138 //===--------------------------------------------------------------------===//
139
140 /// Replace the elements within the given operation. If `replaceAttrs` is
141 /// true, this updates the attribute dictionary of the operation. If
142 /// `replaceLocs` is true, this also updates its location, and the locations
143 /// of any nested block arguments. If `replaceTypes` is true, this also
144 /// updates the result types of the operation, and the types of any nested
145 /// block arguments.
146 void replaceElementsIn(Operation *op, bool replaceAttrs = true,
147 bool replaceLocs = false, bool replaceTypes = false);
148
149 /// Replace the elements within the given operation, and all nested
150 /// operations.
151 void recursivelyReplaceElementsIn(Operation *op, bool replaceAttrs = true,
152 bool replaceLocs = false,
153 bool replaceTypes = false);
154
155 //===--------------------------------------------------------------------===//
156 // Registration
157 //===--------------------------------------------------------------------===//
158
159 /// A replacement mapping function, which returns either std::nullopt (to
160 /// signal the element wasn't handled), or a pair of the replacement element
161 /// and a WalkResult.
162 template <typename T>
163 using ReplaceFnResult = std::optional<std::pair<T, WalkResult>>;
164 template <typename T>
165 using ReplaceFn = std::function<ReplaceFnResult<T>(T)>;
166
167 /// Register a replacement function for mapping a given attribute or type. A
168 /// replacement function must be convertible to any of the following
169 /// forms(where `T` is a class derived from `Type` or `Attribute`, and `BaseT`
170 /// is either `Type` or `Attribute` respectively):
171 ///
172 /// * std::optional<BaseT>(T)
173 /// - This either returns a valid Attribute/Type in the case of success,
174 /// nullptr in the case of failure, or `std::nullopt` to signify that
175 /// additional replacement functions may be applied (i.e. this function
176 /// doesn't handle that instance).
177 ///
178 /// * std::optional<std::pair<BaseT, WalkResult>>(T)
179 /// - Similar to the above, but also allows specifying a WalkResult to
180 /// control the replacement of sub elements of a given attribute or
181 /// type. Returning a `skip` result, for example, will not recursively
182 /// process the resultant attribute or type value.
183 ///
184 /// Note: When replacing, the mostly recently added replacement functions will
185 /// be invoked first.
188
189 /// Register a replacement function that doesn't match the default signature,
190 /// either because it uses a derived parameter type, or it uses a simplified
191 /// result type.
192 template <typename FnT,
193 typename T = typename llvm::function_traits<
194 std::decay_t<FnT>>::template arg_t<0>,
195 typename BaseT = std::conditional_t<std::is_base_of_v<Attribute, T>,
196 Attribute, Type>,
197 typename ResultT = std::invoke_result_t<FnT, T>>
198 std::enable_if_t<!std::is_same_v<T, BaseT> ||
199 !std::is_convertible_v<ResultT, ReplaceFnResult<BaseT>>>
200 addReplacement(FnT &&callback) {
201 addReplacement([callback = std::forward<FnT>(callback)](
202 BaseT base) -> ReplaceFnResult<BaseT> {
203 if (auto derived = dyn_cast<T>(base)) {
204 if constexpr (std::is_convertible_v<ResultT, std::optional<BaseT>>) {
205 std::optional<BaseT> result = callback(derived);
206 return result ? std::make_pair(*result, WalkResult::advance())
208 } else {
209 return callback(derived);
210 }
211 }
212 return ReplaceFnResult<BaseT>();
213 });
214 }
215
216protected:
217 /// Invokes the registered replacement functions from most recently registered
218 /// to least recently registered until a successful replacement is returned.
219 /// Unless skipping is requested, invokes `replace` on sub-elements of the
220 /// current attr/type.
222 Type replaceBase(Type type);
223
224private:
225 /// The set of replacement functions that map sub elements.
226 std::vector<ReplaceFn<Attribute>> attrReplacementFns;
227 std::vector<ReplaceFn<Type>> typeReplacementFns;
228};
229
230} // namespace detail
231
232/// This is an attribute/type replacer that is naively cached. It is best used
233/// when the replacer logic is guaranteed to not contain cycles. Otherwise, any
234/// re-occurrence of an in-progress element will be skipped.
235class AttrTypeReplacer : public detail::AttrTypeReplacerBase<AttrTypeReplacer> {
236public:
238 Type replace(Type type);
239
240private:
241 /// Shared concrete implementation of the public `replace` functions. Invokes
242 /// `replaceBase` with caching.
243 template <typename T>
244 T cachedReplaceImpl(T element);
245
246 // Stores the opaque pointer of an attribute or type.
248};
249
250/// This is an attribute/type replacer that supports custom handling of cycles
251/// in the replacer logic. In addition to registering replacer functions, it
252/// allows registering cycle-breaking functions in the same style.
254 : public detail::AttrTypeReplacerBase<CyclicAttrTypeReplacer> {
255public:
257
258 //===--------------------------------------------------------------------===//
259 // Application
260 //===--------------------------------------------------------------------===//
261
263 Type replace(Type type);
264
265 //===--------------------------------------------------------------------===//
266 // Registration
267 //===--------------------------------------------------------------------===//
268
269 /// A cycle-breaking function. This is invoked if the same element is asked to
270 /// be replaced again when the first instance of it is still being replaced.
271 /// This function must not perform any more recursive `replace` calls.
272 /// If it is able to break the cycle, it should return a replacement result.
273 /// Otherwise, it can return std::nullopt to defer cycle breaking to the next
274 /// repeated element. However, the user must guarantee that, in any possible
275 /// cycle, there always exists at least one element that can break the cycle.
276 template <typename T>
277 using CycleBreakerFn = std::function<std::optional<T>(T)>;
278
279 /// Register a cycle-breaking function.
280 /// When breaking cycles, the mostly recently added cycle-breaking functions
281 /// will be invoked first.
284
285 /// Register a cycle-breaking function that doesn't match the default
286 /// signature.
287 template <typename FnT,
288 typename T = typename llvm::function_traits<
289 std::decay_t<FnT>>::template arg_t<0>,
290 typename BaseT = std::conditional_t<std::is_base_of_v<Attribute, T>,
291 Attribute, Type>>
292 std::enable_if_t<!std::is_same_v<T, BaseT>> addCycleBreaker(FnT &&callback) {
293 addCycleBreaker([callback = std::forward<FnT>(callback)](
294 BaseT base) -> std::optional<BaseT> {
295 if (auto derived = dyn_cast<T>(base))
296 return callback(derived);
297 return std::nullopt;
298 });
299 }
300
301private:
302 /// Invokes the registered cycle-breaker functions from most recently
303 /// registered to least recently registered until a successful result is
304 /// returned.
305 std::optional<const void *> breakCycleImpl(void *element);
306
307 /// Shared concrete implementation of the public `replace` functions.
308 template <typename T>
309 T cachedReplaceImpl(T element);
310
311 /// The set of registered cycle-breaker functions.
312 std::vector<CycleBreakerFn<Attribute>> attrCycleBreakerFns;
313 std::vector<CycleBreakerFn<Type>> typeCycleBreakerFns;
314
315 /// A cache of previously-replaced attr/types.
316 /// The key of the cache is the opaque value of an AttrOrType. Using
317 /// AttrOrType allows distinguishing between the two types when invoking
318 /// cycle-breakers. Using its opaque value avoids the cyclic dependency issue
319 /// of directly using `AttrOrType` to instantiate the cache.
320 /// The value of the cache is just the opaque value of the attr/type itself
321 /// (not the PointerUnion).
322 using AttrOrType = PointerUnion<Attribute, Type>;
324};
325
326//===----------------------------------------------------------------------===//
327/// AttrTypeSubElementHandler
328//===----------------------------------------------------------------------===//
329
330/// This class is used by AttrTypeSubElementHandler instances to walking sub
331/// attributes and types.
333public:
335 function_ref<void(Type)> walkTypesFn)
336 : walkAttrsFn(walkAttrsFn), walkTypesFn(walkTypesFn) {}
337
338 /// Walk an attribute.
339 void walk(Attribute element);
340 /// Walk a type.
341 void walk(Type element);
342 /// Walk a range of attributes or types.
343 template <typename RangeT>
344 void walkRange(RangeT &&elements) {
345 for (auto element : elements)
346 walk(element);
347 }
348
349private:
350 function_ref<void(Attribute)> walkAttrsFn;
351 function_ref<void(Type)> walkTypesFn;
352};
353
354/// This class is used by AttrTypeSubElementHandler instances to process sub
355/// element replacements.
356template <typename T>
358public:
360
361 /// Take the first N replacements as an ArrayRef, dropping them from
362 /// this replacement list.
364 ArrayRef<T> elements = repls.take_front(n);
365 repls = repls.drop_front(n);
366 return elements;
367 }
368
369private:
370 /// The current set of replacements.
371 ArrayRef<T> repls;
372};
375
376/// This class provides support for interacting with the
377/// SubElementInterfaces for different types of parameters. An
378/// implementation of this class should be provided for any parameter class
379/// that may contain an attribute or type. There are two main methods of
380/// this class that need to be implemented:
381///
382/// - walk
383///
384/// This method should traverse into any sub elements of the parameter
385/// using the provided walker, or by invoking handlers for sub-types.
386///
387/// - replace
388///
389/// This method should extract any necessary sub elements using the
390/// provided replacer, or by invoking handlers for sub-types. The new
391/// post-replacement parameter value should be returned.
392///
393template <typename T, typename Enable = void>
395 /// Default walk implementation that does nothing.
396 static inline void walk(const T &param,
398
399 /// Default replace implementation just forwards the parameter.
400 template <typename ParamT>
401 static inline decltype(auto) replace(ParamT &&param,
403 TypeSubElementReplacements &typeRepls) {
404 return std::forward<ParamT>(param);
405 }
406
407 /// Tag indicating that this handler does not support sub-elements.
409};
410
411/// Detect if any of the given parameter types has a sub-element handler.
412namespace detail {
413template <typename T>
414using has_default_sub_element_handler_t = decltype(T::DefaultHandlerTag);
415} // namespace detail
416template <typename... Ts>
417inline constexpr bool has_sub_attr_or_type_v =
418 (!llvm::is_detected<detail::has_default_sub_element_handler_t, Ts>::value ||
419 ...);
420
421/// Implementation for derived Attributes and Types.
422template <typename T>
424 T, std::enable_if_t<std::is_base_of_v<Attribute, T> ||
425 std::is_base_of_v<Type, T>>> {
426 static void walk(T param, AttrTypeImmediateSubElementWalker &walker) {
427 walker.walk(param);
428 }
429 static T replace(T param, AttrSubElementReplacements &attrRepls,
430 TypeSubElementReplacements &typeRepls) {
431 if (!param)
432 return T();
433 if constexpr (std::is_base_of_v<Attribute, T>) {
434 return cast<T>(attrRepls.take_front(1)[0]);
435 } else {
436 return cast<T>(typeRepls.take_front(1)[0]);
437 }
438 }
439};
440/// Implementation for derived ArrayRef.
441template <typename T>
443 std::enable_if_t<has_sub_attr_or_type_v<T>>> {
445
446 static void walk(ArrayRef<T> param,
448 for (const T &subElement : param)
449 EltHandler::walk(subElement, walker);
450 }
451 static auto replace(ArrayRef<T> param, AttrSubElementReplacements &attrRepls,
452 TypeSubElementReplacements &typeRepls) {
453 // Normal attributes/types can extract using the replacer directly.
454 if constexpr (std::is_base_of_v<Attribute, T> &&
455 sizeof(T) == sizeof(void *)) {
456 ArrayRef<Attribute> attrs = attrRepls.take_front(param.size());
457 return ArrayRef<T>((const T *)attrs.data(), attrs.size());
458 } else if constexpr (std::is_base_of_v<Type, T> &&
459 sizeof(T) == sizeof(void *)) {
460 ArrayRef<Type> types = typeRepls.take_front(param.size());
461 return ArrayRef<T>((const T *)types.data(), types.size());
462 } else {
463 // Otherwise, we need to allocate storage for the new elements.
464 SmallVector<T> newElements;
465 for (const T &element : param)
466 newElements.emplace_back(
467 EltHandler::replace(element, attrRepls, typeRepls));
468 return newElements;
469 }
470 }
471};
472/// Implementation for Tuple.
473template <typename... Ts>
475 std::tuple<Ts...>, std::enable_if_t<has_sub_attr_or_type_v<Ts...>>> {
476 static void walk(const std::tuple<Ts...> &param,
478 std::apply(
479 [&](const Ts &...params) {
480 (AttrTypeSubElementHandler<Ts>::walk(params, walker), ...);
481 },
482 param);
483 }
484 static auto replace(const std::tuple<Ts...> &param,
486 TypeSubElementReplacements &typeRepls) {
487 return std::apply(
488 [&](const Ts &...params)
489 -> std::tuple<decltype(AttrTypeSubElementHandler<Ts>::replace(
490 params, attrRepls, typeRepls))...> {
491 return {AttrTypeSubElementHandler<Ts>::replace(params, attrRepls,
492 typeRepls)...};
493 },
494 param);
495 }
496};
497
498namespace detail {
499template <typename T>
500struct is_tuple : public std::false_type {};
501template <typename... Ts>
502struct is_tuple<std::tuple<Ts...>> : public std::true_type {};
503
504template <typename T>
505struct is_pair : public std::false_type {};
506template <typename... Ts>
507struct is_pair<std::pair<Ts...>> : public std::true_type {};
508
509template <typename T, typename... Ts>
510using has_get_method = decltype(T::get(std::declval<Ts>()...));
511template <typename T, typename... Ts>
512using has_get_as_key = decltype(std::declval<T>().getAsKey());
513
514/// This function provides the underlying implementation for the
515/// SubElementInterface walk method, using the key type of the derived
516/// attribute/type to interact with the individual parameters.
517template <typename T>
519 function_ref<void(Attribute)> walkAttrsFn,
520 function_ref<void(Type)> walkTypesFn) {
521 using ImplT = typename T::ImplType;
522 (void)derived;
523 (void)walkAttrsFn;
524 (void)walkTypesFn;
525 if constexpr (llvm::is_detected<has_get_as_key, ImplT>::value) {
526 auto key = static_cast<ImplT *>(derived.getImpl())->getAsKey();
527
528 // If we don't have any sub-elements, there is nothing to do.
529 if constexpr (!has_sub_attr_or_type_v<decltype(key)>)
530 return;
531 AttrTypeImmediateSubElementWalker walker(walkAttrsFn, walkTypesFn);
532 AttrTypeSubElementHandler<decltype(key)>::walk(key, walker);
533 }
534}
535
536/// This function invokes the proper `get` method for a type `T` with the given
537/// values.
538template <typename T, typename... Ts>
539auto constructSubElementReplacement(MLIRContext *ctx, Ts &&...params) {
540 // Prefer a direct `get` method if one exists.
541 if constexpr (llvm::is_detected<has_get_method, T, Ts...>::value) {
542 (void)ctx;
543 return T::get(std::forward<Ts>(params)...);
544 } else if constexpr (llvm::is_detected<has_get_method, T, MLIRContext *,
545 Ts...>::value) {
546 return T::get(ctx, std::forward<Ts>(params)...);
547 } else {
548 // Otherwise, pass to the base get.
549 return T::Base::get(ctx, std::forward<Ts>(params)...);
550 }
551}
552
553/// This function provides the underlying implementation for the
554/// SubElementInterface replace method, using the key type of the derived
555/// attribute/type to interact with the individual parameters.
556template <typename T>
558 ArrayRef<Type> &replTypes) {
559 using ImplT = typename T::ImplType;
560 if constexpr (llvm::is_detected<has_get_as_key, ImplT>::value) {
561 auto key = static_cast<ImplT *>(derived.getImpl())->getAsKey();
562
563 // If we don't have any sub-elements, we can just return the original.
564 if constexpr (!has_sub_attr_or_type_v<decltype(key)>) {
565 return derived;
566
567 // Otherwise, we need to replace any necessary sub-elements.
568 } else {
569 // Functor used to build the replacement on success.
570 auto buildReplacement = [&](auto newKey, MLIRContext *ctx) {
571 if constexpr (is_tuple<decltype(key)>::value ||
572 is_pair<decltype(key)>::value) {
573 return std::apply(
574 [&](auto &&...params) {
576 ctx, std::forward<decltype(params)>(params)...);
577 },
578 newKey);
579 } else {
580 return constructSubElementReplacement<T>(ctx, newKey);
581 }
582 };
583
584 AttrSubElementReplacements attrRepls(replAttrs);
585 TypeSubElementReplacements typeRepls(replTypes);
586 auto newKey = AttrTypeSubElementHandler<decltype(key)>::replace(
587 key, attrRepls, typeRepls);
588 MLIRContext *ctx = derived.getContext();
589 if constexpr (std::is_convertible_v<decltype(newKey), LogicalResult>)
590 return succeeded(newKey) ? buildReplacement(*newKey, ctx) : nullptr;
591 else
592 return buildReplacement(newKey, ctx);
593 }
594 } else {
595 return derived;
596 }
597}
598} // namespace detail
599} // namespace mlir
600
601#endif // MLIR_IR_ATTRTYPESUBELEMENTS_H
void walk(Attribute element)
Walk an attribute.
AttrTypeImmediateSubElementWalker(function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn)
void walkRange(RangeT &&elements)
Walk a range of attributes or types.
This is an attribute/type replacer that is naively cached.
Attribute replace(Attribute attr)
This class is used by AttrTypeSubElementHandler instances to process sub element replacements.
ArrayRef< T > take_front(unsigned n)
Take the first N replacements as an ArrayRef, dropping them from this replacement list.
AttrTypeSubElementReplacements(ArrayRef< T > repls)
WalkResult walk(T element)
std::function< WalkResult(T)> WalkFn
void addWalk(WalkFn< Attribute > &&fn)
Register a walk function for a given attribute or type.
void addWalk(WalkFn< Type > &&fn)
std::enable_if_t<!std::is_same_v< T, BaseT >||std::is_same_v< ResultT, void > > addWalk(FnT &&callback)
Register a replacement function that doesn't match the default signature, either because it uses a de...
WalkResult walk(T element)
Walk the given attribute/type, and recursively walk any sub elements.
Attributes are known-constant values of operations.
Definition Attributes.h:25
void addCycleBreaker(CycleBreakerFn< Attribute > fn)
Register a cycle-breaking function.
std::enable_if_t<!std::is_same_v< T, BaseT > > addCycleBreaker(FnT &&callback)
Register a cycle-breaking function that doesn't match the default signature.
Attribute replace(Attribute attr)
std::function< std::optional< T >(T)> CycleBreakerFn
A cycle-breaking function.
A cache for replacer-like functions that map values between two domains.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
A utility result that is used to signal how to proceed with an ongoing walk:
Definition WalkResult.h:29
static WalkResult advance()
Definition WalkResult.h:47
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 addReplacement(ReplaceFn< Type > fn)
std::optional< std::pair< T, WalkResult > > ReplaceFnResult
A replacement mapping function, which returns either std::nullopt (to signal the element wasn't handl...
std::enable_if_t<!std::is_same_v< T, BaseT >||!std::is_convertible_v< ResultT, ReplaceFnResult< BaseT > > > addReplacement(FnT &&callback)
Register a replacement function that doesn't match the default signature, either because it uses a de...
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.
AttrTypeReplacer.
void walk(Operation *op, function_ref< void(Region *)> callback, WalkOrder order)
Walk all of the regions, blocks, or operations nested under (and including) the given operation.
Definition Visitors.h:102
auto constructSubElementReplacement(MLIRContext *ctx, Ts &&...params)
This function invokes the proper get method for a type T with the given values.
decltype(std::declval< T >().getAsKey()) has_get_as_key
decltype(T::get(std::declval< Ts >()...)) has_get_method
auto replaceImmediateSubElementsImpl(T derived, ArrayRef< Attribute > &replAttrs, ArrayRef< Type > &replTypes)
This function provides the underlying implementation for the SubElementInterface replace method,...
void walkImmediateSubElementsImpl(T derived, function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn)
This function provides the underlying implementation for the SubElementInterface walk method,...
decltype(T::DefaultHandlerTag) has_default_sub_element_handler_t
Include the generated interface declarations.
constexpr bool has_sub_attr_or_type_v
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition Visitors.h:28
AttrTypeSubElementReplacements< Attribute > AttrSubElementReplacements
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
Definition LLVM.h:126
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152
AttrTypeSubElementReplacements< Type > TypeSubElementReplacements
static void walk(ArrayRef< T > param, AttrTypeImmediateSubElementWalker &walker)
static auto replace(ArrayRef< T > param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
static T replace(T param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
static void walk(const std::tuple< Ts... > &param, AttrTypeImmediateSubElementWalker &walker)
static auto replace(const std::tuple< Ts... > &param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
This class provides support for interacting with the SubElementInterfaces for different types of para...
static void walk(const T &param, AttrTypeImmediateSubElementWalker &walker)
Default walk implementation that does nothing.
void DefaultHandlerTag
Tag indicating that this handler does not support sub-elements.
static decltype(auto) replace(ParamT &&param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
Default replace implementation just forwards the parameter.