14 #ifndef MLIR_IR_ATTRTYPESUBELEMENTS_H
15 #define MLIR_IR_ATTRTYPESUBELEMENTS_H
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/DenseMap.h"
41 template <WalkOrder Order,
typename T>
43 return walkImpl(element, Order);
47 return walk<WalkOrder::PostOrder, T>(element);
70 attrWalkFns.emplace_back(std::move(fn));
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>>
86 if (
auto derived = dyn_cast<T>(base)) {
87 if constexpr (std::is_convertible_v<ResultT, WalkResult>)
88 return callback(derived);
101 template <
typename T,
typename WalkFns>
105 template <
typename T>
109 std::vector<WalkFn<Attribute>> attrWalkFns;
110 std::vector<WalkFn<Type>> typeWalkFns;
133 template <
typename Concrete>
147 bool replaceLocs =
false,
bool replaceTypes =
false);
152 bool replaceLocs =
false,
153 bool replaceTypes =
false);
162 template <
typename T>
164 template <
typename T>
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>,
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>>>
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);
209 return callback(derived);
226 std::vector<ReplaceFn<Attribute>> attrReplacementFns;
227 std::vector<ReplaceFn<Type>> typeReplacementFns;
243 template <
typename T>
244 T cachedReplaceImpl(T element);
276 template <
typename T>
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>,
294 BaseT base) -> std::optional<BaseT> {
295 if (
auto derived = dyn_cast<T>(base))
296 return callback(derived);
305 std::optional<const void *> breakCycleImpl(
void *element);
308 template <
typename T>
309 T cachedReplaceImpl(T element);
312 std::vector<CycleBreakerFn<Attribute>> attrCycleBreakerFns;
313 std::vector<CycleBreakerFn<Type>> typeCycleBreakerFns;
336 : walkAttrsFn(walkAttrsFn), walkTypesFn(walkTypesFn) {}
343 template <
typename RangeT>
345 for (
auto element : elements)
356 template <
typename T>
365 repls = repls.drop_front(n);
393 template <
typename T,
typename Enable =
void>
396 static inline void walk(
const T ¶m,
400 template <
typename ParamT>
401 static inline decltype(
auto)
replace(ParamT &¶m,
404 return std::forward<ParamT>(param);
413 template <
typename T>
416 template <
typename... Ts>
418 (!llvm::is_detected<detail::has_default_sub_element_handler_t, Ts>::value ||
422 template <
typename T>
424 T, std::enable_if_t<std::is_base_of_v<Attribute, T> ||
425 std::is_base_of_v<Type, T>>> {
433 if constexpr (std::is_base_of_v<Attribute, T>) {
441 template <
typename T>
443 std::enable_if_t<has_sub_attr_or_type_v<T>>> {
448 for (
const T &subElement : param)
454 if constexpr (std::is_base_of_v<Attribute, T> &&
455 sizeof(T) ==
sizeof(
void *)) {
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 *)) {
461 return ArrayRef<T>((
const T *)types.data(), types.size());
465 for (
const T &element : param)
466 newElements.emplace_back(
467 EltHandler::replace(element, attrRepls, typeRepls));
473 template <
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...> ¶m,
479 [&](
const Ts &...params) {
484 static auto replace(
const std::tuple<Ts...> ¶m,
488 [&](
const Ts &...params)
490 params, attrRepls, typeRepls))...> {
499 template <
typename T>
501 template <
typename... Ts>
502 struct is_tuple<std::tuple<Ts...>> :
public std::true_type {};
504 template <
typename T>
506 template <
typename... Ts>
507 struct is_pair<std::pair<Ts...>> :
public std::true_type {};
509 template <
typename T,
typename... Ts>
511 template <
typename T,
typename... Ts>
517 template <
typename T>
521 using ImplT =
typename T::ImplType;
525 if constexpr (llvm::is_detected<has_get_as_key, ImplT>::value) {
526 auto key =
static_cast<ImplT *
>(derived.getImpl())->getAsKey();
538 template <
typename T,
typename... Ts>
541 if constexpr (llvm::is_detected<has_get_method, T, Ts...>::value) {
543 return T::get(std::forward<Ts>(params)...);
546 return T::get(ctx, std::forward<Ts>(params)...);
556 template <
typename T>
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();
570 auto buildReplacement = [&](
auto newKey,
MLIRContext *ctx) {
571 if constexpr (
is_tuple<decltype(key)>::value ||
572 is_pair<decltype(key)>::value) {
574 [&](
auto &&...params) {
575 return constructSubElementReplacement<T>(
576 ctx, std::forward<decltype(params)>(params)...);
580 return constructSubElementReplacement<T>(ctx, newKey);
587 key, attrRepls, typeRepls);
589 if constexpr (std::is_convertible_v<decltype(newKey), LogicalResult>)
590 return succeeded(newKey) ? buildReplacement(*newKey, ctx) :
nullptr;
592 return buildReplacement(newKey, ctx);
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.
AttrTypeSubElementReplacements(ArrayRef< T > repls)
ArrayRef< T > take_front(unsigned n)
Take the first N replacements as an ArrayRef, dropping them from this replacement list.
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.
This is an attribute/type replacer that supports custom handling of cycles in the replacer logic.
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.
MLIRContext is the top-level object for a collection of MLIR operations.
Operation is the basic unit of execution within MLIR.
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:
static WalkResult advance()
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
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 addReplacement(ReplaceFn< Attribute > fn)
Register a replacement function for mapping a given attribute or type.
void replaceElementsIn(Operation *op, bool replaceAttrs=true, bool replaceLocs=false, bool replaceTypes=false)
Replace the elements within the given operation.
std::optional< std::pair< T, WalkResult > > ReplaceFnResult
A replacement mapping function, which returns either std::nullopt (to signal the element wasn't handl...
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.
decltype(std::declval< T >().getAsKey()) has_get_as_key
auto constructSubElementReplacement(MLIRContext *ctx, Ts &&...params)
This function invokes the proper get method for a type T with the given values.
decltype(T::DefaultHandlerTag) has_default_sub_element_handler_t
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::get(std::declval< Ts >()...)) has_get_method
@ Type
An inlay hint that for a type annotation.
Include the generated interface declarations.
constexpr bool has_sub_attr_or_type_v
WalkOrder
Traversal order for region, block and operation walk utilities.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
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(T param, AttrTypeImmediateSubElementWalker &walker)
static void walk(const std::tuple< Ts... > ¶m, AttrTypeImmediateSubElementWalker &walker)
static auto replace(const std::tuple< Ts... > ¶m, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
This class provides support for interacting with the SubElementInterfaces for different types of para...
static void walk(const T ¶m, 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 &¶m, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
Default replace implementation just forwards the parameter.