1 //===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This pass tries to partially inline the fast path of well-known library
10 // functions, such as using square-root instructions for cases where sqrt()
11 // does not need to set errno.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Transforms/Scalar/PartiallyInlineLibCalls.h"
16 #include "llvm/Analysis/TargetLibraryInfo.h"
17 #include "llvm/Analysis/TargetTransformInfo.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/Support/DebugCounter.h"
20 #include "llvm/Transforms/Scalar.h"
21 #include "llvm/Transforms/Utils/BasicBlockUtils.h"
25 #define DEBUG_TYPE "partially-inline-libcalls"
27 DEBUG_COUNTER(PILCounter
, "partially-inline-libcalls-transform",
28 "Controls transformations in partially-inline-libcalls");
30 static bool optimizeSQRT(CallInst
*Call
, Function
*CalledFunc
,
31 BasicBlock
&CurrBB
, Function::iterator
&BB
,
32 const TargetTransformInfo
*TTI
) {
33 // There is no need to change the IR, since backend will emit sqrt
34 // instruction if the call has already been marked read-only.
35 if (Call
->onlyReadsMemory())
38 if (!DebugCounter::shouldExecute(PILCounter
))
41 // Do the following transformation:
47 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
48 // [if (v0 is a NaN) || if (src < 0)]
49 // v1 = sqrt(src) # library call.
53 // Move all instructions following Call to newly created block JoinBB.
54 // Create phi and replace all uses.
55 BasicBlock
*JoinBB
= llvm::SplitBlock(&CurrBB
, Call
->getNextNode());
56 IRBuilder
<> Builder(JoinBB
, JoinBB
->begin());
57 Type
*Ty
= Call
->getType();
58 PHINode
*Phi
= Builder
.CreatePHI(Ty
, 2);
59 Call
->replaceAllUsesWith(Phi
);
61 // Create basic block LibCallBB and insert a call to library function sqrt.
62 BasicBlock
*LibCallBB
= BasicBlock::Create(CurrBB
.getContext(), "call.sqrt",
63 CurrBB
.getParent(), JoinBB
);
64 Builder
.SetInsertPoint(LibCallBB
);
65 Instruction
*LibCall
= Call
->clone();
66 Builder
.Insert(LibCall
);
67 Builder
.CreateBr(JoinBB
);
69 // Add attribute "readnone" so that backend can use a native sqrt instruction
70 // for this call. Insert a FP compare instruction and a conditional branch
71 // at the end of CurrBB.
72 Call
->addAttribute(AttributeList::FunctionIndex
, Attribute::ReadNone
);
73 CurrBB
.getTerminator()->eraseFromParent();
74 Builder
.SetInsertPoint(&CurrBB
);
75 Value
*FCmp
= TTI
->isFCmpOrdCheaperThanFCmpZero(Ty
)
76 ? Builder
.CreateFCmpORD(Call
, Call
)
77 : Builder
.CreateFCmpOGE(Call
->getOperand(0),
78 ConstantFP::get(Ty
, 0.0));
79 Builder
.CreateCondBr(FCmp
, JoinBB
, LibCallBB
);
82 Phi
->addIncoming(Call
, &CurrBB
);
83 Phi
->addIncoming(LibCall
, LibCallBB
);
85 BB
= JoinBB
->getIterator();
89 static bool runPartiallyInlineLibCalls(Function
&F
, TargetLibraryInfo
*TLI
,
90 const TargetTransformInfo
*TTI
) {
93 Function::iterator CurrBB
;
94 for (Function::iterator BB
= F
.begin(), BE
= F
.end(); BB
!= BE
;) {
97 for (BasicBlock::iterator II
= CurrBB
->begin(), IE
= CurrBB
->end();
99 CallInst
*Call
= dyn_cast
<CallInst
>(&*II
);
100 Function
*CalledFunc
;
102 if (!Call
|| !(CalledFunc
= Call
->getCalledFunction()))
105 if (Call
->isNoBuiltin())
108 // Skip if function either has local linkage or is not a known library
111 if (CalledFunc
->hasLocalLinkage() ||
112 !TLI
->getLibFunc(*CalledFunc
, LF
) || !TLI
->has(LF
))
118 if (TTI
->haveFastSqrt(Call
->getType()) &&
119 optimizeSQRT(Call
, CalledFunc
, *CurrBB
, BB
, TTI
))
135 PartiallyInlineLibCallsPass::run(Function
&F
, FunctionAnalysisManager
&AM
) {
136 auto &TLI
= AM
.getResult
<TargetLibraryAnalysis
>(F
);
137 auto &TTI
= AM
.getResult
<TargetIRAnalysis
>(F
);
138 if (!runPartiallyInlineLibCalls(F
, &TLI
, &TTI
))
139 return PreservedAnalyses::all();
140 return PreservedAnalyses::none();
144 class PartiallyInlineLibCallsLegacyPass
: public FunctionPass
{
148 PartiallyInlineLibCallsLegacyPass() : FunctionPass(ID
) {
149 initializePartiallyInlineLibCallsLegacyPassPass(
150 *PassRegistry::getPassRegistry());
153 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
154 AU
.addRequired
<TargetLibraryInfoWrapperPass
>();
155 AU
.addRequired
<TargetTransformInfoWrapperPass
>();
156 FunctionPass::getAnalysisUsage(AU
);
159 bool runOnFunction(Function
&F
) override
{
163 TargetLibraryInfo
*TLI
=
164 &getAnalysis
<TargetLibraryInfoWrapperPass
>().getTLI();
165 const TargetTransformInfo
*TTI
=
166 &getAnalysis
<TargetTransformInfoWrapperPass
>().getTTI(F
);
167 return runPartiallyInlineLibCalls(F
, TLI
, TTI
);
172 char PartiallyInlineLibCallsLegacyPass::ID
= 0;
173 INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass
,
174 "partially-inline-libcalls",
175 "Partially inline calls to library functions", false,
177 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass
)
178 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass
)
179 INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass
,
180 "partially-inline-libcalls",
181 "Partially inline calls to library functions", false, false)
183 FunctionPass
*llvm::createPartiallyInlineLibCallsPass() {
184 return new PartiallyInlineLibCallsLegacyPass();