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 { 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; 64 GlobalAllocPass() 65 : ModulePass(ID), Allocs(Context::getInstance().getGlobalAllocs()) {} 66 67 const char *getPassName() const override { return "GlobalAllocPass"; } 68 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; 101 RemoveAllGlobalAllocPass() : ModulePass(ID) {} 102 const char *getPassName() const override { 103 return "RemoveAllGlobalAllocPass"; 104 } 105 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 129 ModulePass *createRemoveAllGlobalAllocPass() { 130 return new RemoveAllGlobalAllocPass(); 131 } 132 ModulePass *createGlobalAllocPass() { return new GlobalAllocPass(); } 133 134 } // namespace rs2spirv 135