1 /*
2 * Copyright 2017, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "GlobalAllocPass.h"
18
19 #include "Context.h"
20 #include "RSAllocationUtils.h"
21
22 #include "llvm/IR/GlobalVariable.h"
23 #include "llvm/IR/Module.h"
24 #include "llvm/Pass.h"
25 #include "llvm/Support/Debug.h"
26
27 #define DEBUG_TYPE "rs2spirv-global-alloc"
28
29 using namespace llvm;
30
31 namespace rs2spirv {
32
33 namespace {
collectGlobalAllocs(Module & M,SmallVectorImpl<GlobalVariable * > & GlobalAllocs)34 bool collectGlobalAllocs(Module &M,
35 SmallVectorImpl<GlobalVariable *> &GlobalAllocs) {
36 for (auto &GV : M.globals()) {
37 if (!isRSAllocation(GV))
38 continue;
39
40 DEBUG(GV.dump());
41 GlobalAllocs.push_back(&GV);
42 }
43
44 return !GlobalAllocs.empty();
45 }
46
47 //
48 // This pass would enumerate used global rs_allocations (TBD) and
49 // lowers calls to accessors of the following type:
50 //
51 // rsGetAllocationDimX(g)
52 //
53 // to
54 //
55 // __rsov_rsGetAllocationDimX(some uninque constant identifying g) */
56 //
57 // Note the __rsov_* variant is used as a marker for another SPIRIT
58 // transformations (see GlobalAllocSPIRITPass.cpp) to expand them into
59 // SPIR-V instructions that loads the metadata.
60 //
61 class GlobalAllocPass : public ModulePass {
62 public:
63 static char ID;
GlobalAllocPass()64 GlobalAllocPass()
65 : ModulePass(ID), Allocs(Context::getInstance().getGlobalAllocs()) {}
66
getPassName() const67 const char *getPassName() const override { return "GlobalAllocPass"; }
68
runOnModule(Module & M)69 bool runOnModule(Module &M) override {
70 DEBUG(dbgs() << "RS2SPIRVGlobalAllocPass\n");
71 DEBUG(M.dump());
72
73 SmallVector<GlobalVariable *, 8> GlobalAllocs;
74 const bool CollectRes = collectGlobalAllocs(M, GlobalAllocs);
75 if (!CollectRes)
76 return false; // Module not modified.
77
78 SmallVector<RSAllocationCallInfo, 8> Calls;
79 getRSAllocationInfo(M, Allocs);
80 getRSAllocAccesses(Allocs, Calls);
81
82 // Lower the found accessors
83 for (auto &C : Calls) {
84 assert(C.Kind == RSAllocAccessKind::DIMX &&
85 "Unsupported type of accessor call types");
86 solidifyRSAllocAccess(M, C);
87 }
88 // Return true, as the pass modifies module.
89 DEBUG(dbgs() << "RS2SPIRVGlobalAllocPass end\n");
90 return true;
91 }
92
93 private:
94 SmallVectorImpl<RSAllocationInfo> &Allocs;
95 };
96
97 // A simple pass to remove all global allocations forcibly
98 class RemoveAllGlobalAllocPass : public ModulePass {
99 public:
100 static char ID;
RemoveAllGlobalAllocPass()101 RemoveAllGlobalAllocPass() : ModulePass(ID) {}
getPassName() const102 const char *getPassName() const override {
103 return "RemoveAllGlobalAllocPass";
104 }
105
runOnModule(Module & M)106 bool runOnModule(Module &M) override {
107 DEBUG(dbgs() << "RemoveAllGlobalAllocPass\n");
108 DEBUG(M.dump());
109
110 SmallVector<GlobalVariable *, 8> GlobalAllocs;
111 const bool CollectRes = collectGlobalAllocs(M, GlobalAllocs);
112 if (!CollectRes)
113 return false; // Module not modified.
114 // Remove global allocations
115 for (auto *G : GlobalAllocs) {
116 G->eraseFromParent();
117 }
118 DEBUG(dbgs() << "RemoveAllGlobalAllocPass end\n");
119 DEBUG(M.dump());
120 // Return true, as the pass modifies module.
121 return true;
122 }
123 };
124
125 } // namespace
126 char GlobalAllocPass::ID = 0;
127 char RemoveAllGlobalAllocPass::ID = 0;
128
createRemoveAllGlobalAllocPass()129 ModulePass *createRemoveAllGlobalAllocPass() {
130 return new RemoveAllGlobalAllocPass();
131 }
createGlobalAllocPass()132 ModulePass *createGlobalAllocPass() { return new GlobalAllocPass(); }
133
134 } // namespace rs2spirv
135