blob: b602cf4fb5800f2f04375be9104e0b2661120391 [file] [log] [blame]
Owen Anderson2f82e272009-06-14 08:26:32 +00001//===- PartialInlining.cpp - Inline parts of functions --------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass performs partial inlining, typically by inlining an if statement
11// that surrounds the body of the function.
12//
13//===----------------------------------------------------------------------===//
14
Owen Anderson2f82e272009-06-14 08:26:32 +000015#include "llvm/Transforms/IPO.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/ADT/Statistic.h"
Chandler Carruth1305dc32014-03-04 11:45:46 +000017#include "llvm/IR/CFG.h"
Chandler Carruth5ad5f152014-01-13 09:26:24 +000018#include "llvm/IR/Dominators.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000019#include "llvm/IR/Instructions.h"
20#include "llvm/IR/Module.h"
Owen Anderson2f82e272009-06-14 08:26:32 +000021#include "llvm/Pass.h"
Owen Anderson2f82e272009-06-14 08:26:32 +000022#include "llvm/Transforms/Utils/Cloning.h"
Chandler Carruth0fde0012012-05-04 10:18:49 +000023#include "llvm/Transforms/Utils/CodeExtractor.h"
Owen Anderson2f82e272009-06-14 08:26:32 +000024using namespace llvm;
25
Chandler Carruth964daaa2014-04-22 02:55:47 +000026#define DEBUG_TYPE "partialinlining"
27
Owen Andersonbd6a2132009-06-15 20:50:26 +000028STATISTIC(NumPartialInlined, "Number of functions partially inlined");
29
Owen Anderson2f82e272009-06-14 08:26:32 +000030namespace {
Nick Lewycky02d5f772009-10-25 06:33:48 +000031 struct PartialInliner : public ModulePass {
Craig Topper3e4c6972014-03-05 09:10:37 +000032 void getAnalysisUsage(AnalysisUsage &AU) const override { }
Owen Anderson2f82e272009-06-14 08:26:32 +000033 static char ID; // Pass identification, replacement for typeid
Owen Anderson6c18d1a2010-10-19 17:21:58 +000034 PartialInliner() : ModulePass(ID) {
35 initializePartialInlinerPass(*PassRegistry::getPassRegistry());
36 }
Craig Topper3e4c6972014-03-05 09:10:37 +000037
38 bool runOnModule(Module& M) override;
39
Owen Anderson2f82e272009-06-14 08:26:32 +000040 private:
41 Function* unswitchFunction(Function* F);
42 };
Alexander Kornienkof00654e2015-06-23 09:49:53 +000043}
Owen Anderson2f82e272009-06-14 08:26:32 +000044
45char PartialInliner::ID = 0;
Owen Andersona57b97e2010-07-21 22:09:45 +000046INITIALIZE_PASS(PartialInliner, "partial-inliner",
Owen Andersondf7a4f22010-10-07 22:25:06 +000047 "Partial Inliner", false, false)
Owen Anderson2f82e272009-06-14 08:26:32 +000048
49ModulePass* llvm::createPartialInliningPass() { return new PartialInliner(); }
50
51Function* PartialInliner::unswitchFunction(Function* F) {
52 // First, verify that this function is an unswitching candidate...
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +000053 BasicBlock *entryBlock = &F->front();
Owen Andersonf0081db2009-09-08 19:53:15 +000054 BranchInst *BR = dyn_cast<BranchInst>(entryBlock->getTerminator());
55 if (!BR || BR->isUnconditional())
Craig Topperf40110f2014-04-25 05:29:35 +000056 return nullptr;
Owen Anderson2f82e272009-06-14 08:26:32 +000057
Craig Topperf40110f2014-04-25 05:29:35 +000058 BasicBlock* returnBlock = nullptr;
59 BasicBlock* nonReturnBlock = nullptr;
Owen Anderson2f82e272009-06-14 08:26:32 +000060 unsigned returnCount = 0;
Reid Klecknerc26a17a2015-02-04 19:14:57 +000061 for (BasicBlock *BB : successors(entryBlock)) {
62 if (isa<ReturnInst>(BB->getTerminator())) {
63 returnBlock = BB;
Owen Anderson2f82e272009-06-14 08:26:32 +000064 returnCount++;
65 } else
Reid Klecknerc26a17a2015-02-04 19:14:57 +000066 nonReturnBlock = BB;
67 }
Owen Anderson2f82e272009-06-14 08:26:32 +000068
69 if (returnCount != 1)
Craig Topperf40110f2014-04-25 05:29:35 +000070 return nullptr;
Owen Anderson2f82e272009-06-14 08:26:32 +000071
72 // Clone the function, so that we can hack away on it.
Rafael Espindola229e38f2010-10-13 01:36:30 +000073 ValueToValueMapTy VMap;
Peter Collingbournedba99562016-05-10 20:23:24 +000074 Function* duplicateFunction = CloneFunction(F, VMap);
Owen Anderson2f82e272009-06-14 08:26:32 +000075 duplicateFunction->setLinkage(GlobalValue::InternalLinkage);
Devang Patel0dc3c2d2010-06-24 00:33:28 +000076 BasicBlock* newEntryBlock = cast<BasicBlock>(VMap[entryBlock]);
77 BasicBlock* newReturnBlock = cast<BasicBlock>(VMap[returnBlock]);
78 BasicBlock* newNonReturnBlock = cast<BasicBlock>(VMap[nonReturnBlock]);
Owen Anderson2f82e272009-06-14 08:26:32 +000079
80 // Go ahead and update all uses to the duplicate, so that we can just
81 // use the inliner functionality when we're done hacking.
82 F->replaceAllUsesWith(duplicateFunction);
83
84 // Special hackery is needed with PHI nodes that have inputs from more than
85 // one extracted block. For simplicity, just split the PHIs into a two-level
86 // sequence of PHIs, some of which will go in the extracted region, and some
87 // of which will go outside.
88 BasicBlock* preReturn = newReturnBlock;
89 newReturnBlock = newReturnBlock->splitBasicBlock(
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +000090 newReturnBlock->getFirstNonPHI()->getIterator());
Owen Anderson2f82e272009-06-14 08:26:32 +000091 BasicBlock::iterator I = preReturn->begin();
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +000092 Instruction *Ins = &newReturnBlock->front();
Owen Anderson2f82e272009-06-14 08:26:32 +000093 while (I != preReturn->end()) {
94 PHINode* OldPhi = dyn_cast<PHINode>(I);
95 if (!OldPhi) break;
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +000096
97 PHINode *retPhi = PHINode::Create(OldPhi->getType(), 2, "", Ins);
Owen Anderson2f82e272009-06-14 08:26:32 +000098 OldPhi->replaceAllUsesWith(retPhi);
99 Ins = newReturnBlock->getFirstNonPHI();
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000100
101 retPhi->addIncoming(&*I, preReturn);
Owen Anderson2f82e272009-06-14 08:26:32 +0000102 retPhi->addIncoming(OldPhi->getIncomingValueForBlock(newEntryBlock),
103 newEntryBlock);
104 OldPhi->removeIncomingValue(newEntryBlock);
105
106 ++I;
107 }
108 newEntryBlock->getTerminator()->replaceUsesOfWith(preReturn, newReturnBlock);
109
110 // Gather up the blocks that we're going to extract.
111 std::vector<BasicBlock*> toExtract;
112 toExtract.push_back(newNonReturnBlock);
113 for (Function::iterator FI = duplicateFunction->begin(),
114 FE = duplicateFunction->end(); FI != FE; ++FI)
115 if (&*FI != newEntryBlock && &*FI != newReturnBlock &&
116 &*FI != newNonReturnBlock)
Duncan P. N. Exon Smith17323402015-10-13 17:51:03 +0000117 toExtract.push_back(&*FI);
118
Owen Anderson2f82e272009-06-14 08:26:32 +0000119 // The CodeExtractor needs a dominator tree.
120 DominatorTree DT;
Chandler Carruth73523022014-01-13 13:07:17 +0000121 DT.recalculate(*duplicateFunction);
122
Dan Gohman4a618822010-02-10 16:03:48 +0000123 // Extract the body of the if.
Chandler Carruth0fde0012012-05-04 10:18:49 +0000124 Function* extractedFunction
125 = CodeExtractor(toExtract, &DT).extractCodeRegion();
Owen Anderson2f82e272009-06-14 08:26:32 +0000126
Chris Lattner4ba01ec2010-04-22 23:07:58 +0000127 InlineFunctionInfo IFI;
128
Owen Anderson2f82e272009-06-14 08:26:32 +0000129 // Inline the top-level if test into all callers.
Chandler Carruthcdf47882014-03-09 03:16:01 +0000130 std::vector<User *> Users(duplicateFunction->user_begin(),
131 duplicateFunction->user_end());
Owen Anderson2f82e272009-06-14 08:26:32 +0000132 for (std::vector<User*>::iterator UI = Users.begin(), UE = Users.end();
133 UI != UE; ++UI)
Chris Lattner4ba01ec2010-04-22 23:07:58 +0000134 if (CallInst *CI = dyn_cast<CallInst>(*UI))
135 InlineFunction(CI, IFI);
136 else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI))
137 InlineFunction(II, IFI);
Owen Anderson2f82e272009-06-14 08:26:32 +0000138
139 // Ditch the duplicate, since we're done with it, and rewrite all remaining
140 // users (function pointers, etc.) back to the original function.
141 duplicateFunction->replaceAllUsesWith(F);
142 duplicateFunction->eraseFromParent();
143
Owen Andersonbd6a2132009-06-15 20:50:26 +0000144 ++NumPartialInlined;
145
Owen Anderson2f82e272009-06-14 08:26:32 +0000146 return extractedFunction;
147}
148
149bool PartialInliner::runOnModule(Module& M) {
Andrew Kayloraa641a52016-04-22 22:06:11 +0000150 if (skipModule(M))
151 return false;
152
Owen Anderson2f82e272009-06-14 08:26:32 +0000153 std::vector<Function*> worklist;
154 worklist.reserve(M.size());
155 for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
156 if (!FI->use_empty() && !FI->isDeclaration())
Dan Gohman92fdb962010-01-05 16:20:55 +0000157 worklist.push_back(&*FI);
Owen Anderson2f82e272009-06-14 08:26:32 +0000158
159 bool changed = false;
160 while (!worklist.empty()) {
161 Function* currFunc = worklist.back();
162 worklist.pop_back();
163
164 if (currFunc->use_empty()) continue;
165
166 bool recursive = false;
Chandler Carruthcdf47882014-03-09 03:16:01 +0000167 for (User *U : currFunc->users())
168 if (Instruction* I = dyn_cast<Instruction>(U))
Owen Anderson2f82e272009-06-14 08:26:32 +0000169 if (I->getParent()->getParent() == currFunc) {
170 recursive = true;
171 break;
172 }
173 if (recursive) continue;
174
175
176 if (Function* newFunc = unswitchFunction(currFunc)) {
177 worklist.push_back(newFunc);
178 changed = true;
179 }
180
181 }
182
183 return changed;
Duncan Sands29c8efc2009-07-03 15:30:58 +0000184}