提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
官方指南:https://mlir.llvm.org/docs/Tutorials/Toy
- 用dialect多层逐级向下抽象lowing,多层语义统一
一、Toy 和 AST(抽象语法树)
AST结构:
Model:
Function
Proto 'name' @path.toy:row:col'
Params: [param1]
Block {
Return
VarDecl
}
从Toy语言到AST的parser可以参考llvm的https://llvm.org/docs/tutorial/MyFirstLanguageFrontend/LangImpl02.html
二、Basic MLIR
- Dialects: attribute相关的定义,在不同的namespace中表示,图中可以混合多个Dialect定义,分级lowing。
- Operations: instructions, globals (like functions), modules
在toy Dialect中的transpose operation集成方式:
%t_tensor = "toy.transpose"(%tensor) {inplace = true} : (tensor<2x3xf64>) -> tensor<3x2xf64> loc("example/file/path":12:1)
其中一个operation需要包含的概念:
- name(toy.transpose)
- SSA计算值(返回值%t_tensor,输入%tensor)
- 属性(inplace = true)
- result type(-> tensor<3x2xf64> )
- 源码位置(loc(“example/file/path”:12:1))
- successors blocks (for branches, mostly)
- regions (for structural operations like functions)
Toy Dialect
- c++ 继承,
class ToyDialect : public mlir::Dialect
- TableGen,在ODS框架里定义,
def Toy_Dialect : Dialect
,https://llvm.org/docs/TableGen/ProgRef.html
加载自定义dialect: context.loadDialect<ToyDialect>();
内置的dialect:https://mlir.llvm.org/docs/Dialects/Builtin/
Toy Operations
-
c++ 模板
自定义的op继承mlir::Op,基类是一个CRTP(奇异递归模板模式),class ToyXXOp : public mlir::Op<ToyXXOp, mlir::OpTrait::xxxx>
。Trait可以有很多,描述op属性。
注册:void ToyDialect::initialize() { addOperations<ToyXXOp>(); }
- Operation:真实数据存储在reference里,需要传递值
- Op:基类,wrapper (*operation) 的智能指针
mlir::Operation *operation; ToyXXOp op = llvm::dyn_cast<ToyXXOp>(operation); mlir::Operation *internalOperation = op.getOperation(); // 获取op里面wrapper的operation
-
ODS Framework
Operation Definition Specification:https://mlir.llvm.org/docs/OpDefinitions/
编译阶段自动由TableGen生成,继承自Op类。
Toy Dialect的基类op定义为class Toy_Op<string mnemonic, list<Trait> traits = []> :Op<Toy_Dialect, mnemonic, traits>;
Toy里自定义的op为:def ToyXXOp : Toy_Op<"XX"> { let arguments = (ins F64ElementsAttr:$value); let results = (outs F64Tensor); let hasVerifier = 1; let builders = [ OpBuilder<(ins "double":$value)> ]; }
三、Transformation(High-level)
在Toy Dialect高级语义基础上做 local pattern-match transformations。MLIR’s Generic DAG Rewriter:https://mlir.llvm.org/docs/PatternRewriter/
- c++ pattern-match
继承mlir::OpRewritePattern<ToyXXOp>
并重写matchAndRewrite
。
注册:// 在ToyXXOp的Canonicalization framework中 void TransposeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { results.add<SimplifyRedundantTranspose>(context); } // 在主流程中,把optimization加到PassManager里 mlir::PassManager pm(module.getContext()); pm.addNestedPass<mlir::toy::FuncOp>(mlir::createCanonicalizerPass());
- DRR
https://mlir.llvm.org/docs/DeclarativeRewrites/
只能用于通过ODS注册的op
重写规则class Pattern<dag sourcePattern, list<dag> resultPatterns, list<dag> additionalConstraints = [], dag benefitsAdded = (addBenefit 0)>; // 例子:Reshape(Reshape(x)) 替换为 Reshape(x) def ReshapeReshapeOptPattern : Pat<(ReshapeOp(ReshapeOp $arg)), (ReshapeOp $arg)>; // 带参数限制条件的pattern // 例子:r