//===- AMDGPUExportKernelRuntimeHandles.cpp - Lower enqueued block --------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // \file // // Give any globals used for OpenCL block enqueue runtime handles external // linkage so the runtime may access them. These should behave like internal // functions for purposes of linking, but need to have an external symbol in the // final object for the runtime to access them. // // TODO: This could be replaced with a new linkage type or global object // metadata that produces an external symbol in the final object, but allows // rename on IR linking. Alternatively if we can rely on // GlobalValue::getGlobalIdentifier we can just make these external symbols to // begin with. // //===----------------------------------------------------------------------===// #include "AMDGPUExportKernelRuntimeHandles.h" #include "AMDGPU.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" #define DEBUG_TYPE "amdgpu-export-kernel-runtime-handles" using namespace llvm; namespace { /// Lower enqueued blocks. class AMDGPUExportKernelRuntimeHandlesLegacy : public ModulePass { public: static char ID; explicit AMDGPUExportKernelRuntimeHandlesLegacy() : ModulePass(ID) {} private: bool runOnModule(Module &M) override; }; } // end anonymous namespace char AMDGPUExportKernelRuntimeHandlesLegacy::ID = 0; char &llvm::AMDGPUExportKernelRuntimeHandlesLegacyID = AMDGPUExportKernelRuntimeHandlesLegacy::ID; INITIALIZE_PASS(AMDGPUExportKernelRuntimeHandlesLegacy, DEBUG_TYPE, "Externalize enqueued block runtime handles", false, false) ModulePass *llvm::createAMDGPUExportKernelRuntimeHandlesLegacyPass() { return new AMDGPUExportKernelRuntimeHandlesLegacy(); } static bool exportKernelRuntimeHandles(Module &M) { bool Changed = false; const StringLiteral HandleSectionName(".amdgpu.kernel.runtime.handle"); for (GlobalVariable &GV : M.globals()) { if (GV.getSection() == HandleSectionName) { GV.setLinkage(GlobalValue::ExternalLinkage); GV.setDSOLocal(false); Changed = true; } } if (!Changed) return false; // FIXME: We shouldn't really need to export the kernel address. We can // initialize the runtime handle with the kernel descriptor. for (Function &F : M) { if (F.getCallingConv() != CallingConv::AMDGPU_KERNEL) continue; const MDNode *Associated = F.getMetadata(LLVMContext::MD_associated); if (!Associated) continue; auto *VM = cast(Associated->getOperand(0)); auto *Handle = dyn_cast(VM->getValue()); if (Handle && Handle->getSection() == HandleSectionName) { F.setLinkage(GlobalValue::ExternalLinkage); F.setVisibility(GlobalValue::ProtectedVisibility); } } return Changed; } bool AMDGPUExportKernelRuntimeHandlesLegacy::runOnModule(Module &M) { return exportKernelRuntimeHandles(M); } PreservedAnalyses AMDGPUExportKernelRuntimeHandlesPass::run(Module &M, ModuleAnalysisManager &MAM) { if (!exportKernelRuntimeHandles(M)) return PreservedAnalyses::all(); PreservedAnalyses PA; PA.preserveSet>(); return PA; }