MLIR笔记(2)

3. LVM有趣的代码

3.1. dyn_cast()与cast()

C++支持类型间的自动转换(如operator =声明的转换),但在转换的调用链里自动转换只能调用一次,这固然是避免给编译器带来过分的复杂性,但更重要的是允许自动转换接力调用几乎很难避免出现递归调用,而且调用链过长会很快失去控制,给人带来意想不到的结果。但是,C++原生的类型转换系统对于LLVM/MLIR来说局限性太大,因此,LLVM打造了自己的类型转换系统,它仿造C++的惯例,给出了自己的类型转换函数:cast、dyn_cast。显然,它们分别对应其他cast与dynamic_cast。它们与C++版本的最大不同在于:cast、dyn_cast都支持无限次自动转换(这在用户眼皮底下发生,但用户需要提供一些指定的方法)。在这个体系中,dyn_cast最有代表性,llvm里一共定义了3个版本,它们的区别在于函数参数类型:

331  template <class X, class Y>

332  LLVM_NODISCARD inline std::enable_if_t<

333      !is_simple_type::value, typename cast_rettyconst Y>::ret_type>

334  dyn_cast(const Y &Val) {

335    return isa(Val) ? cast(Val) : nullptr;

336  }

337 

338  template <class X, class Y>

339  LLVM_NODISCARD inline typename cast_retty::ret_type dyn_cast(Y &Val) {

340    return isa(Val) ? cast(Val) : nullptr;

341  }

342 

343  template <class X, class Y>

344  LLVM_NODISCARD inline typename cast_retty::ret_type dyn_cast(Y *Val) {

345    return isa(Val) ? cast(Val) : nullptr;

346  }

在这些函数里用到isa()与cast(),isa()是这样的:它检查参数的类型是否与模板参数里给出的类型一致。

141  template <class X, class Y> LLVM_NODISCARD inline bool isa(const Y &Val) {  // 最终调用的函数

142    return isa_impl_wrapconst Y,

143                         typename simplify_type<const Y>::SimpleType>::doit(Val);

144  }

145 

146  template <typename First, typename Second, typename... Rest, typename Y>

147  LLVM_NODISCARD inline bool isa(const Y &Val) {

148    return isa(Val) || isa(Val);

149  }

实际上,isa()支持对某个类型列表,检查指定类型是否与其中一个类型一致。而两个特定类型比较的实现是由isa_impl_wrap这个类提供的:

116  template<typename To, typename From, typename SimpleFrom>

117  struct isa_impl_wrap {

118    // When From != SimplifiedType, we can simplify the type some more by using

119    // the simplify_type template.

120    static bool doit(const From &Val) {

121      return isa_impl_wrap

122        typename simplify_type::SimpleType>::doit(

123                            simplify_type<const From>::getSimplifiedValue(Val));

124    }

125  };

126 

127  template<typename To, typename FromTy>

128  struct isa_impl_wrap {

129    // When From == SimpleType, we are as simple as we are going to get.

130    static bool doit(const FromTy &Val) {

131      return isa_impl_cl::doit(Val);

132    }

133  };

为了支持无限次自动转换,这里指出了3个类型:To、From、SimpleFrom。其中,被转换值从From类型转换到SimpleFrom类型,这个SimpleFrom类型还可能进一步转换为另一个SimpleFrom类型,直到From与SimpleFrom类型一致为止,这意味着From不能再“简化了”。这时我们使用128行的isa_impl_wrap特化定义。

首先,我们先看一下完成从From到SimpleFrom的simplify_type类。注意,如果存在llvm所不知道的From到SimpleFrom的转换,必须提供这个目的的simplify_type特化版本。如果不提供,将使用simplify_type的非特化版本(llvm对自己的数据结构定义了若干simplify_type特化版本):

33  template<typename From> struct simplify_type {

34    using SimpleType = From; // The real type this represents...

35 

36    // An accessor to get the real value...

37    static SimpleType &getSimplifiedValue(From &Val) {

你可能感兴趣的:(MLIR笔记,mlir,笔记,编译,llvm)