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 "RemoveNonkernelsPass.h"
18 
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/Module.h"
21 #include "llvm/Pass.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
24 
25 #include "Context.h"
26 
27 #define DEBUG_TYPE "rs2spirv-remove"
28 
29 using namespace llvm;
30 
31 namespace rs2spirv {
32 
33 namespace {
34 
35 class RemoveNonkernelsPass : public ModulePass {
36 public:
37   static char ID;
RemoveNonkernelsPass()38   explicit RemoveNonkernelsPass() : ModulePass(ID) {}
39 
getPassName() const40   const char *getPassName() const override { return "RemoveNonkernelsPass"; }
41 
runOnModule(Module & M)42   bool runOnModule(Module &M) override {
43     DEBUG(dbgs() << "RemoveNonkernelsPass\n");
44     DEBUG(M.dump());
45 
46     rs2spirv::Context &Ctxt = rs2spirv::Context::getInstance();
47 
48     if (Ctxt.getNumForEachKernel() == 0) {
49       DEBUG(dbgs() << "RemoveNonkernelsPass detected no kernel\n");
50       // Returns false, since no modification is made to the Module.
51       return false;
52     }
53 
54     std::vector<Function *> Functions;
55     for (auto &F : M.functions()) {
56       Functions.push_back(&F);
57     }
58 
59     for (auto &F : Functions) {
60       if (F->isDeclaration())
61         continue;
62 
63       if (Ctxt.isForEachKernel(F->getName())) {
64         continue; // Skip kernels.
65       }
66 
67       F->replaceAllUsesWith(UndefValue::get((Type *)F->getType()));
68       F->eraseFromParent();
69 
70       DEBUG(dbgs() << "Removed:\t" << F->getName() << '\n');
71     }
72 
73     DEBUG(M.dump());
74     DEBUG(dbgs() << "Done removal\n");
75 
76     // Returns true, because the pass modifies the Module.
77     return true;
78   }
79 };
80 
81 } // namespace
82 
83 char RemoveNonkernelsPass::ID = 0;
84 
createRemoveNonkernelsPass()85 ModulePass *createRemoveNonkernelsPass() {
86   return new RemoveNonkernelsPass();
87 }
88 
89 } // namespace rs2spirv
90