blob: 9d0a6d63ed59e38e8be58df8773109ca488a5734 [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));
Marco Antognini7e338402021-03-15 12:48:37 +000093 // Fall-through
David Neto22f144c2017-06-12 14:26:21 -040094 case Instruction::PHI:
95 // If we previously checked this phi...
96 if (0 < CheckedPhis.count(Inst)) {
97 // ... then we don't need to check it again!
98 break;
99 }
100
101 CheckedPhis.insert(Inst);
Marco Antognini7e338402021-03-15 12:48:37 +0000102 // Fall-through
David Neto22f144c2017-06-12 14:26:21 -0400103 case Instruction::GetElementPtr:
104 case Instruction::BitCast:
105 // These pointer users could have a call user, and so we
106 // must check them also.
107 ToChecks.append(Inst->user_begin(), Inst->user_end());
108 }
109 }
110 }
111 }
112 }
113 }
114 }
115 }
116
117 // TODO: Need to check pointer bitcast, stored to an alloca, then loaded,
118 // then passed into a function?
119
120 for (CallInst *Call : WorkList) {
121 InlineFunctionInfo IFI;
David Neto22f144c2017-06-12 14:26:21 -0400122 // Disable generation of lifetime intrinsic.
alan-baker741fd1f2020-04-14 17:38:15 -0400123 Changed |= InlineFunction(*Call, IFI, nullptr, false).isSuccess();
David Neto22f144c2017-06-12 14:26:21 -0400124 }
125
126 return Changed;
127}