diff --git a/mlir/lib/Dialect/GPU/Transforms/SerializeToCubin.cpp b/mlir/lib/Dialect/GPU/Transforms/SerializeToCubin.cpp --- a/mlir/lib/Dialect/GPU/Transforms/SerializeToCubin.cpp +++ b/mlir/lib/Dialect/GPU/Transforms/SerializeToCubin.cpp @@ -19,6 +19,7 @@ #include "mlir/Target/LLVMIR/Dialect/NVVM/NVVMToLLVMIRTranslation.h" #include "mlir/Target/LLVMIR/Export.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/Threading.h" #include @@ -46,6 +47,8 @@ namespace { class SerializeToCubinPass : public PassWrapper { + static llvm::once_flag initializeBackendOnce; + public: MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SerializeToCubinPass) @@ -73,9 +76,21 @@ option = value.str(); } +llvm::once_flag SerializeToCubinPass::initializeBackendOnce; + SerializeToCubinPass::SerializeToCubinPass(StringRef triple, StringRef chip, StringRef features, int optLevel, bool dumpPtx) { + // No matter how this pass is constructed, ensure that the NVPTX backend + // is initialized exactly once. + llvm::call_once(initializeBackendOnce, []() { + // Initialize LLVM NVPTX backend. + LLVMInitializeNVPTXTarget(); + LLVMInitializeNVPTXTargetInfo(); + LLVMInitializeNVPTXTargetMC(); + LLVMInitializeNVPTXAsmPrinter(); + }); + maybeSetOption(this->triple, triple); maybeSetOption(this->chip, chip); maybeSetOption(this->features, features); @@ -144,15 +159,8 @@ // Register pass to serialize GPU kernel functions to a CUBIN binary annotation. void mlir::registerGpuSerializeToCubinPass() { - PassRegistration registerSerializeToCubin([] { - // Initialize LLVM NVPTX backend. - LLVMInitializeNVPTXTarget(); - LLVMInitializeNVPTXTargetInfo(); - LLVMInitializeNVPTXTargetMC(); - LLVMInitializeNVPTXAsmPrinter(); - - return std::make_unique(); - }); + PassRegistration registerSerializeToCubin( + [] { return std::make_unique(); }); } std::unique_ptr mlir::createGpuSerializeToCubinPass(StringRef triple, diff --git a/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp b/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp --- a/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp +++ b/mlir/lib/Dialect/GPU/Transforms/SerializeToHsaco.cpp @@ -47,6 +47,7 @@ #include "llvm/Support/Program.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/Threading.h" #include "llvm/Support/WithColor.h" #include "llvm/Target/TargetMachine.h" @@ -54,7 +55,6 @@ #include "llvm/Transforms/IPO/Internalize.h" -#include #include using namespace mlir; @@ -62,6 +62,8 @@ namespace { class SerializeToHsacoPass : public PassWrapper { + static llvm::once_flag initializeBackendOnce; + public: MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SerializeToHsacoPass) @@ -122,8 +124,20 @@ option = getValue(); } +llvm::once_flag SerializeToHsacoPass::initializeBackendOnce; + SerializeToHsacoPass::SerializeToHsacoPass(StringRef triple, StringRef arch, StringRef features, int optLevel) { + // No matter how this pass is constructed, ensure that the AMDGPU backend + // is initialized exactly once. + llvm::call_once(initializeBackendOnce, []() { + // Initialize LLVM AMDGPU backend. + LLVMInitializeAMDGPUAsmParser(); + LLVMInitializeAMDGPUAsmPrinter(); + LLVMInitializeAMDGPUTarget(); + LLVMInitializeAMDGPUTargetInfo(); + LLVMInitializeAMDGPUTargetMC(); + }); maybeSetOption(this->triple, [&triple] { return triple.str(); }); maybeSetOption(this->chip, [&arch] { return arch.str(); }); maybeSetOption(this->features, [&features] { return features.str(); }); @@ -437,13 +451,6 @@ // Register pass to serialize GPU kernel functions to a HSACO binary annotation. void mlir::registerGpuSerializeToHsacoPass() { PassRegistration registerSerializeToHSACO([] { - // Initialize LLVM AMDGPU backend. - LLVMInitializeAMDGPUAsmParser(); - LLVMInitializeAMDGPUAsmPrinter(); - LLVMInitializeAMDGPUTarget(); - LLVMInitializeAMDGPUTargetInfo(); - LLVMInitializeAMDGPUTargetMC(); - return std::make_unique("amdgcn-amd-amdhsa", "", "", 2); });