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/Transforms/Scalar/PartiallyInlineLibCalls.h"
17 #include "llvm/Analysis/TargetLibraryInfo.h"
18 #include "llvm/Analysis/TargetTransformInfo.h"
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/Transforms/Scalar.h"
21 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
25 #define DEBUG_TYPE "partially-inline-libcalls"
28 static bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
29 BasicBlock &CurrBB, Function::iterator &BB) {
30 // There is no need to change the IR, since backend will emit sqrt
31 // instruction if the call has already been marked read-only.
32 if (Call->onlyReadsMemory())
35 // The call must have the expected result type.
36 if (!Call->getType()->isFloatingPointTy())
39 // Do the following transformation:
45 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
47 // v1 = sqrt(src) # library call.
51 // Move all instructions following Call to newly created block JoinBB.
52 // Create phi and replace all uses.
53 BasicBlock *JoinBB = llvm::SplitBlock(&CurrBB, Call->getNextNode());
54 IRBuilder<> Builder(JoinBB, JoinBB->begin());
55 PHINode *Phi = Builder.CreatePHI(Call->getType(), 2);
56 Call->replaceAllUsesWith(Phi);
58 // Create basic block LibCallBB and insert a call to library function sqrt.
59 BasicBlock *LibCallBB = BasicBlock::Create(CurrBB.getContext(), "call.sqrt",
60 CurrBB.getParent(), JoinBB);
61 Builder.SetInsertPoint(LibCallBB);
62 Instruction *LibCall = Call->clone();
63 Builder.Insert(LibCall);
64 Builder.CreateBr(JoinBB);
66 // Add attribute "readnone" so that backend can use a native sqrt instruction
67 // for this call. Insert a FP compare instruction and a conditional branch
68 // at the end of CurrBB.
69 Call->addAttribute(AttributeSet::FunctionIndex, Attribute::ReadNone);
70 CurrBB.getTerminator()->eraseFromParent();
71 Builder.SetInsertPoint(&CurrBB);
72 Value *FCmp = Builder.CreateFCmpOEQ(Call, Call);
73 Builder.CreateCondBr(FCmp, JoinBB, LibCallBB);
76 Phi->addIncoming(Call, &CurrBB);
77 Phi->addIncoming(LibCall, LibCallBB);
79 BB = JoinBB->getIterator();
83 static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI,
84 const TargetTransformInfo *TTI) {
87 Function::iterator CurrBB;
88 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
91 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
93 CallInst *Call = dyn_cast<CallInst>(&*II);
96 if (!Call || !(CalledFunc = Call->getCalledFunction()))
99 // Skip if function either has local linkage or is not a known library
101 LibFunc::Func LibFunc;
102 if (CalledFunc->hasLocalLinkage() || !CalledFunc->hasName() ||
103 !TLI->getLibFunc(CalledFunc->getName(), LibFunc))
109 if (TTI->haveFastSqrt(Call->getType()) &&
110 optimizeSQRT(Call, CalledFunc, *CurrBB, BB))
126 PartiallyInlineLibCallsPass::run(Function &F, AnalysisManager<Function> &AM) {
127 auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
128 auto &TTI = AM.getResult<TargetIRAnalysis>(F);
129 if (!runPartiallyInlineLibCalls(F, &TLI, &TTI))
130 return PreservedAnalyses::all();
131 return PreservedAnalyses::none();
135 class PartiallyInlineLibCallsLegacyPass : public FunctionPass {
139 PartiallyInlineLibCallsLegacyPass() : FunctionPass(ID) {
140 initializePartiallyInlineLibCallsLegacyPassPass(
141 *PassRegistry::getPassRegistry());
144 void getAnalysisUsage(AnalysisUsage &AU) const override {
145 AU.addRequired<TargetLibraryInfoWrapperPass>();
146 AU.addRequired<TargetTransformInfoWrapperPass>();
147 FunctionPass::getAnalysisUsage(AU);
150 bool runOnFunction(Function &F) override {
154 TargetLibraryInfo *TLI =
155 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI();
156 const TargetTransformInfo *TTI =
157 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
158 return runPartiallyInlineLibCalls(F, TLI, TTI);
163 char PartiallyInlineLibCallsLegacyPass::ID = 0;
164 INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass,
165 "partially-inline-libcalls",
166 "Partially inline calls to library functions", false,
168 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
169 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
170 INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass,
171 "partially-inline-libcalls",
172 "Partially inline calls to library functions", false, false)
174 FunctionPass *llvm::createPartiallyInlineLibCallsPass() {
175 return new PartiallyInlineLibCallsLegacyPass();