blob: f12858ceb083ceb175cb080102cababe68110cd7 [file] [log] [blame]
David Neto22f144c2017-06-12 14:26:21 -04001// Copyright 2017 The Clspv Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
David Neto118188e2018-08-24 11:27:54 -040015#include "llvm/ADT/UniqueVector.h"
16#include "llvm/IR/Instructions.h"
17#include "llvm/IR/IRBuilder.h"
18#include "llvm/IR/Module.h"
19#include "llvm/Pass.h"
20#include "llvm/Support/raw_ostream.h"
21#include "llvm/Transforms/Utils/Cloning.h"
David Neto22f144c2017-06-12 14:26:21 -040022
23using namespace llvm;
24
25#define DEBUG_TYPE "inlinefuncwithpointerbitcastarg"
26
27namespace {
28struct InlineFuncWithPointerBitCastArgPass : public ModulePass {
29 static char ID;
30 InlineFuncWithPointerBitCastArgPass() : ModulePass(ID) {}
31
32 bool InlineFunctions(Module &M);
33 bool runOnModule(Module &M) override;
34};
35}
36
37char InlineFuncWithPointerBitCastArgPass::ID = 0;
38static RegisterPass<InlineFuncWithPointerBitCastArgPass>
39 X("InlineFuncWithPointerBitCastArg",
40 "Inline Function with Pointer Bitcast Argument Pass");
41
42namespace clspv {
43llvm::ModulePass *createInlineFuncWithPointerBitCastArgPass() {
44 return new InlineFuncWithPointerBitCastArgPass();
45}
46}
47
48bool InlineFuncWithPointerBitCastArgPass::runOnModule(Module &M) {
49 bool Changed = false;
50
51 // Loop through our inline pass until they stop changing thing.
52 for (bool localChanged = true; localChanged; Changed |= localChanged) {
53 localChanged = false;
54
55 localChanged |= InlineFunctions(M);
56 }
57
58 return Changed;
59}
60
61bool InlineFuncWithPointerBitCastArgPass::InlineFunctions(Module &M) {
62 bool Changed = false;
63
64 UniqueVector<CallInst *> WorkList;
65 for (Function &F : M) {
66 for (BasicBlock &BB : F) {
67 for (Instruction &I : BB) {
68 // If we have a bitcast instruction...
69 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
70 // ... which is a pointer bitcast...
71 if (Bitcast->getType()->isPointerTy()) {
72 // ... we need to recursively check all the users to find any call
73 // instructions.
74 SmallVector<Value *, 8> ToChecks(Bitcast->user_begin(),
75 Bitcast->user_end());
76 SmallSet<Instruction *, 8> CheckedPhis;
77
78 while (!ToChecks.empty()) {
79 auto ToCheck = ToChecks.back();
80 ToChecks.pop_back();
81
82 if (auto Inst = dyn_cast<Instruction>(ToCheck)) {
83 switch (Inst->getOpcode()) {
84 default:
85 break;
86 case Instruction::Call:
87 // We found a call instruction which needs to be inlined!
88 WorkList.insert(cast<CallInst>(Inst));
89 case Instruction::PHI:
90 // If we previously checked this phi...
91 if (0 < CheckedPhis.count(Inst)) {
92 // ... then we don't need to check it again!
93 break;
94 }
95
96 CheckedPhis.insert(Inst);
97 case Instruction::GetElementPtr:
98 case Instruction::BitCast:
99 // These pointer users could have a call user, and so we
100 // must check them also.
101 ToChecks.append(Inst->user_begin(), Inst->user_end());
102 }
103 }
104 }
105 }
106 }
107 }
108 }
109 }
110
111 // TODO: Need to check pointer bitcast, stored to an alloca, then loaded,
112 // then passed into a function?
113
114 for (CallInst *Call : WorkList) {
115 InlineFunctionInfo IFI;
116 CallSite CS(Call);
117 // Disable generation of lifetime intrinsic.
118 Changed |= InlineFunction(CS, IFI, nullptr, false);
119 }
120
121 return Changed;
122}