1 //===- SerializeToBlob.cpp - MLIR GPU lowering pass -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements a base class for a pass to serialize a gpu module 10 // into a binary blob that can be executed on a GPU. The binary blob is added 11 // as a string attribute to the gpu module. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "mlir/Dialect/GPU/Passes.h" 16 #include "mlir/Pass/Pass.h" 17 #include "llvm/IR/LegacyPassManager.h" 18 #include "llvm/Support/TargetRegistry.h" 19 #include "llvm/Support/TargetSelect.h" 20 #include "llvm/Target/TargetMachine.h" 21 22 using namespace mlir; 23 24 std::string gpu::getDefaultGpuBinaryAnnotation() { return "gpu.binary"; } 25 26 gpu::SerializeToBlobPass::SerializeToBlobPass(TypeID passID) 27 : OperationPass<gpu::GPUModuleOp>(passID) {} 28 29 gpu::SerializeToBlobPass::SerializeToBlobPass(const SerializeToBlobPass &other) 30 : OperationPass<gpu::GPUModuleOp>(other) {} 31 32 static std::string translateToISA(llvm::Module &llvmModule, 33 llvm::TargetMachine &targetMachine) { 34 llvmModule.setDataLayout(targetMachine.createDataLayout()); 35 36 std::string targetISA; 37 llvm::raw_string_ostream stream(targetISA); 38 llvm::buffer_ostream pstream(stream); 39 llvm::legacy::PassManager codegenPasses; 40 targetMachine.addPassesToEmitFile(codegenPasses, pstream, nullptr, 41 llvm::CGFT_AssemblyFile); 42 codegenPasses.run(llvmModule); 43 return targetISA; 44 } 45 46 void gpu::SerializeToBlobPass::runOnOperation() { 47 // Lower the module to an LLVM IR module using a separate context to enable 48 // multi-threaded processing. 49 llvm::LLVMContext llvmContext; 50 std::unique_ptr<llvm::Module> llvmModule = translateToLLVMIR(llvmContext); 51 if (!llvmModule) 52 return signalPassFailure(); 53 54 // Lower the LLVM IR module to target ISA. 55 std::unique_ptr<llvm::TargetMachine> targetMachine = createTargetMachine(); 56 if (!targetMachine) 57 return signalPassFailure(); 58 59 std::string targetISA = translateToISA(*llvmModule, *targetMachine); 60 61 // Serialize the target ISA. 62 std::unique_ptr<std::vector<char>> blob = serializeISA(targetISA); 63 if (!blob) 64 return signalPassFailure(); 65 66 // Add the blob as module attribute. 67 auto attr = StringAttr::get(&getContext(), {blob->data(), blob->size()}); 68 getOperation()->setAttr(gpuBinaryAnnotation, attr); 69 } 70 71 std::unique_ptr<llvm::TargetMachine> 72 gpu::SerializeToBlobPass::createTargetMachine() { 73 Location loc = getOperation().getLoc(); 74 std::string error; 75 const llvm::Target *target = 76 llvm::TargetRegistry::lookupTarget(triple, error); 77 if (!target) { 78 emitError(loc, Twine("failed to lookup target: ") + error); 79 return {}; 80 } 81 llvm::TargetMachine *machine = 82 target->createTargetMachine(triple, chip, features, {}, {}); 83 if (!machine) { 84 emitError(loc, "failed to create target machine"); 85 return {}; 86 } 87 88 return std::unique_ptr<llvm::TargetMachine>{machine}; 89 } 90