blob: 9779cb6fcf6aeaa1fcdb81b39cba916b6c24d6b8 [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
alan-bakerbccf62c2019-03-29 10:32:41 -040015#include "llvm/ADT/SmallSet.h"
David Neto118188e2018-08-24 11:27:54 -040016#include "llvm/ADT/UniqueVector.h"
17#include "llvm/IR/Instructions.h"
18#include "llvm/IR/IRBuilder.h"
19#include "llvm/IR/Module.h"
20#include "llvm/Pass.h"
21#include "llvm/Support/raw_ostream.h"
22#include "llvm/Transforms/Utils/Cloning.h"
David Neto22f144c2017-06-12 14:26:21 -040023
24using namespace llvm;
25
26#define DEBUG_TYPE "inlinefuncwithpointerbitcastarg"
27
28namespace {
29struct InlineFuncWithPointerBitCastArgPass : public ModulePass {
30 static char ID;
31 InlineFuncWithPointerBitCastArgPass() : ModulePass(ID) {}
32
33 bool InlineFunctions(Module &M);
34 bool runOnModule(Module &M) override;
35};
36}
37
38char InlineFuncWithPointerBitCastArgPass::ID = 0;
39static RegisterPass<InlineFuncWithPointerBitCastArgPass>
40 X("InlineFuncWithPointerBitCastArg",
41 "Inline Function with Pointer Bitcast Argument Pass");
42
43namespace clspv {
44llvm::ModulePass *createInlineFuncWithPointerBitCastArgPass() {
45 return new InlineFuncWithPointerBitCastArgPass();
46}
47}
48
49bool InlineFuncWithPointerBitCastArgPass::runOnModule(Module &M) {
50 bool Changed = false;
51
52 // Loop through our inline pass until they stop changing thing.
53 for (bool localChanged = true; localChanged; Changed |= localChanged) {
54 localChanged = false;
55
56 localChanged |= InlineFunctions(M);
57 }
58
59 return Changed;
60}
61
62bool InlineFuncWithPointerBitCastArgPass::InlineFunctions(Module &M) {
63 bool Changed = false;
64
65 UniqueVector<CallInst *> WorkList;
66 for (Function &F : M) {
67 for (BasicBlock &BB : F) {
68 for (Instruction &I : BB) {
69 // If we have a bitcast instruction...
70 if (auto Bitcast = dyn_cast<BitCastInst>(&I)) {
71 // ... which is a pointer bitcast...
72 if (Bitcast->getType()->isPointerTy()) {
73 // ... we need to recursively check all the users to find any call
74 // instructions.
75 SmallVector<Value *, 8> ToChecks(Bitcast->user_begin(),
76 Bitcast->user_end());
77 SmallSet<Instruction *, 8> CheckedPhis;
78
79 while (!ToChecks.empty()) {
80 auto ToCheck = ToChecks.back();
81 ToChecks.pop_back();
82
83 if (auto Inst = dyn_cast<Instruction>(ToCheck)) {
84 switch (Inst->getOpcode()) {
85 default:
86 break;
87 case Instruction::Call:
88 // We found a call instruction which needs to be inlined!
89 WorkList.insert(cast<CallInst>(Inst));
90 case Instruction::PHI:
91 // If we previously checked this phi...
92 if (0 < CheckedPhis.count(Inst)) {
93 // ... then we don't need to check it again!
94 break;
95 }
96
97 CheckedPhis.insert(Inst);
98 case Instruction::GetElementPtr:
99 case Instruction::BitCast:
100 // These pointer users could have a call user, and so we
101 // must check them also.
102 ToChecks.append(Inst->user_begin(), Inst->user_end());
103 }
104 }
105 }
106 }
107 }
108 }
109 }
110 }
111
112 // TODO: Need to check pointer bitcast, stored to an alloca, then loaded,
113 // then passed into a function?
114
115 for (CallInst *Call : WorkList) {
116 InlineFunctionInfo IFI;
117 CallSite CS(Call);
118 // Disable generation of lifetime intrinsic.
119 Changed |= InlineFunction(CS, IFI, nullptr, false);
120 }
121
122 return Changed;
123}