Related: [RFC] mlir-spirv-runner
Current implementation: https://reviews.llvm.org/D86108
I have created a prototype for mlir-spirv-runner
that executes a gpu kernel on the cpu via SPIR-V to LLVM conversion. As a part of the runner, I need to link and execute 2 MLIR modules, which is not possible with the current infrastructure.
I think it is easier to put the discussion here on how to address multiple MLIR modules execution, and outline the current points discussed. Ping @antiagainst, @MaheshRavishankar, @mehdi_amini and @ftynse for visibility.
Problem
After several passes, I have a nested module structure that I want to translate into LLVM IR and execute.
// main module
module {
...
module { ... } // nested module
...
}
Ideally, I want to link the main and the nested modules.
Current solution
The solution I have currently implemented adds an optional function reference parameter called llvmModuleBuilder
to JitRunnerMain()
, similar to mlirTransformer
. llvmModuleBuilder
is a custom function specified by the user (mlir-spirv-runner
in this case) that processes MLIR module and creates LLVM IR module in a specified way. In our case - translates each of the two modules to LLVM IR and linked them with LLVM’s Linker.
The clear drawback of this solution is that we need to pass llvmModuleBuilder
through the whole stack down to ExecutionEngine::create()
. There, we would call
auto llvmModule = llvmModuleBuilder ? llvmModuleBuilder(m, *ctx)
: translateModuleToLLVMIR(m, *ctx);
to get LLVM IR module either via our custom function, or if it is not specified by translateModuleToLLVMIR()
call.
This has some loose contract right now, so any suggestions are welcome.
Alternative
There is an alternative proposed in the discussion on the Phabricator:
translateModuleToLLVMIR()
can be modified to handle multiple modules. So instead of just taking a single ModuleOp
, it can take an ArrayRef<ModuleOp>
as arguments and then link them. This way we wouldn’t have to thread through the llvmModuleBuilder
callback through the entire stack. This would require ExecutionEngine::create()
to take an argument ArrayRef<ModuleOp>
instead of just ModuleOp
and an extra utility to handle module separation (can be provided by mlir-spirv-runner
or other user).
Any suggestions and thoughts are welcome!
Thanks,
George