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 | |
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 | |
56 | ModulePass *llvm::createAMDGPUExportKernelRuntimeHandlesLegacyPass() { |
57 | return new AMDGPUExportKernelRuntimeHandlesLegacy(); |
58 | } |
59 | |
60 | static 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(KindID: LLVMContext::MD_associated); |
83 | if (!Associated) |
84 | continue; |
85 | |
86 | auto *VM = cast<ValueAsMetadata>(Val: Associated->getOperand(I: 0)); |
87 | auto *Handle = dyn_cast<GlobalObject>(Val: 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 | |
97 | bool AMDGPUExportKernelRuntimeHandlesLegacy::runOnModule(Module &M) { |
98 | return exportKernelRuntimeHandles(M); |
99 | } |
100 | |
101 | PreservedAnalyses |
102 | AMDGPUExportKernelRuntimeHandlesPass::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 |