I have this MLIR code consisting of a mix of Standard, Linalg, and SCF dialects. I wish to lower the Linalg and SCF operations to the Standard dialect, and then lower the Standard dialect to the LLVM dialect.
module {
func @main() {
// Create constants for the lower and upper bounds of an integer range [1,10]
%c1_i32 = constant 1 : i32
%c10_i32 = constant 10 : i32
// Compute the size of a rank 1 dynamic-size memref to contain all elements in the range [1,10]
%c1_i32_0 = constant 1 : i32
%0 = subi %c10_i32, %c1_i32 : i32
%1 = addi %0, %c1_i32_0 : i32
%2 = index_cast %1 : i32 to index
// Allocate space and write the values of the range [1,10] into it
%3 = alloca(%2) : memref<?xi32>
%c0 = constant 0 : index
%c1 = constant 1 : index
scf.parallel (%arg0) = (%c0) to (%2) step (%c1) {
%6 = index_cast %arg0 : index to i32
%7 = addi %c1_i32, %6 : i32
store %7, %3[%arg0] : memref<?xi32>
scf.yield
}
// Make a copy of the above
%c0_1 = constant 0 : index
%4 = dim %3, %c0_1 : memref<?xi32>
%5 = alloca(%4) : memref<?xi32>
linalg.copy(%3, %5) : memref<?xi32>, memref<?xi32>
return
}
}
I can successfully lower the above MLIR code to the LLVM dialect by invoking mlir-opt -convert-scf-to-std -convert-linalg-to-std -convert-std-to-llvm
.
However, when I try to accomplish the same task via C++ using the following pass:
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVM.h"
#include "mlir/Conversion/StandardToLLVM/ConvertStandardToLLVMPass.h"
#include "mlir/Conversion/SCFToStandard/SCFToStandard.h"
#include "mlir/Conversion/LinalgToStandard/LinalgToStandard.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/SCF/SCF.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
using namespace mlir;
struct LLVMLoweringPass : public PassWrapper<LLVMLoweringPass, OperationPass<ModuleOp>> {
void getDependentDialects(DialectRegistry ®istry) const override {
registry.insert<LLVM::LLVMDialect>();
}
void runOnOperation() final {
LLVMConversionTarget target(getContext());
target.addLegalOp<ModuleOp, ModuleTerminatorOp>();
LLVMTypeConverter typeConverter(&getContext());
OwningRewritePatternList patterns;
linalg::populateLinalgToStandardConversionPatterns(patterns, &getContext());
populateLoopToStdConversionPatterns(patterns, &getContext());
populateStdToLLVMConversionPatterns(typeConverter, patterns);
auto module = getOperation();
if (failed(applyFullConversion(module, target, std::move(patterns))))
signalPassFailure();
}
};
I get an error: failed to legalize operation 'scf.parallel'
With debug info:
//===-------------------------------------------===//
Legalizing operation : 'scf.parallel'(0xced760) {
* Fold {
} -> FAILURE : unable to fold
* Pattern : 'scf.parallel -> ()' {
** Insert : 'scf.yield'(0xd49a10)
** Insert : 'scf.for'(0xd14510)
** Insert : 'std.index_cast'(0xd296e0)
** Insert : 'std.addi'(0xd49a70)
** Insert : 'std.store'(0xd49b20)
** Replace : 'scf.parallel'(0xced760)
//===-------------------------------------------===//
Legalizing operation : 'scf.yield'(0xd49a10) {
"scf.yield"() : () -> ()
* Fold {
} -> FAILURE : unable to fold
} -> FAILURE : no matched legalization pattern
//===-------------------------------------------===//
} -> FAILURE : generated operation 'scf.yield'(0x0000000000D49A10) was illegal
} -> FAILURE : no matched legalization pattern
//===-------------------------------------------===//
I am not sure how to resolve this issue and would like some help with debugging.
I’m still quite new to MLIR (and compilers in general), so please bear with me.
In-case this is useful: I am using LLVM version 12.0.0git, pulled from the master branch. Last commit: 8b87fdb2079fad046b0611ac5e14aca921877c51