MLIR 学习笔记

  • 参考 MLIR 官网、MLIR 技术细节整理以及 MLIR 源码完成。其中一些细节可能随 LLVM 版本变化而变化。
  • 学到哪里写到哪里。

文章目录

  • IR 结构
    • mlir::Operation
      • mlir::Op
    • mlir::Block
    • mlir::Region
    • mlir::Value
    • mlir::Type
    • mlir::Attribute
  • 操作定义规范(ODS)
    • TableGen语法
    • Op
  • Conversion 方言转换
    • Pattern 模式匹配
    • Builder 生成器 / PatternRewriter / ConversionPatternRewriter
    • TypeConverter 类型转换器
    • ConversionTarget
    • ConversionConfig

IR 结构

MLIR 结构按照 mlir::Operation -> mlir::Region -> mlir::Block -> mlir::Operation 规则循环嵌套。一般情况下 mlir::ModuleOp 为最外层。

mlir::Operation

MLIR 所有操作的基础

可以视作有如下域 说明 方法
parent 父节点 Block *getBlock()
name 名称 OperationName getName()
location 位置 Location getLoc()
discardableAttrs/attrs 普通属性 ArrayRef getDiscardableAttrs()
inherentAttrs/properties 固有属性 std::optional getInherentAttr(StringRef name)
operands 操作数 operand_range getOperands()
results 返回值 result_range getResults()
regions 子区域 MutableArrayRef getRegions()
successors 后继(仅 terminator) SuccessorRange getSuccessors()
uses/users 使用关系 use_range getUses(); user_range getUsers()

注:

  • inherentAttrs/properties 主要由 tablegen 定义,主要包括 arguments 中的 Attr 类型参数以及部分 Trait 生成,用于与普通属性(attribute)区分。而 ArrayRef getAttrs() 方法可以同时获得两种属性。

    // 示例
    // 使用<{...}>表示固有属性
    // 使用{...}表示普通属性
    %1 = "func.call"(%0) <{callee = @func}> {newattr = "test"} : (i32) -> i32
    
  • 使用walk函数遍历

  • 可定义 RegionKindInterface,默认情况下 RegionRegionKind::SSACFG 模式,表示存在 SSA 格式的控制流;也可以设置为 RegionKind::Graph 模式 ,表示 Region 内无控制流。

mlir::Op

tablegen 中继承 Op 时生成的基类,MLIR中的绝大多数操作都通过它来生成。可以视为 mlir::Operation 的某种封装?根据不同操作的实际需要,可以在tablegen文件中自定义。

可以视作有如下域 说明 方法
Operation *state 操作 Operation *getOperation()
Properties(实际储存在 state 中) 固有属性 InferredProperties &getProperties()

注:

  • mlir::Op 定义了操作 *->,因此既可以使用 op.func 访问 mlir::Op 及其子类封装的方法,也可以使用 op->func 访问 mlir::Operation 类的方法。

  • MLIR 里的模块、函数、控制流等等结构实际上都可以定义为 mlir::Op

mlir::Block

用于包裹一组 mlir::Operation

可以视作有如下域 说明 方法
parent 父节点 Region *getParent()
operations 一组操作 OpListType &getOperations()
arguments 参数 BlockArgListType getArguments()
terminator 终结符操作 Operation *getTerminator()
successors 前驱(由 terminator 计算) SuccessorRange getSuccessors()
predecessors 后继(由 terminator 计算) iterator_range getPredecessors()

注:

  • 使用 walk 函数遍历
  • llvm::Block 的定义不同,默认情况下 mlir::Block 内定义的值,可视范围仅为当前 Block 及其嵌套子结构,无法跨越 Block 边界,因此无法像 LLVM IR 中一样通过 Phi 节点实现跨 Block 的 SSA 结构,而是必须要通过参数传递的方式显示传递所有的值。

mlir::Region

用于包裹一组 mlir::Block

可以视作有如下域 说明 方法
blocks 一组 Block BlockListType &getBlocks()
arguments 首个 Block 的参数 BlockArgListType getArguments()
parent/container 父节点 Operation *getParentOp()
CFG 调试用 void viewGraph()

注:

  • 使用 walk 函数遍历

mlir::Value

类似 llvm::Value 作用,表示值。
// TODO SSA 模式与图模式

mlir::Type

// TODO

mlir::Attribute

// TODO

操作定义规范(ODS)

使用 TableGen 自动生成 C++ 代码的方法(文件名以 .inc 为结尾),这些代码需要手动导入。

TableGen语法

与 C++ 语法类似,文件名以 .td 结尾,需要使用专门的后端编译。详细语法参考 TableGen Programmer’s Reference。(需要注意,这一套规则仅供语法参考,实际的 MLIR 方言生成大多使用特殊规则,需要看特定注释,简单的建议只使用 let)

  • class 可以继承,使用如下。TableGen class 的作用类似于 C++ 中的模板,需要 def 才会实际生成 C++ 类。
    class A : B {
      let x = t1; // 覆盖父类的字段
      Type3 y = ?; // 定义新的字段
      code z = [{ ... }]; // 强调该字段是代码, [{ ... }]包裹一段字符串,可以转行。
      defvar t = 0; // 定义一个局部变量(不是字段),例如 defvar t = !ne(t2, "b");
      assert condition, message; // 若条件为假,打印一条非致命错误信息
      ...
    }
    
  • def 生成对应的 C++ 类。
    def a: A<"name", "size">{
      ...
    }
    
  • dag td参数可以是有向无环图(DAG),使用 (operator arg0, arg1, argN) 表示,operator 可以是任何 def ,常用的有 ins outs region

