1 //===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
16 #include "llvm/Analysis/TargetTransformInfo.h"
17 #include "llvm/IR/IRBuilder.h"
18 #include "llvm/IR/Intrinsics.h"
19 #include "llvm/Pass.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Analysis/TargetLibraryInfo.h"
22 #include "llvm/Transforms/Scalar.h"
23 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
27 #define DEBUG_TYPE "partially-inline-libcalls"
30 class PartiallyInlineLibCalls : public FunctionPass {
34 PartiallyInlineLibCalls() :
36 initializePartiallyInlineLibCallsPass(*PassRegistry::getPassRegistry());
39 void getAnalysisUsage(AnalysisUsage &AU) const override;
40 bool runOnFunction(Function &F) override;
43 /// Optimize calls to sqrt.
44 bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
45 BasicBlock &CurrBB, Function::iterator &BB);
48 char PartiallyInlineLibCalls::ID = 0;
51 INITIALIZE_PASS(PartiallyInlineLibCalls, "partially-inline-libcalls",
52 "Partially inline calls to library functions", false, false)
54 void PartiallyInlineLibCalls::getAnalysisUsage(AnalysisUsage &AU) const {
55 AU.addRequired<TargetLibraryInfoWrapperPass>();
56 AU.addRequired<TargetTransformInfo>();
57 FunctionPass::getAnalysisUsage(AU);
60 bool PartiallyInlineLibCalls::runOnFunction(Function &F) {
62 Function::iterator CurrBB;
63 TargetLibraryInfo *TLI =
64 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
65 const TargetTransformInfo *TTI = &getAnalysis<TargetTransformInfo>();
66 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
69 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
71 CallInst *Call = dyn_cast<CallInst>(&*II);
74 if (!Call || !(CalledFunc = Call->getCalledFunction()))
77 // Skip if function either has local linkage or is not a known library
79 LibFunc::Func LibFunc;
80 if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
81 !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
87 if (TTI->haveFastSqrt(Call->getType()) &&
88 optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
103 bool PartiallyInlineLibCalls::optimizeSQRT(CallInst *Call,
104 Function *CalledFunc,
106 Function::iterator &BB) {
107 // There is no need to change the IR, since backend will emit sqrt
108 // instruction if the call has already been marked read-only.
109 if (Call->onlyReadsMemory())
112 // The call must have the expected result type.
113 if (!Call->getType()->isFloatingPointTy())
116 // Do the following transformation:
122 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
124 // v1 = sqrt(src) # library call.
128 // Move all instructions following Call to newly created block JoinBB.
129 // Create phi and replace all uses.
130 BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode());
131 IRBuilder<> Builder(JoinBB, JoinBB->begin());
132 PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
133 Call->replaceAllUsesWith(Phi);
135 // Create basic block LibCallBB and insert a call to library function sqrt.
136 BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
137 CurrBB.getParent(), JoinBB);
138 Builder.SetInsertPoint(LibCallBB);
139 Instruction *LibCall = Call->clone();
140 Builder.Insert(LibCall);
141 Builder.CreateBr(JoinBB);
143 // Add attribute "readnone" so that backend can use a native sqrt instruction
144 // for this call. Insert a FP compare instruction and a conditional branch
145 // at the end of CurrBB.
146 Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
147 CurrBB.getTerminator()->eraseFromParent();
148 Builder.SetInsertPoint(&CurrBB);
149 Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
150 Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
153 Phi->addIncoming(Call, &CurrBB);
154 Phi->addIncoming(LibCall, LibCallBB);
160 FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
161 return new PartiallyInlineLibCalls();