mlir 编译器学习笔记之九 -- 后端生成
方案1、在mlir中使用标准的emitc转换生成EmitC 是 MLIRMulti-Level Intermediate Representation框架中的一个官方方言Dialect而不是一个独立的编程语言标准如 C11 或 C99 那样的标准,其中总体实现可以参数社区的现有实现方法populateSCFToEmitCConversionPatterns(patterns, converter);populateHLCToEmitCConversionPatterns(patterns, converter);populateArithToEmitCPatterns(converter, patterns);populateConvertMathToEmitCPatterns(patterns, emitc::LanguageTarget::c99);populateFuncToEmitCPatterns(converter, patterns);对于结构体比如OpCommHead.opType TAU_TYPE表达%424 literal TAU_TYPE : !emitc.opaqueBauOpType%429 emitc.variable() {value #emitc.opaque{0}} : () - !emitc.lvalue!emitc.opaqueOpCommHead%431 emitc.member(%429) {member opType} : (!emitc.lvalue!emitc.opaqueOpCommHead) - !emitc.lvalue!emitc.opaqueBauOpTypeassign %424 : !emitc.opaqueBauOpType to %431 : !emitc.opaqueBauOpType方案2、直接将输出操作拼接即依次直接导入数据流1.1 基于方案1结构体的处理可以转换多元素的依次处理。比如CommHead结构// Convert CreateOpCommHeadPtrOp to emitc::VariableOp and emitc::ApplyOp.struct CreateOpCommHeadPtrOpConversion: public OpConversionPatternbau::CreateOpCommHeadPtrOp {using OpConversionPatternbau::CreateOpCommHeadPtrOp::OpConversionPattern;LogicalResultmatchAndRewrite(bau::CreateOpCommHeadPtrOp configOp, OpAdaptor adaptor,ConversionPatternRewriter rewriter) const override {auto getMemberInfo []() - SmallVectorstd::pairStringRef, SmallVectorValue {return SmallVectorstd::pairStringRef, SmallVectorValue{{wordBitmap, SmallVectorValue{adaptor.getWordBitmap()}},{condEn, SmallVectorValue{adaptor.getCondEn()}}};};return createStructOrUnionPtrbau::CreateOpCommHeadPtrOp(configOp, rewriter, this-getTypeConverter(), getMemberInfo);}};其中上面的文件也可以使用py生成比如def generate_emitc_pattern(head_data):f open(EMITC_PATTERN_FILE, w, encodingutf-8)f.write(CLANG_OFF)add_pattern_str void ADD_PATTERN_FUNCadd_pattern_str (RewritePatternSet patterns, add_pattern_str TypeConverter typeConverter) {\nadd_pattern_str MLIRContext *ctx patterns.getContext();\nfor name, _ in utils.get_struct_and_union_asembly(head_data).items():op_name utils.get_create_op_name(name)out_str get_conversion_comment(op_name) \nout_str (get_conversion_define(op_name) \n\n)out_str (get_conversion_main_func_def(op_name) \n)out_str (get_member_info_head() \n)out_str (get_member_convert_map(head_data, name, , True) };\n)out_str };\nout_str return createStructOrUnionPtrbau:: op_name (\nout_str configOp, rewriter, out_str this-getTypeConverter(), getMemberInfo);\nout_str }\nout_str };\nf.write(out_str)f.write(\n)add_pattern_str ( patterns.add get_conversion_name(op_name))add_pattern_str (typeConverter, ctx);\nadd_pattern_str }\nf.write(add_pattern_str)f.write(CLANG_ON)print(fSuccess generate {EMITC_PATTERN_FILE})1.2 基于方案1call_opaque和verbatim的主要区别call_opaque专门用来调用 C/C 函数生成格式固定、清晰的函数调用代码。verbatim一个“万能”的文本插入工具可以生成任何 C/C 代码注call_opaque的参数只能是SSA 值即其他操作的结果不能是任意表达式所以类似的内联emitc.call_opaque MyFunc(%arg0, %arg1) : (!emitc.ptri32, i32) - ()不支持需要改为emitc.verbatim MyFunc({}, {}); args %arg0, %arg12、declare_module 和 define_module 被框架/工具链强制要求放在不同的逻辑模块module中并且生成到不同的输出文件declare_module头文件define_module源文件