]>
git.proxmox.com Git - rustc.git/blob - src/llvm/lib/Transforms/Scalar/PartiallyInlineLibCalls.cpp
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/Target/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
<TargetLibraryInfo
>();
56 AU
.addRequired
<TargetTransformInfo
>();
57 FunctionPass::getAnalysisUsage(AU
);
60 bool PartiallyInlineLibCalls::runOnFunction(Function
&F
) {
62 Function::iterator CurrBB
;
63 TargetLibraryInfo
*TLI
= &getAnalysis
<TargetLibraryInfo
>();
64 const TargetTransformInfo
*TTI
= &getAnalysis
<TargetTransformInfo
>();
65 for (Function::iterator BB
= F
.begin(), BE
= F
.end(); BB
!= BE
;) {
68 for (BasicBlock::iterator II
= CurrBB
->begin(), IE
= CurrBB
->end();
70 CallInst
*Call
= dyn_cast
<CallInst
>(&*II
);
73 if (!Call
|| !(CalledFunc
= Call
->getCalledFunction()))
76 // Skip if function either has local linkage or is not a known library
78 LibFunc::Func LibFunc
;
79 if (CalledFunc
->hasLocalLinkage() || !CalledFunc
->hasName() ||
80 !TLI
->getLibFunc(CalledFunc
->getName(), LibFunc
))
86 if (TTI
->haveFastSqrt(Call
->getType()) &&
87 optimizeSQRT(Call
, CalledFunc
, *CurrBB
, BB
))
102 bool PartiallyInlineLibCalls::optimizeSQRT(CallInst
*Call
,
103 Function
*CalledFunc
,
105 Function::iterator
&BB
) {
106 // There is no need to change the IR, since backend will emit sqrt
107 // instruction if the call has already been marked read-only.
108 if (Call
->onlyReadsMemory())
111 // The call must have the expected result type.
112 if (!Call
->getType()->isFloatingPointTy())
115 // Do the following transformation:
121 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
123 // v1 = sqrt(src) # library call.
127 // Move all instructions following Call to newly created block JoinBB.
128 // Create phi and replace all uses.
129 BasicBlock
*JoinBB
= llvm::SplitBlock(&CurrBB
, Call
->getNextNode(), this);
130 IRBuilder
<> Builder(JoinBB
, JoinBB
->begin());
131 PHINode
*Phi
= Builder
.CreatePHI(Call
->getType(), 2);
132 Call
->replaceAllUsesWith(Phi
);
134 // Create basic block LibCallBB and insert a call to library function sqrt.
135 BasicBlock
*LibCallBB
= BasicBlock::Create(CurrBB
.getContext(), "call.sqrt",
136 CurrBB
.getParent(), JoinBB
);
137 Builder
.SetInsertPoint(LibCallBB
);
138 Instruction
*LibCall
= Call
->clone();
139 Builder
.Insert(LibCall
);
140 Builder
.CreateBr(JoinBB
);
142 // Add attribute "readnone" so that backend can use a native sqrt instruction
143 // for this call. Insert a FP compare instruction and a conditional branch
144 // at the end of CurrBB.
145 Call
->addAttribute(AttributeSet::FunctionIndex
, Attribute::ReadNone
);
146 CurrBB
.getTerminator()->eraseFromParent();
147 Builder
.SetInsertPoint(&CurrBB
);
148 Value
*FCmp
= Builder
.CreateFCmpOEQ(Call
, Call
);
149 Builder
.CreateCondBr(FCmp
, JoinBB
, LibCallBB
);
152 Phi
->addIncoming(Call
, &CurrBB
);
153 Phi
->addIncoming(LibCall
, LibCallBB
);
159 FunctionPass
*llvm::createPartiallyInlineLibCallsPass() {
160 return new PartiallyInlineLibCalls();