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 #include "llvm/Analysis/TargetLibraryInfo.h"
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/Transforms/Scalar.h"
22 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
23 
24 using namespace llvm;
25 
26 #define DEBUG_TYPE "partially-inline-libcalls"
27 
28 namespace {
29   class PartiallyInlineLibCalls : public FunctionPass {
30   public:
31     static char ID;
32 
33     PartiallyInlineLibCalls() :
34       FunctionPass(ID) {
35       initializePartiallyInlineLibCallsPass(*PassRegistry::getPassRegistry());
36     }
37 
38     void getAnalysisUsage(AnalysisUsage &AU) const override;
39     bool runOnFunction(Function &F) override;
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 
53 void PartiallyInlineLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
54   AU.addRequired<TargetLibraryInfoWrapperPass>();
55   AU.addRequired<TargetTransformInfoWrapperPass>();
56   FunctionPass::getAnalysisUsage(AU);
57 }
58 
59 bool PartiallyInlineLibCalls::runOnFunction(Function &F) {
60   if (skipFunction(F))
61     return false;
62 
63   bool Changed = false;
64   Function::iterator CurrBB;
65   TargetLibraryInfo *TLI =
66       &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
67   const TargetTransformInfo *TTI =
68       &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
69   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 
80       // Skip if function either has local linkage or is not a known library
81       // function.
82       LibFunc::Func LibFunc;
83       if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
84           !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
85         continue;
86 
87       switch (LibFunc) {
88       case LibFunc::sqrtf:
89       case LibFunc::sqrt:
90         if (TTI->haveFastSqrt(Call->getType()) &&
91             optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
92           break;
93         continue;
94       default:
95         continue;
96       }
97 
98       Changed = true;
99       break;
100     }
101   }
102 
103   return Changed;
104 }
105 
106 bool PartiallyInlineLibCalls::optimizeSQRT(CallInst *Call,
107                                            Function *CalledFunc,
108                                            BasicBlock &CurrBB,
109                                            Function::iterator &BB) {
110   // 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 
115   // The call must have the expected result type.
116   if (!Call->getType()->isFloatingPointTy())
117     return false;
118 
119   // 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.
133   BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode());
134   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 
159   BB = JoinBB->getIterator();
160   return true;
161 }
162 
163 FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
164   return new PartiallyInlineLibCalls();
165 }
166