blob: 27bb230af2f06c1ffe66685ba8add32605e167de [file] [log] [blame]
Richard Sandiford37cd6cf2013-08-23 10:27:02 +00001//===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
Akira Hatanaka5c50a162013-06-11 22:21:44 +00002//
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//
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000010// This pass tries to partially inline the fast path of well-known library
11// functions, such as using square-root instructions for cases where sqrt()
12// does not need to set errno.
Akira Hatanaka5c50a162013-06-11 22:21:44 +000013//
14//===----------------------------------------------------------------------===//
15
Mehdi Aminib550cb12016-04-18 09:17:29 +000016#include "llvm/Analysis/TargetLibraryInfo.h"
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000017#include "llvm/Analysis/TargetTransformInfo.h"
Akira Hatanaka5c50a162013-06-11 22:21:44 +000018#include "llvm/IR/IRBuilder.h"
19#include "llvm/IR/Intrinsics.h"
20#include "llvm/Pass.h"
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000021#include "llvm/Transforms/Scalar.h"
Akira Hatanaka5c50a162013-06-11 22:21:44 +000022#include "llvm/Transforms/Utils/BasicBlockUtils.h"
23
24using namespace llvm;
25
Chandler Carruth964daaa2014-04-22 02:55:47 +000026#define DEBUG_TYPE "partially-inline-libcalls"
27
Akira Hatanaka5c50a162013-06-11 22:21:44 +000028namespace {
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000029 class PartiallyInlineLibCalls : public FunctionPass {
Akira Hatanaka5c50a162013-06-11 22:21:44 +000030 public:
31 static char ID;
32
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000033 PartiallyInlineLibCalls() :
34 FunctionPass(ID) {
35 initializePartiallyInlineLibCallsPass(*PassRegistry::getPassRegistry());
Akira Hatanaka5c50a162013-06-11 22:21:44 +000036 }
37
Craig Topper3e4c6972014-03-05 09:10:37 +000038 void getAnalysisUsage(AnalysisUsage &AU) const override;
39 bool runOnFunction(Function &F) override;
Akira Hatanaka5c50a162013-06-11 22:21:44 +000040
41 private:
42 /// Optimize calls to sqrt.
43 bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000044 BasicBlock &CurrBB, Function::iterator &BB);
Akira Hatanaka5c50a162013-06-11 22:21:44 +000045 };
46
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000047 char PartiallyInlineLibCalls::ID = 0;
Alexander Kornienkof00654e2015-06-23 09:49:53 +000048}
Akira Hatanaka5c50a162013-06-11 22:21:44 +000049
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000050INITIALIZE_PASS(PartiallyInlineLibCalls, "partially-inline-libcalls",
51 "Partially inline calls to library functions", false, false)
Akira Hatanaka5c50a162013-06-11 22:21:44 +000052
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000053void PartiallyInlineLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
Chandler Carruthb98f63d2015-01-15 10:41:28 +000054 AU.addRequired<TargetLibraryInfoWrapperPass>();
Chandler Carruth705b1852015-01-31 03:43:40 +000055 AU.addRequired<TargetTransformInfoWrapperPass>();
Akira Hatanaka5c50a162013-06-11 22:21:44 +000056 FunctionPass::getAnalysisUsage(AU);
57}
58
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000059bool PartiallyInlineLibCalls::runOnFunction(Function &F) {
Andrew Kaylor50271f72016-05-03 22:32:30 +000060 if (skipFunction(F))
61 return false;
62
Akira Hatanaka5c50a162013-06-11 22:21:44 +000063 bool Changed = false;
64 Function::iterator CurrBB;
Chandler Carruthb98f63d2015-01-15 10:41:28 +000065 TargetLibraryInfo *TLI =
66 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
Chandler Carruth705b1852015-01-31 03:43:40 +000067 const TargetTransformInfo *TTI =
Chandler Carruthfdb9c572015-02-01 12:01:35 +000068 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
Akira Hatanaka5c50a162013-06-11 22:21:44 +000069 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
70 CurrBB = BB++;
71
72 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
73 II != IE; ++II) {
74 CallInst *Call = dyn_cast<CallInst>(&*II);
75 Function *CalledFunc;
76
77 if (!Call || !(CalledFunc = Call->getCalledFunction()))
78 continue;
79
Akira Hatanaka5c50a162013-06-11 22:21:44 +000080 // Skip if function either has local linkage or is not a known library
81 // function.
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000082 LibFunc::Func LibFunc;
Akira Hatanaka5c50a162013-06-11 22:21:44 +000083 if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000084 !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
Akira Hatanaka5c50a162013-06-11 22:21:44 +000085 continue;
86
87 switch (LibFunc) {
88 case LibFunc::sqrtf:
89 case LibFunc::sqrt:
Richard Sandiford37cd6cf2013-08-23 10:27:02 +000090 if (TTI->haveFastSqrt(Call->getType()) &&
91 optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
Akira Hatanaka5c50a162013-06-11 22:21:44 +000092 break;
93 continue;
94 default:
95 continue;
96 }
97
98 Changed = true;
99 break;
100 }
101 }
102
103 return Changed;
104}
105
Richard Sandiford37cd6cf2013-08-23 10:27:02 +0000106bool PartiallyInlineLibCalls::optimizeSQRT(CallInst *Call,
107 Function *CalledFunc,
108 BasicBlock &CurrBB,
109 Function::iterator &BB) {
Akira Hatanaka5c50a162013-06-11 22:21:44 +0000110 // There is no need to change the IR, since backend will emit sqrt
111 // instruction if the call has already been marked read-only.
112 if (Call->onlyReadsMemory())
113 return false;
114
Peter Collingbournee52646c2014-08-01 23:21:21 +0000115 // The call must have the expected result type.
116 if (!Call->getType()->isFloatingPointTy())
117 return false;
118
Akira Hatanaka5c50a162013-06-11 22:21:44 +0000119 // Do the following transformation:
120 //
121 // (before)
122 // dst = sqrt(src)
123 //
124 // (after)
125 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
126 // if (v0 is a NaN)
127 // v1 = sqrt(src) # library call.
128 // dst = phi(v0, v1)
129 //
130
131 // Move all instructions following Call to newly created block JoinBB.
132 // Create phi and replace all uses.
Chandler Carruth32c52c72015-01-18 02:39:37 +0000133 BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode());
Akira Hatanaka5c50a162013-06-11 22:21:44 +0000134 IRBuilder<> Builder(JoinBB, JoinBB->begin());
135 PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
136 Call->replaceAllUsesWith(Phi);
137
138 // Create basic block LibCallBB and insert a call to library function sqrt.
139 BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
140 CurrBB.getParent(), JoinBB);
141 Builder.SetInsertPoint(LibCallBB);
142 Instruction *LibCall = Call->clone();
143 Builder.Insert(LibCall);
144 Builder.CreateBr(JoinBB);
145
146 // Add attribute "readnone" so that backend can use a native sqrt instruction
147 // for this call. Insert a FP compare instruction and a conditional branch
148 // at the end of CurrBB.
149 Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
150 CurrBB.getTerminator()->eraseFromParent();
151 Builder.SetInsertPoint(&CurrBB);
152 Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
153 Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
154
155 // Add phi operands.
156 Phi->addIncoming(Call, &CurrBB);
157 Phi->addIncoming(LibCall, LibCallBB);
158
Duncan P. N. Exon Smithbe4d8cb2015-10-13 19:26:58 +0000159 BB = JoinBB->getIterator();
Akira Hatanaka5c50a162013-06-11 22:21:44 +0000160 return true;
161}
Richard Sandiford37cd6cf2013-08-23 10:27:02 +0000162
163FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
164 return new PartiallyInlineLibCalls();
165}