| /* |
| * Copyright 2017, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "GlobalAllocPass.h" |
| |
| #include "Context.h" |
| #include "RSAllocationUtils.h" |
| |
| #include "llvm/IR/GlobalVariable.h" |
| #include "llvm/IR/Module.h" |
| #include "llvm/Pass.h" |
| #include "llvm/Support/Debug.h" |
| |
| #define DEBUG_TYPE "rs2spirv-global-alloc" |
| |
| using namespace llvm; |
| |
| namespace rs2spirv { |
| |
| namespace { |
| bool collectGlobalAllocs(Module &M, |
| SmallVectorImpl<GlobalVariable *> &GlobalAllocs) { |
| for (auto &GV : M.globals()) { |
| if (!isRSAllocation(GV)) |
| continue; |
| |
| DEBUG(GV.dump()); |
| GlobalAllocs.push_back(&GV); |
| } |
| |
| return !GlobalAllocs.empty(); |
| } |
| |
| // |
| // This pass would enumerate used global rs_allocations (TBD) and |
| // lowers calls to accessors of the following type: |
| // |
| // rsGetAllocationDimX(g) |
| // |
| // to |
| // |
| // __rsov_rsGetAllocationDimX(some uninque constant identifying g) */ |
| // |
| // Note the __rsov_* variant is used as a marker for another SPIRIT |
| // transformations (see GlobalAllocSPIRITPass.cpp) to expand them into |
| // SPIR-V instructions that loads the metadata. |
| // |
| class GlobalAllocPass : public ModulePass { |
| public: |
| static char ID; |
| GlobalAllocPass() |
| : ModulePass(ID), Allocs(Context::getInstance().getGlobalAllocs()) {} |
| |
| const char *getPassName() const override { return "GlobalAllocPass"; } |
| |
| bool runOnModule(Module &M) override { |
| DEBUG(dbgs() << "RS2SPIRVGlobalAllocPass\n"); |
| DEBUG(M.dump()); |
| |
| SmallVector<GlobalVariable *, 8> GlobalAllocs; |
| const bool CollectRes = collectGlobalAllocs(M, GlobalAllocs); |
| if (!CollectRes) |
| return false; // Module not modified. |
| |
| SmallVector<RSAllocationCallInfo, 8> Calls; |
| getRSAllocationInfo(M, Allocs); |
| getRSAllocAccesses(Allocs, Calls); |
| |
| // Lower the found accessors |
| for (auto &C : Calls) { |
| assert(C.Kind == RSAllocAccessKind::DIMX && |
| "Unsupported type of accessor call types"); |
| solidifyRSAllocAccess(M, C); |
| } |
| // Return true, as the pass modifies module. |
| DEBUG(dbgs() << "RS2SPIRVGlobalAllocPass end\n"); |
| return true; |
| } |
| |
| private: |
| SmallVectorImpl<RSAllocationInfo> &Allocs; |
| }; |
| |
| // A simple pass to remove all global allocations forcibly |
| class RemoveAllGlobalAllocPass : public ModulePass { |
| public: |
| static char ID; |
| RemoveAllGlobalAllocPass() : ModulePass(ID) {} |
| const char *getPassName() const override { |
| return "RemoveAllGlobalAllocPass"; |
| } |
| |
| bool runOnModule(Module &M) override { |
| DEBUG(dbgs() << "RemoveAllGlobalAllocPass\n"); |
| DEBUG(M.dump()); |
| |
| SmallVector<GlobalVariable *, 8> GlobalAllocs; |
| const bool CollectRes = collectGlobalAllocs(M, GlobalAllocs); |
| if (!CollectRes) |
| return false; // Module not modified. |
| // Remove global allocations |
| for (auto *G : GlobalAllocs) { |
| G->eraseFromParent(); |
| } |
| DEBUG(dbgs() << "RemoveAllGlobalAllocPass end\n"); |
| DEBUG(M.dump()); |
| // Return true, as the pass modifies module. |
| return true; |
| } |
| }; |
| |
| } // namespace |
| char GlobalAllocPass::ID = 0; |
| char RemoveAllGlobalAllocPass::ID = 0; |
| |
| ModulePass *createRemoveAllGlobalAllocPass() { |
| return new RemoveAllGlobalAllocPass(); |
| } |
| ModulePass *createGlobalAllocPass() { return new GlobalAllocPass(); } |
| |
| } // namespace rs2spirv |