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