在第五章Partial Lowing的基础上,现在进行Full Lowing,即将目前的Multi-dialect(Affine Dialect和Standard Dialect,以及遗留的Toy.PrintOp)全部lowing到LLVM dialect,对于生成的LLVM IR,可以直接使用LLVM JIT完成程序的执行。
首先我们来对Toy.PrintOp进行匹配转换Pattern的定义,因为Affine和Standard Dialect内都有d 相应LLVM dialect的Pattern可以直接使用。
class PrintOpLowering : public ConversionPattern {
public:
explicit PrintOpLowering(MLIRContext *context)
: ConversionPattern(toy::PrintOp::getOperationName(), 1, context) {}
LogicalResult
matchAndRewrite(Operation *op, ArrayRef<Value> operands,
ConversionPatternRewriter &rewriter) const override {
}
};
以上代码定义toy中的Print Operation Lowing到LLVM的类,其中包括匹配重写函数,匹配toy的printOp并生成对LLVM的printf函数的调用,从而实现printOp的lowing。
然后我们对现存的mlir Dialect表示完全lowing到LLVM表示,首先定义ToyToLLVMLoweringPass类,并在其中的runOnOperation()函数中定义最终转换目标为LLVM并填充Pattern匹配转换集:
LLVMConversionTarget target(getContext());
target.addLegalOp<ModuleOp>();
LLVMTypeConverter typeConverter(&getContext());
RewritePatternSet patterns(&getContext());
populateAffineToStdConversionPatterns(patterns);
populateSCFToControlFlowConversionPatterns(patterns);
mlir::arith::populateArithToLLVMConversionPatterns(typeConverter, patterns);
populateFinalizeMemRefToLLVMConversionPatterns(typeConverter, patterns);
cf::populateControlFlowToLLVMConversionPatterns(typeConverter, patterns);
populateFuncToLLVMConversionPatterns(typeConverter, patterns);
patterns.add<PrintOpLowering>(&getContext());
第二步应用这些Pattern并执行完全转换:
auto module = getOperation();
if (failed(applyFullConversion(module, target, std::move(patterns))))
signalPassFailure();
最后,在pm中登记ToyToLLVMLoweringPass:
if (isLoweringToLLVM) {
pm.addPass(mlir::toy::createLowerToLLVMPass());
// This is necessary to have line tables emitted and basic
// debugger working. In the future we will add proper debug information
// emission directly from our frontend.
pm.addPass(mlir::LLVM::createDIScopeForLLVMFuncOpPass());
}
到此为止我们可以得到LLVM IR的mlir表达式,如果要进一步生成LLVM IR表达式,则调用:
auto llvmModule = mlir::translateModuleToLLVMIR(module, llvmContext);
当然对于LLVM IR的mlir表达式,我们也可以选择直接JIT运行得到结果。