注:

  • 在 CMakeLists.txt 中可以很方便地使用 MLIR 提供的方法生成 .inc
    • 使用 add_circt_dialect(dialect dialect_namespace) 生成六个常用文件 ${dialect}.h.inc${dialect}.cpp.inc${dialect}Types.h.inc${dialect}Types.cpp.inc${dialect}Dialect.h.inc${dialect}Dialect.cpp.inc
    • 使用 add_mlir_interface(interface) 生成两个常用文件 ${interface}.h.inc${interface}.cpp.inc

Op

定义文件 mlir/include/mlir/IR/OpBase.td ,专门用于生成 mlir::Op 派生类的模板,挑一些我觉得重要的列出

字段 说明 生成C++类方法
string summary 简短描述
string description 详细描述
dag arguments 操作的参数,分操作数与属性(固有属性)两种。操作数为运行时值,属性为编译时常量 每个命名参数的 getter
dag results 返回值 每个命名返回值的 getter
dag regions 定义操作的子域 每个命名域的 getter
list builders 使用 mlir::OpBuilder::create 函数生成对应 Op 时,会调用 build 函数 默认生成两种常用的builder,在这里可以声明其他 builder
string assemblyFormat 自定义汇编格式,可通过设置 hasCustomAssemblyFormat 在 C++ 文件中自定义 生成 parser 与 print 两个函数
list traits traits, interfaces, and constraints 都被定义在这里,似乎可以从 InterfaceMap 中看到所有的内容。有点乱还没完全搞清楚
code extraClassDeclaration 额外的成员函数声明
code extraClassDefinition 额外的成员函数定义

其中汇编格式查询文档参考。

Conversion 方言转换

基于 pattern-match 模式的规则转换,基于 target, patterns, config 等定义的 mlir::OperationConverter ,通常有 PartialFullAnalysis 三种模式。三者均会以先序遍历的方式遍历控制树(包括嵌套子结构),并进行相应的类型转换。

注意:

  • 遍历的顺序可能会被改变,详见下文 生成器 章节

Pattern 模式匹配

所有匹配都需要重写 matchrewrite,或重写 matchAndRewrite 函数实现。需要满足以下约束:

  • match 阶段 IR 不应发生变化
  • 所有的 IR 改变均需要通过给定的 rewriter 修改
  • 匹配分为两种模式,即字符串匹配与按照标签匹配,其中标签有任意、interfaceIDtraitID 三种
类型 说明 注意事项
mlir::RewritePattern 虚基类
mlir::ConversionPattern 方言转换的基类 封装 matchAndRewrite,暴露操作数映射后的值;可添加类型转换器;
mlir::OpConversionPattern 针对 mlir::Op 派生类的封装 依据操作名进行字符串匹配;
mlir::OpInterfaceConversionPattern 针对 mlir::OpInterface 派生类的封装 依据 interfaceID 进行匹配
mlir::OpTraitConversionPattern 几乎没人用? 依据 TraitType 进行匹配

Builder 生成器 / PatternRewriter / ConversionPatternRewriter

类型 说明
mlir::Builder 生成器的基类,管理内置的类型、属性、与 affine 表达式;
mlir::OpBuilder 提供基本的 IR 生成、克隆功能;内置 InsertPoint;内置 Listener,用于通知 IR 的变更
mlir::RewriterBase/mlir::PatternRewriter 重写器的基类,提供大量 IR 重写方法
mlir::ConversionPatternRewriter 提供大量 IR 转换的方法;内置 ConversionPatternRewriterImpl ,记录所有的 IRRewrite 过程

其中 mlir::detail::ConversionPatternRewriterImpl 常用的记录状态如下

说明
mapping 记录 ValueBlockOperation 三种映射关系
rewrites 记录所有 IRRewrite 过程
replacedOps 记录删除/替换的操作
regionToConverter 记录每个 Region 使用的类型转换器

其中 IRRewrite 分为如下几类,可能会对 matchAndRewrite 的遍历顺序有一定影响:

类型 说明 对遍历的影响
BlockRewrite 直接反映到 IR 上,不可回退 会检查 block 参数;并立刻遍历父节点
MoveOperationRewrite 直接反映到 IR 上,不可回退
ModifyOperationRewrite 直接反映到 IR 上,但修改前操作会记录,可回退 立刻遍历修改后的节点
ReplaceOperationRewrite 删除/替换均记录为 ReplaceOperationRewrite,不直接反映到 IR 上,直到调用 commit 方法才会真实修改 IR,可回退
CreateOperationRewrite 直接反映到 IR,不可回退 立刻遍历新生成的节点
UnresolvedMaterializationRewrite -

TypeConverter 类型转换器

ConversionTarget

ConversionConfig

你可能感兴趣的:(mlir,笔记)