1 //===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
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 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.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "partially-inline-libcalls"
17 #include "llvm/Analysis/TargetTransformInfo.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/Intrinsics.h"
20 #include "llvm/Pass.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Target/TargetLibraryInfo.h"
23 #include "llvm/Transforms/Scalar.h"
24 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
25
26 using namespace llvm;
27
28 namespace {
29 class PartiallyInlineLibCalls : public FunctionPass {
30 public:
31 static char ID;
32
PartiallyInlineLibCalls()33 PartiallyInlineLibCalls() :
34 FunctionPass(ID) {
35 initializePartiallyInlineLibCallsPass(*PassRegistry::getPassRegistry());
36 }
37
38 virtual void getAnalysisUsage(AnalysisUsage &AU) const;
39 virtual bool runOnFunction(Function &F);
40
41 private:
42 /// Optimize calls to sqrt.
43 bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
44 BasicBlock &CurrBB, Function::iterator &BB);
45 };
46
47 char PartiallyInlineLibCalls::ID = 0;
48 }
49
50 INITIALIZE_PASS(PartiallyInlineLibCalls, "partially-inline-libcalls",
51 "Partially inline calls to library functions", false, false)
52
getAnalysisUsage(AnalysisUsage & AU) const53 void PartiallyInlineLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
54 AU.addRequired<TargetLibraryInfo>();
55 AU.addRequired<TargetTransformInfo>();
56 FunctionPass::getAnalysisUsage(AU);
57 }
58
runOnFunction(Function & F)59 bool PartiallyInlineLibCalls::runOnFunction(Function &F) {
60 bool Changed = false;
61 Function::iterator CurrBB;
62 TargetLibraryInfo *TLI = &getAnalysis<TargetLibraryInfo>();
63 const TargetTransformInfo *TTI = &getAnalysis<TargetTransformInfo>();
64 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
65 CurrBB = BB++;
66
67 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
68 II != IE; ++II) {
69 CallInst *Call = dyn_cast<CallInst>(&*II);
70 Function *CalledFunc;
71
72 if (!Call || !(CalledFunc = Call->getCalledFunction()))
73 continue;
74
75 // Skip if function either has local linkage or is not a known library
76 // function.
77 LibFunc::Func LibFunc;
78 if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
79 !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
80 continue;
81
82 switch (LibFunc) {
83 case LibFunc::sqrtf:
84 case LibFunc::sqrt:
85 if (TTI->haveFastSqrt(Call->getType()) &&
86 optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
87 break;
88 continue;
89 default:
90 continue;
91 }
92
93 Changed = true;
94 break;
95 }
96 }
97
98 return Changed;
99 }
100
optimizeSQRT(CallInst * Call,Function * CalledFunc,BasicBlock & CurrBB,Function::iterator & BB)101 bool PartiallyInlineLibCalls::optimizeSQRT(CallInst *Call,
102 Function *CalledFunc,
103 BasicBlock &CurrBB,
104 Function::iterator &BB) {
105 // There is no need to change the IR, since backend will emit sqrt
106 // instruction if the call has already been marked read-only.
107 if (Call->onlyReadsMemory())
108 return false;
109
110 // Do the following transformation:
111 //
112 // (before)
113 // dst = sqrt(src)
114 //
115 // (after)
116 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
117 // if (v0 is a NaN)
118 // v1 = sqrt(src) # library call.
119 // dst = phi(v0, v1)
120 //
121
122 // Move all instructions following Call to newly created block JoinBB.
123 // Create phi and replace all uses.
124 BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode(), this);
125 IRBuilder<> Builder(JoinBB, JoinBB->begin());
126 PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
127 Call->replaceAllUsesWith(Phi);
128
129 // Create basic block LibCallBB and insert a call to library function sqrt.
130 BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
131 CurrBB.getParent(), JoinBB);
132 Builder.SetInsertPoint(LibCallBB);
133 Instruction *LibCall = Call->clone();
134 Builder.Insert(LibCall);
135 Builder.CreateBr(JoinBB);
136
137 // Add attribute "readnone" so that backend can use a native sqrt instruction
138 // for this call. Insert a FP compare instruction and a conditional branch
139 // at the end of CurrBB.
140 Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
141 CurrBB.getTerminator()->eraseFromParent();
142 Builder.SetInsertPoint(&CurrBB);
143 Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
144 Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
145
146 // Add phi operands.
147 Phi->addIncoming(Call, &CurrBB);
148 Phi->addIncoming(LibCall, LibCallBB);
149
150 BB = JoinBB;
151 return true;
152 }
153
createPartiallyInlineLibCallsPass()154 FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
155 return new PartiallyInlineLibCalls();
156 }
157