LLVM  14.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 
19 #include "llvm/IR/Dominators.h"
20 #include "llvm/IR/IRBuilder.h"
21 #include "llvm/InitializePasses.h"
23 #include "llvm/Transforms/Scalar.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "partially-inline-libcalls"
29 
30 DEBUG_COUNTER(PILCounter, "partially-inline-libcalls-transform",
31  "Controls transformations in partially-inline-libcalls");
32 
33 static bool optimizeSQRT(CallInst *Call, Function *CalledFunc,
35  const TargetTransformInfo *TTI, DomTreeUpdater *DTU) {
36  // There is no need to change the IR, since backend will emit sqrt
37  // instruction if the call has already been marked read-only.
38  if (Call->onlyReadsMemory())
39  return false;
40 
41  if (!DebugCounter::shouldExecute(PILCounter))
42  return false;
43 
44  // Do the following transformation:
45  //
46  // (before)
47  // dst = sqrt(src)
48  //
49  // (after)
50  // v0 = sqrt_noreadmem(src) # native sqrt instruction.
51  // [if (v0 is a NaN) || if (src < 0)]
52  // v1 = sqrt(src) # library call.
53  // dst = phi(v0, v1)
54  //
55 
56  Type *Ty = Call->getType();
57  IRBuilder<> Builder(Call->getNextNode());
58 
59  // Split CurrBB right after the call, create a 'then' block (that branches
60  // back to split-off tail of CurrBB) into which we'll insert a libcall.
62  Builder.getTrue(), Call->getNextNode(), /*Unreachable=*/false,
63  /*BranchWeights*/ nullptr, DTU);
64 
65  auto *CurrBBTerm = cast<BranchInst>(CurrBB.getTerminator());
66  // We want an 'else' block though, not a 'then' block.
67  cast<BranchInst>(CurrBBTerm)->swapSuccessors();
68 
69  // Create phi that will merge results of either sqrt and replace all uses.
70  BasicBlock *JoinBB = LibCallTerm->getSuccessor(0);
71  JoinBB->setName(CurrBB.getName() + ".split");
72  Builder.SetInsertPoint(JoinBB, JoinBB->begin());
73  PHINode *Phi = Builder.CreatePHI(Ty, 2);
74  Call->replaceAllUsesWith(Phi);
75 
76  // Finally, insert the libcall into 'else' block.
77  BasicBlock *LibCallBB = LibCallTerm->getParent();
78  LibCallBB->setName("call.sqrt");
79  Builder.SetInsertPoint(LibCallTerm);
80  Instruction *LibCall = Call->clone();
81  Builder.Insert(LibCall);
82 
83  // Add attribute "readnone" so that backend can use a native sqrt instruction
84  // for this call.
85  Call->addFnAttr(Attribute::ReadNone);
86 
87  // Insert a FP compare instruction and use it as the CurrBB branch condition.
88  Builder.SetInsertPoint(CurrBBTerm);
90  ? Builder.CreateFCmpORD(Call, Call)
91  : Builder.CreateFCmpOGE(Call->getOperand(0),
92  ConstantFP::get(Ty, 0.0));
93  CurrBBTerm->setCondition(FCmp);
94 
95  // Add phi operands.
96  Phi->addIncoming(Call, &CurrBB);
97  Phi->addIncoming(LibCall, LibCallBB);
98 
99  BB = JoinBB->getIterator();
100  return true;
101 }
102 
104  const TargetTransformInfo *TTI,
105  DominatorTree *DT) {
107  if (DT)
109 
110  bool Changed = false;
111 
112  Function::iterator CurrBB;
113  for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE;) {
114  CurrBB = BB++;
115 
116  for (BasicBlock::iterator II = CurrBB->begin(), IE = CurrBB->end();
117  II != IE; ++II) {
118  CallInst *Call = dyn_cast<CallInst>(&*II);
119  Function *CalledFunc;
120 
121  if (!Call || !(CalledFunc = Call->getCalledFunction()))
122  continue;
123 
124  if (Call->isNoBuiltin() || Call->isStrictFP())
125  continue;
126 
127  // Skip if function either has local linkage or is not a known library
128  // function.
129  LibFunc LF;
130  if (CalledFunc->hasLocalLinkage() ||
131  !TLI->getLibFunc(*CalledFunc, LF) || !TLI->has(LF))
132  continue;
133 
134  switch (LF) {
135  case LibFunc_sqrtf:
136  case LibFunc_sqrt:
137  if (TTI->haveFastSqrt(Call->getType()) &&
138  optimizeSQRT(Call, CalledFunc, *CurrBB, BB, TTI,
139  DTU.hasValue() ? DTU.getPointer() : nullptr))
140  break;
141  continue;
142  default:
143  continue;
144  }
145 
146  Changed = true;
147  break;
148  }
149  }
150 
151  return Changed;
152 }
153 
156  auto &TLI = AM.getResult<TargetLibraryAnalysis>(F);
157  auto &TTI = AM.getResult<TargetIRAnalysis>(F);
158  auto *DT = AM.getCachedResult<DominatorTreeAnalysis>(F);
159  if (!runPartiallyInlineLibCalls(F, &TLI, &TTI, DT))
160  return PreservedAnalyses::all();
163  return PA;
164 }
165 
166 namespace {
167 class PartiallyInlineLibCallsLegacyPass : public FunctionPass {
168 public:
169  static char ID;
170 
171  PartiallyInlineLibCallsLegacyPass() : FunctionPass(ID) {
174  }
175 
176  void getAnalysisUsage(AnalysisUsage &AU) const override {
181  }
182 
183  bool runOnFunction(Function &F) override {
184  if (skipFunction(F))
185  return false;
186 
187  TargetLibraryInfo *TLI =
188  &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
189  const TargetTransformInfo *TTI =
190  &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
191  DominatorTree *DT = nullptr;
192  if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
193  DT = &DTWP->getDomTree();
194  return runPartiallyInlineLibCalls(F, TLI, TTI, DT);
195  }
196 };
197 }
198 
200 INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass,
201  "partially-inline-libcalls",
202  "Partially inline calls to library functions", false,
203  false)
207 INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass,
208  "partially-inline-libcalls",
210 
212  return new PartiallyInlineLibCallsLegacyPass();
213 }
llvm::PreservedAnalyses
A set of analyses that are preserved following a run of a transformation pass.
Definition: PassManager.h:155
llvm::TargetIRAnalysis
Analysis pass providing the TargetTransformInfo.
Definition: TargetTransformInfo.h:2331
libcalls
partially inline libcalls
Definition: PartiallyInlineLibCalls.cpp:208
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::BasicBlock::iterator
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:90
llvm::AnalysisManager::getResult
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Definition: PassManager.h:779
Scalar.h
llvm::Function
Definition: Function.h:61
llvm::TargetTransformInfo
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Definition: TargetTransformInfo.h:168
llvm::IRBuilder<>
DomTreeUpdater.h
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:151
to
Should compile to
Definition: README.txt:449
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::Optional
Definition: APInt.h:33
PartiallyInlineLibCalls.h
runPartiallyInlineLibCalls
static bool runPartiallyInlineLibCalls(Function &F, TargetLibraryInfo *TLI, const TargetTransformInfo *TTI, DominatorTree *DT)
Definition: PartiallyInlineLibCalls.cpp:103
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::DomTreeUpdater::UpdateStrategy::Lazy
@ Lazy
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
llvm::Optional::getPointer
constexpr const T * getPointer() const
Definition: Optional.h:280
llvm::Optional::hasValue
constexpr bool hasValue() const
Definition: Optional.h:288
llvm::PassRegistry::getPassRegistry
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Definition: PassRegistry.cpp:31
llvm::LibFunc
LibFunc
Definition: TargetLibraryInfo.h:34
llvm::BasicBlock::begin
iterator begin()
Instruction iterator methods.
Definition: BasicBlock.h:296
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
TargetLibraryInfo.h
false
Definition: StackSlotColoring.cpp:142
functions
partially inline Partially calls to library functions
Definition: PartiallyInlineLibCalls.cpp:209
llvm::TargetLibraryInfo::getLibFunc
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
Definition: TargetLibraryInfo.h:289
llvm::Instruction
Definition: Instruction.h:45
llvm::DebugCounter::shouldExecute
static bool shouldExecute(unsigned CounterName)
Definition: DebugCounter.h:74
llvm::DominatorTreeWrapperPass
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:287
llvm::Value::setName
void setName(const Twine &Name)
Change the name of the value.
Definition: Value.cpp:376
llvm::DomTreeUpdater
Definition: DomTreeUpdater.h:28
llvm::Instruction::getSuccessor
BasicBlock * getSuccessor(unsigned Idx) const
Return the specified successor. This instruction must be a terminator.
Definition: Instruction.cpp:777
llvm::TargetTransformInfo::isFCmpOrdCheaperThanFCmpZero
bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) const
Return true if it is faster to check if a floating-point value is NaN (or not-NaN) versus a compariso...
Definition: TargetTransformInfo.cpp:535
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(PartiallyInlineLibCallsLegacyPass, "partially-inline-libcalls", "Partially inline calls to library functions", false, false) INITIALIZE_PASS_END(PartiallyInlineLibCallsLegacyPass
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
DEBUG_COUNTER
DEBUG_COUNTER(PILCounter, "partially-inline-libcalls-transform", "Controls transformations in partially-inline-libcalls")
llvm::TargetTransformInfo::haveFastSqrt
bool haveFastSqrt(Type *Ty) const
Return true if the hardware has a fast square-root instruction.
Definition: TargetTransformInfo.cpp:531
llvm::ARM_PROC::IE
@ IE
Definition: ARMBaseInfo.h:27
optimizeSQRT
static bool optimizeSQRT(CallInst *Call, Function *CalledFunc, BasicBlock &CurrBB, Function::iterator &BB, const TargetTransformInfo *TTI, DomTreeUpdater *DTU)
Definition: PartiallyInlineLibCalls.cpp:33
llvm::TargetLibraryInfoWrapperPass
Definition: TargetLibraryInfo.h:463
llvm::TargetTransformInfoWrapperPass
Wrapper pass for TargetTransformInfo.
Definition: TargetTransformInfo.h:2387
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
llvm::PreservedAnalyses::preserve
void preserve()
Mark an analysis as preserved.
Definition: PassManager.h:176
llvm::PHINode::addIncoming
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Definition: Instructions.h:2783
llvm::Optional::emplace
void emplace(ArgTypes &&... Args)
Create a new object by constructing it in place with the given arguments.
Definition: Optional.h:264
llvm::createPartiallyInlineLibCallsPass
FunctionPass * createPartiallyInlineLibCallsPass()
Definition: PartiallyInlineLibCalls.cpp:211
inline
into xmm2 addss xmm2 xmm1 xmm3 addss xmm3 movaps xmm0 unpcklps xmm0 ret seems silly when it could just be one addps Expand libm rounding functions inline
Definition: README-SSE.txt:72
IRBuilder.h
llvm::GlobalValue::hasLocalLinkage
bool hasLocalLinkage() const
Definition: GlobalValue.h:445
llvm::TargetLibraryInfo::has
bool has(LibFunc F) const
Tests whether a library function is available.
Definition: TargetLibraryInfo.h:323
Builder
assume Assume Builder
Definition: AssumeBundleBuilder.cpp:651
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition: PassAnalysisSupport.h:98
library
Itanium Name Demangler i e convert the string _Z1fv into but neither can depend on each other libcxxabi needs the demangler to implement which is part of the itanium ABI spec LLVM needs a copy for a bunch of but doesn t want to use the system s __cxa_demangle because it a might not be and b probably isn t that up to date on the latest language features The copy of the demangler in LLVM has some extra stuff that aren t needed in which depend on the shared generic components Despite these we want to keep the core generic demangling library identical between both copies to simplify development and testing If you re working on the generic library
Definition: README.txt:30
llvm::ilist_node_impl::getIterator
self_iterator getIterator()
Definition: ilist_node.h:81
llvm::Value::getName
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
llvm::BasicBlock::getTerminator
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.cpp:148
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::PreservedAnalyses::all
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: PassManager.h:161
llvm::ConstantFP::get
static Constant * get(Type *Ty, double V)
This returns a ConstantFP, or a vector containing a splat of a ConstantFP, for the specified value in...
Definition: Constants.cpp:947
llvm::AnalysisManager::getCachedResult
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
Definition: PassManager.h:798
DebugCounter.h
llvm::TargetLibraryInfo
Provides information about what library functions are available for the current target.
Definition: TargetLibraryInfo.h:219
llvm::initializePartiallyInlineLibCallsLegacyPassPass
void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry &)
llvm::DominatorTreeAnalysis
Analysis pass which computes a DominatorTree.
Definition: Dominators.h:252
Dominators.h
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:94
TargetTransformInfo.h
llvm::PHINode
Definition: Instructions.h:2633
calls
amdgpu Simplify well known AMD library calls
Definition: AMDGPULibCalls.cpp:199
llvm::Pass::getAnalysisUsage
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:93
llvm::AnalysisManager
A container for analyses that lazily runs them and caches their results.
Definition: InstructionSimplify.h:44
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1475
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::SplitBlockAndInsertIfThen
Instruction * SplitBlockAndInsertIfThen(Value *Cond, Instruction *SplitBefore, bool Unreachable, MDNode *BranchWeights, DominatorTree *DT, LoopInfo *LI=nullptr, BasicBlock *ThenBlock=nullptr)
Split the containing block at the specified instruction - everything before SplitBefore stays in the ...
Definition: BasicBlockUtils.cpp:1418
llvm::PartiallyInlineLibCallsPass::run
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition: PartiallyInlineLibCalls.cpp:155
BasicBlockUtils.h
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::TargetLibraryAnalysis
Analysis pass providing the TargetLibraryInfo.
Definition: TargetLibraryInfo.h:438
llvm::Function::iterator
BasicBlockListType::iterator iterator
Definition: Function.h:67
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37