LLVM 24.0.0git
PartiallyInlineLibCalls.cpp
Go to the documentation of this file.
1//===--- PartiallyInlineLibCalls.cpp - Partially inline libcalls ----------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
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.
12//
13//===----------------------------------------------------------------------===//
14
20#include "llvm/IR/Dominators.h"
21#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/MDBuilder.h"
27#include <optional>
28
29using namespace llvm;
30
31#define DEBUG_TYPE "partially-inline-libcalls"
32
33DEBUG_COUNTER(PILCounter, "partially-inline-libcalls-transform",
34 "Controls transformations in partially-inline-libcalls");
35
36static bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
37 BasicBlock &CurrBB, Function::iterator &BB,
40 // There is no need to change the IR, since backend will emit sqrt
41 // instruction if the call has already been marked read-only.
42 if (Call->onlyReadsMemory())
43 return false;
44
45 if (!DebugCounter::shouldExecute(PILCounter))
46 return false;
47
48 // Do the following transformation:
49 //
50 // (before)
51 // dst = sqrt(src)
52 //
53 // (after)
54 // v0 = sqrt_noreadmem(src) # native sqrt instruction.
55 // [if (v0 is a NaN) || if (src < 0)]
56 // v1 = sqrt(src) # library call.
57 // dst = phi(v0, v1)
58 //
59
60 Type *Ty = Call->getType();
61 IRBuilder<> Builder(Call->getNextNode());
62
63 // Split CurrBB right after the call, create a 'then' block (that branches
64 // back to split-off tail of CurrBB) into which we'll insert a libcall.
66 Builder.getTrue(), Call->getNextNode(), /*Unreachable=*/false,
67 /*BranchWeights*/ nullptr, DTU);
68
69 auto *CurrBBTerm = cast<CondBrInst>(CurrBB.getTerminator());
70 // We want an 'else' block though, not a 'then' block.
71 CurrBBTerm->swapSuccessors();
72
73 // Create phi that will merge results of either sqrt and replace all uses.
74 BasicBlock *JoinBB = LibCallTerm->getSuccessor(0);
75 JoinBB->setName(CurrBB.getName() + ".split");
76 Builder.SetInsertPoint(JoinBB->begin());
77 PHINode *Phi = Builder.CreatePHI(Ty, 2);
78 Call->replaceAllUsesWith(Phi);
79
80 // Finally, insert the libcall into 'else' block.
81 BasicBlock *LibCallBB = LibCallTerm->getParent();
82 LibCallBB->setName("call.sqrt");
83 Builder.SetInsertPoint(LibCallTerm);
84 Instruction *LibCall = Call->clone();
85 Builder.Insert(LibCall);
86
87 // Add memory(none) attribute, so that the backend can use a native sqrt
88 // instruction for this call.
89 Call->setDoesNotAccessMemory();
90
91 // Insert a FP compare instruction and use it as the CurrBB branch condition.
92 Builder.SetInsertPoint(CurrBBTerm);
93 Value *FCmp = TTI->isFCmpOrdCheaperThanFCmpZero(Ty)
94 ? Builder.CreateFCmpORD(Call, Call)
95 : Builder.CreateFCmpOGE(Call->getOperand(0),
96 ConstantFP::get(Ty, 0.0));
97 CurrBBTerm->setCondition(FCmp);
98 if (CurrBBTerm->getFunction()->getEntryCount()) {
99 // Presume the quick path - where we don't call the library call - is the
100 // frequent one
101 MDBuilder MDB(CurrBBTerm->getContext());
102 CurrBBTerm->setMetadata(LLVMContext::MD_prof,
104 }
105 // Add phi operands.
106 Phi->addIncoming(Call, &CurrBB);
107 Phi->addIncoming(LibCall, LibCallBB);
108
109 BB = JoinBB->getIterator();
110 return true;
111}
112
115 DominatorTree *DT,
117 std::optional<DomTreeUpdater> DTU;
118 if (DT)
119 DTU.emplace(DT, DomTreeUpdater::UpdateStrategy::Lazy);
120
121 bool Changed = false;
122
123 Function::iterator CurrBB;
124 for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
125 CurrBB = BB++;
126
127 for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
128 II != IE; ++II) {
130 Function *CalledFunc;
131
132 if (!Call || !(CalledFunc = Call->getCalledFunction()))
133 continue;
134
135 if (Call->isNoBuiltin() || Call->isStrictFP())
136 continue;
137
138 if (Call->isMustTailCall())
139 continue;
140
141 // Skip if function either has local linkage or is not a known library
142 // function.
143 if (CalledFunc->hasLocalLinkage())
144 continue;
145
146 LibFunc LF = TLI->getLibFunc(*CalledFunc);
147 if (!TLI->has(LF))
148 continue;
149
150 switch (LF) {
151 case LibFunc_sqrtf:
152 case LibFunc_sqrt:
153 if (TTI->haveFastSqrt(Call->getType()) &&
154 optimizeSQRT(Call, CalledFunc, *CurrBB, BB, TTI,
155 DTU ? &*DTU : nullptr, ORE))
156 break;
157 continue;
158 default:
159 continue;
160 }
161
162 Changed = true;
163 break;
164 }
165 }
166
167 return Changed;
168}
169
182
183namespace {
184class PartiallyInlineLibCallsLegacyPass : public FunctionPass {
185public:
186 static char ID;
187
188 PartiallyInlineLibCallsLegacyPass() : FunctionPass(ID) {
191 }
192
193 void getAnalysisUsage(AnalysisUsage &AU) const override {
199 }
200
201 bool runOnFunction(Function &F) override {
202 if (skipFunction(F))
203 return false;
204
205 TargetLibraryInfo *TLI =
206 &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
207 const TargetTransformInfo *TTI =
208 &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
209 DominatorTree *DT = nullptr;
210 if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
211 DT = &DTWP->getDomTree();
212 auto *ORE = &getAnalysis<OptimizationRemarkEmitterWrapperPass>().getORE();
213 return runPartiallyInlineLibCalls(F, TLI, TTI, DT, ORE);
214 }
215};
216}
217
218char PartiallyInlineLibCallsLegacyPass::ID = 0;
219INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass,
220 "partially-inline-libcalls",
221 "Partially inline calls to library functions", false,
222 false)
227INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass,
228 "partially-inline-libcalls",
229 "Partially inline calls to library functions", false, false)
230
232 return new PartiallyInlineLibCallsLegacyPass();
233}
const TargetLowering & TLI
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
static bool runOnFunction(Function &F, bool PostInlining)
#define F(x, y, z)
Definition MD5.cpp:54
uint64_t IntrinsicInst * II
static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI, const TargetTransformInfo *TTI, DominatorTree *DT, OptimizationRemarkEmitter *ORE)
static bool optimizeSQRT(CallInst *Call, Function *CalledFunc, BasicBlock &CurrBB, Function::iterator &BB, const TargetTransformInfo *TTI, DomTreeUpdater *DTU, OptimizationRemarkEmitter *ORE)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This pass exposes codegen information to IR-level passes.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:440
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
This class represents a function call, abstracting a target machine's calling convention.
static bool shouldExecute(CounterInfo &Counter)
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:277
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition Dominators.h:122
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
BasicBlockListType::iterator iterator
Definition Function.h:70
bool hasLocalLinkage() const
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2947
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI MDNode * createLikelyBranchWeights()
Return metadata containing two branch weights, with significant bias towards true destination.
Definition MDBuilder.cpp:43
OptimizationRemarkEmitter legacy analysis pass.
The optimization diagnostic interface.
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition Pass.cpp:114
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserve()
Mark an analysis as preserved.
Definition Analysis.h:132
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:390
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
const ParentTy * getParent() const
Definition ilist_node.h:34
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
TargetTransformInfo TTI
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI FunctionPass * createPartiallyInlineLibCallsPass()
LLVM_ABI Instruction * SplitBlockAndInsertIfThen(Value *Cond, BasicBlock::iterator SplitBefore, bool Unreachable, MDNode *BranchWeights=nullptr, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry &)