Home | History | Annotate | Download | only in compiler
      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