1、利用 重载方法: val.getDefiningOpemitc::CallOpaqueOp() 和 val.getDefiningOp()class Value { private: Operation* definingOp_ nullptr; public: Operation*getDefiningOp() const { // 基础版本 return definingOp_; } template typename OpTy // 模板版本 - 调用基础版本增加类型检查 OpTy getDefiningOp() const { return llvm::dyn_cast_or_nullOpTy(getDefiningOp()); } };2、动态多态 (dyn_cast) 要求具有相同的基类。当没有相同基类时候可以使用requires(C20)模版类变量 可以使用 dyn_castBAUStructuredOp(*op) 直接类型转换也可以Operation* operation op隐式类型转换3、利用模版template typename... OpType实现多个同类算子处理template typename... OpTypesstatic void registerMAUOps(RewritePatternSet patterns) {(patterns.addInsertDataLayoutforBAUByInterfaceOpTypes(patterns.getContext()), ...);}4、return WalkResult::advance();是结束本次迭代而不是结束整个funcOp-walk5、class ConvertAtenAddOp 需要处理两个操作数的类型提升利用了返回值已经是类型提升后的类型简化Value operandA convertScalarToDtype(rewriter, loc, adaptor.getA(), resultType);6、LLVM中Pattern Rewrite通常使用一个循环来反复应用优化规则直到没有规则可以应用为止,eg:combinebool changed true; while (changed) { changed false; changed | applyPattern1(); changed | applyPattern2(); // 更多模式... }7、获取tensor的维度值Location loc addOp.getLoc();OpBuilder builder(op-getContext());SmallVectorOpFoldResult sizes tensor::getMixedSizes(builder, loc, lhs);// 使用dispatchIndexOpFoldResults将sizes解析获取静态和动态值(仅动态维)8、this-softmaxOps[softmaxOp] std::move(info);相比this-softmaxOps[softmaxOp] info 高效仅仅转移所有权而不需要复制整个容器9、创建型设计模式单例模式explicit SymbolAnalysis() default; // 禁止默认构造static SymbolAnalysis *instance; // 仅创建一次存在时直接返回10、alloc, tensor.reshape 动态shape和静态shape表达形式存在差异 11、禁用特定pattern的方法 patterns.disablePatternMyPattern2();12、寄存器分配不能使用纯回溯(智能搜索 剪枝)并非暴力遍历a) 分形传播时考虑输入间的约束则需要回溯因为一个输入的选择会影响所有其他输入 回溯剪枝b) 如果不考虑输入间的约束 只需考虑这个输入自身的约束则线性时间无需回溯动态规划/贪心算法(遵循最优子结构性质, 即一个问题的最优解包含其子问题的最优解)13、在 MLIR 中ShapedType是所有具有形状和元素类型的类型的公共基类包括TensorType、VectorType和MemRefType。可以使用ShapedType来区别标量14、方言合法性动态shape无法区分是否合法时,可以设置标记eg:target.addDynamicallyLegalOpscf::ForOp, scf::YieldOp([this](Operation *op) { if (this-dynamicShape) { auto attr op-getAttrOfTypeBoolAttr(isLegal); return attr attr.getValue(); } ... } // 相应配置newOp-setAttr(isLegal, rewriter.getBoolAttr(true));15、属性也是Op的一部分属性不一样Op就不同所以当算子加上属性后就能避免cse优化defOp-setAttr(cseBarrier, builder.getIndexAttr(currBarrier));16、实现延迟的关键是要存储行为存储行为的核心是延迟计算和策略模式的实现17、 pattern匹配后注册的优先populateArithToEmitCPatterns(patterns) { SignedCastConversionarith::IndexCastOp, // 优先级较低 IndexCastOpConversion, // 优先级较高后注册优先匹配}
mlir 编译器学习笔记之六 -- 经典实现
1、利用 重载方法: val.getDefiningOpemitc::CallOpaqueOp() 和 val.getDefiningOp()class Value { private: Operation* definingOp_ nullptr; public: Operation*getDefiningOp() const { // 基础版本 return definingOp_; } template typename OpTy // 模板版本 - 调用基础版本增加类型检查 OpTy getDefiningOp() const { return llvm::dyn_cast_or_nullOpTy(getDefiningOp()); } };2、动态多态 (dyn_cast) 要求具有相同的基类。当没有相同基类时候可以使用requires(C20)模版类变量 可以使用 dyn_castBAUStructuredOp(*op) 直接类型转换也可以Operation* operation op隐式类型转换3、利用模版template typename... OpType实现多个同类算子处理template typename... OpTypesstatic void registerMAUOps(RewritePatternSet patterns) {(patterns.addInsertDataLayoutforBAUByInterfaceOpTypes(patterns.getContext()), ...);}4、return WalkResult::advance();是结束本次迭代而不是结束整个funcOp-walk5、class ConvertAtenAddOp 需要处理两个操作数的类型提升利用了返回值已经是类型提升后的类型简化Value operandA convertScalarToDtype(rewriter, loc, adaptor.getA(), resultType);6、LLVM中Pattern Rewrite通常使用一个循环来反复应用优化规则直到没有规则可以应用为止,eg:combinebool changed true; while (changed) { changed false; changed | applyPattern1(); changed | applyPattern2(); // 更多模式... }7、获取tensor的维度值Location loc addOp.getLoc();OpBuilder builder(op-getContext());SmallVectorOpFoldResult sizes tensor::getMixedSizes(builder, loc, lhs);// 使用dispatchIndexOpFoldResults将sizes解析获取静态和动态值(仅动态维)8、this-softmaxOps[softmaxOp] std::move(info);相比this-softmaxOps[softmaxOp] info 高效仅仅转移所有权而不需要复制整个容器9、创建型设计模式单例模式explicit SymbolAnalysis() default; // 禁止默认构造static SymbolAnalysis *instance; // 仅创建一次存在时直接返回10、alloc, tensor.reshape 动态shape和静态shape表达形式存在差异 11、禁用特定pattern的方法 patterns.disablePatternMyPattern2();12、寄存器分配不能使用纯回溯(智能搜索 剪枝)并非暴力遍历a) 分形传播时考虑输入间的约束则需要回溯因为一个输入的选择会影响所有其他输入 回溯剪枝b) 如果不考虑输入间的约束 只需考虑这个输入自身的约束则线性时间无需回溯动态规划/贪心算法(遵循最优子结构性质, 即一个问题的最优解包含其子问题的最优解)13、在 MLIR 中ShapedType是所有具有形状和元素类型的类型的公共基类包括TensorType、VectorType和MemRefType。可以使用ShapedType来区别标量14、方言合法性动态shape无法区分是否合法时,可以设置标记eg:target.addDynamicallyLegalOpscf::ForOp, scf::YieldOp([this](Operation *op) { if (this-dynamicShape) { auto attr op-getAttrOfTypeBoolAttr(isLegal); return attr attr.getValue(); } ... } // 相应配置newOp-setAttr(isLegal, rewriter.getBoolAttr(true));15、属性也是Op的一部分属性不一样Op就不同所以当算子加上属性后就能避免cse优化defOp-setAttr(cseBarrier, builder.getIndexAttr(currBarrier));16、实现延迟的关键是要存储行为存储行为的核心是延迟计算和策略模式的实现17、 pattern匹配后注册的优先populateArithToEmitCPatterns(patterns) { SignedCastConversionarith::IndexCastOp, // 优先级较低 IndexCastOpConversion, // 优先级较高后注册优先匹配}