1 //===- AMDGPUExportKernelRuntimeHandles.cpp - Lower enqueued block --------===// 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 // \file 10 // 11 // Give any globals used for OpenCL block enqueue runtime handles external 12 // linkage so the runtime may access them. These should behave like internal 13 // functions for purposes of linking, but need to have an external symbol in the 14 // final object for the runtime to access them. 15 // 16 // TODO: This could be replaced with a new linkage type or global object 17 // metadata that produces an external symbol in the final object, but allows 18 // rename on IR linking. Alternatively if we can rely on 19 // GlobalValue::getGlobalIdentifier we can just make these external symbols to 20 // begin with. 21 // 22 //===----------------------------------------------------------------------===// 23 24 #include "AMDGPUExportKernelRuntimeHandles.h" 25 #include "AMDGPU.h" 26 #include "llvm/IR/Module.h" 27 #include "llvm/Pass.h" 28 29 #define DEBUG_TYPE "amdgpu-export-kernel-runtime-handles" 30 31 using namespace llvm; 32 33 namespace { 34 35 /// Lower enqueued blocks. 36 class AMDGPUExportKernelRuntimeHandlesLegacy : public ModulePass { 37 public: 38 static char ID; 39 AMDGPUExportKernelRuntimeHandlesLegacy()40 explicit AMDGPUExportKernelRuntimeHandlesLegacy() : ModulePass(ID) {} 41 42 private: 43 bool runOnModule(Module &M) override; 44 }; 45 46 } // end anonymous namespace 47 48 char AMDGPUExportKernelRuntimeHandlesLegacy::ID = 0; 49 50 char &llvm::AMDGPUExportKernelRuntimeHandlesLegacyID = 51 AMDGPUExportKernelRuntimeHandlesLegacy::ID; 52 53 INITIALIZE_PASS(AMDGPUExportKernelRuntimeHandlesLegacy, DEBUG_TYPE, 54 "Externalize enqueued block runtime handles", false, false) 55 createAMDGPUExportKernelRuntimeHandlesLegacyPass()56ModulePass *llvm::createAMDGPUExportKernelRuntimeHandlesLegacyPass() { 57 return new AMDGPUExportKernelRuntimeHandlesLegacy(); 58 } 59 exportKernelRuntimeHandles(Module & M)60static bool exportKernelRuntimeHandles(Module &M) { 61 bool Changed = false; 62 63 const StringLiteral HandleSectionName(".amdgpu.kernel.runtime.handle"); 64 65 for (GlobalVariable &GV : M.globals()) { 66 if (GV.getSection() == HandleSectionName) { 67 GV.setLinkage(GlobalValue::ExternalLinkage); 68 GV.setDSOLocal(false); 69 Changed = true; 70 } 71 } 72 73 if (!Changed) 74 return false; 75 76 // FIXME: We shouldn't really need to export the kernel address. We can 77 // initialize the runtime handle with the kernel descriptor. 78 for (Function &F : M) { 79 if (F.getCallingConv() != CallingConv::AMDGPU_KERNEL) 80 continue; 81 82 const MDNode *Associated = F.getMetadata(LLVMContext::MD_associated); 83 if (!Associated) 84 continue; 85 86 auto *VM = cast<ValueAsMetadata>(Associated->getOperand(0)); 87 auto *Handle = dyn_cast<GlobalObject>(VM->getValue()); 88 if (Handle && Handle->getSection() == HandleSectionName) { 89 F.setLinkage(GlobalValue::ExternalLinkage); 90 F.setVisibility(GlobalValue::ProtectedVisibility); 91 } 92 } 93 94 return Changed; 95 } 96 runOnModule(Module & M)97bool AMDGPUExportKernelRuntimeHandlesLegacy::runOnModule(Module &M) { 98 return exportKernelRuntimeHandles(M); 99 } 100 101 PreservedAnalyses run(Module & M,ModuleAnalysisManager & MAM)102AMDGPUExportKernelRuntimeHandlesPass::run(Module &M, 103 ModuleAnalysisManager &MAM) { 104 if (!exportKernelRuntimeHandles(M)) 105 return PreservedAnalyses::all(); 106 107 PreservedAnalyses PA; 108 PA.preserveSet<AllAnalysesOn<Function>>(); 109 return PA; 110 } 111