Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Complete MLIR Lowering to LLVM Dialect

Notes 3

Building upon the partial lowering described in the previous section, this process completes the transformation of the multi-dialect IR (comprising Affine, Standard, and legacy Toy.PrintOp dialects) into the LLVM dialect. The reuslting LLVM IR can then be executed using LLVM's JIT execution engine.

First, define a pattern for converting Toy.PrintOp operations to their LLVM counterparts. Since both Affine and Standard dialects contain relevant constructs, direct LLVM dialect patterns can be utilized.

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 {
    // Implementation details for rewriting PrintOp to LLVM printf call
  }
};

This class implements the lowering of the Toy print operation to LLVM, including a matching and rewriting function that converts toy::PrintOp into calls to LLVM's printf intrinsic.

Next, perform full dialect conversion to LLVM representation. Begin by defining the ToyToLLVMLoweringPass class and implementing its runOnOperation method to set up the conversion target and patttern set:

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());

Then apply these patterns to execute the complete lowering transformation:

auto module = getOperation();
if (failed(applyFullConversion(module, target, std::move(patterns))))
  signalPassFailure();

Finally, register the ToyToLLVMLoweringPass within the pass manager:

if (isLoweringToLLVM) {
  pm.addPass(mlir::toy::createLowerToLLVMPass());
  // Required for emitting line tables and enabling basic debugging.
  // Future versions will support full debug information emission.
  pm.addPass(mlir::LLVM::createDIScopeForLLVMFuncOpPass());
}

At this point, the MLIR module represents valid LLVM IR. To generate the actual LLVM IR text, invoke:

auto llvmModule = mlir::translateModuleToLLVMIR(module, llvmContext);

Alternatively, the LLVM IR can be executed directly through JIT compilation.

Related Articles

Designing Alertmanager Templates for Prometheus Notifications

How to craft Alertmanager templates to format alert messages, improving clarity and presentation. Alertmanager uses Go’s text/template engine with additional helper functions. Alerting rules referenc...

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.