From 0424b5115cffad73a0f6e68affed603a7ed9a692 Mon Sep 17 00:00:00 2001 From: "Yaxun (Sam) Liu" Date: Fri, 8 Apr 2022 23:56:07 -0400 Subject: [CUDA][HIP] Fix host used external kernel in archive For -fgpu-rdc, a host function may call an external kernel which is defined in an archive of bitcode. Since this external kernel is only referenced in host function, the device bitcode does not contain reference to this external kernel, then the linker will not try to resolve this external kernel in the archive. To fix this issue, host-used external kernels and device variables are tracked. A global array containing pointers to these external kernels and variables is emitted which serves as an artificial references to the external kernels and variables used by host. Reviewed by: Artem Belevich Differential Revision: https://reviews.llvm.org/D123441 --- clang/lib/CodeGen/CodeGenModule.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'clang/lib/CodeGen/CodeGenModule.cpp') diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index b251a4a7df3d..76094c73a927 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -579,6 +579,30 @@ void CodeGenModule::Release() { } } + // Emit a global array containing all external kernels or device variables + // used by host functions and mark it as used for CUDA/HIP. This is necessary + // to get kernels or device variables in archives linked in even if these + // kernels or device variables are only used in host functions. + if (!Context.CUDAExternalDeviceDeclODRUsedByHost.empty()) { + SmallVector UsedArray; + for (auto D : Context.CUDAExternalDeviceDeclODRUsedByHost) { + GlobalDecl GD; + if (auto *FD = dyn_cast(D)) + GD = GlobalDecl(FD, KernelReferenceKind::Kernel); + else + GD = GlobalDecl(D); + UsedArray.push_back(llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast( + GetAddrOfGlobal(GD), Int8PtrTy)); + } + + llvm::ArrayType *ATy = llvm::ArrayType::get(Int8PtrTy, UsedArray.size()); + + auto *GV = new llvm::GlobalVariable( + getModule(), ATy, false, llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(ATy, UsedArray), "gpu.used.external"); + addCompilerUsedGlobal(GV); + } + emitLLVMUsed(); if (SanStats) SanStats->finish(); -- cgit v1.2.3