LLVM: lib/Transforms/Utils/LibCallsShrinkWrap.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
42
43#include
44
45using namespace llvm;
46
47#define DEBUG_TYPE "libcalls-shrinkwrap"
48
49STATISTIC(NumWrappedOneCond, "Number of One-Condition Wrappers Inserted");
50STATISTIC(NumWrappedTwoCond, "Number of Two-Condition Wrappers Inserted");
51
52namespace {
53class LibCallsShrinkWrap : public InstVisitor {
54public:
56 : TLI(TLI), DTU(DTU){};
57 void visitCallInst(CallInst &CI) { checkCandidate(CI); }
58 bool perform() {
60 for (auto &CI : WorkList) {
61 LLVM_DEBUG(dbgs() << "CDCE calls: " << CI->getCalledFunction()->getName()
62 << "\n");
63 if (perform(CI)) {
66 }
67 }
69 }
70
71private:
72 bool perform(CallInst *CI);
73 void checkCandidate(CallInst &CI);
74 void shrinkWrapCI(CallInst *CI, Value *Cond);
75 bool performCallDomainErrorOnly(CallInst *CI, const LibFunc &Func);
76 bool performCallErrors(CallInst *CI, const LibFunc &Func);
77 bool performCallRangeErrorOnly(CallInst *CI, const LibFunc &Func);
78 Value *generateOneRangeCond(CallInst *CI, const LibFunc &Func);
79 Value *generateTwoRangeCond(CallInst *CI, const LibFunc &Func);
80 Value *generateCondForPow(CallInst *CI, const LibFunc &Func);
81
82
85 float Val2) {
87 auto Cond2 = createCond(BBBuilder, Arg2, Cmp2, Val2);
88 auto Cond1 = createCond(BBBuilder, Arg, Cmp, Val);
89 return BBBuilder.CreateOr(Cond1, Cond2);
90 }
91
92
96 return createOrCond(CI, Arg, Cmp, Val, Arg, Cmp2, Val2);
97 }
98
99
101 float Val) {
107 return BBBuilder.CreateFCmp(Cmp, Arg, V);
108 }
109
110
112 float Val) {
114 return createCond(BBBuilder, Arg, Cmp, Val);
115 }
116
117
120 return createCond(CI, Arg, Cmp, Val);
121 }
122
123 const TargetLibraryInfo &TLI;
124 DomTreeUpdater &DTU;
126};
127}
128
129
130bool LibCallsShrinkWrap::performCallDomainErrorOnly(CallInst *CI,
131 const LibFunc &Func) {
133
134 switch (Func) {
135 case LibFunc_acos:
136 case LibFunc_acosf:
137 case LibFunc_acosl:
138 case LibFunc_asin:
139 case LibFunc_asinf:
140 case LibFunc_asinl:
141 {
142 ++NumWrappedTwoCond;
144 break;
145 }
146 case LibFunc_cos:
147 case LibFunc_cosf:
148 case LibFunc_cosl:
149 case LibFunc_sin:
150 case LibFunc_sinf:
151 case LibFunc_sinl:
152 {
153 ++NumWrappedTwoCond;
155 -INFINITY);
156 break;
157 }
158 case LibFunc_acosh:
159 case LibFunc_acoshf:
160 case LibFunc_acoshl:
161 {
162 ++NumWrappedOneCond;
164 break;
165 }
166 case LibFunc_sqrt:
167 case LibFunc_sqrtf:
168 case LibFunc_sqrtl:
169 {
170 ++NumWrappedOneCond;
172 break;
173 }
174 default:
175 return false;
176 }
177 shrinkWrapCI(CI, Cond);
178 return true;
179}
180
181
182bool LibCallsShrinkWrap::performCallRangeErrorOnly(CallInst *CI,
183 const LibFunc &Func) {
185
186 switch (Func) {
187 case LibFunc_cosh:
188 case LibFunc_coshf:
189 case LibFunc_coshl:
190 case LibFunc_exp:
191 case LibFunc_expf:
192 case LibFunc_expl:
193 case LibFunc_exp10:
194 case LibFunc_exp10f:
195 case LibFunc_exp10l:
196 case LibFunc_exp2:
197 case LibFunc_exp2f:
198 case LibFunc_exp2l:
199 case LibFunc_sinh:
200 case LibFunc_sinhf:
201 case LibFunc_sinhl: {
202 Cond = generateTwoRangeCond(CI, Func);
203 break;
204 }
205 case LibFunc_expm1:
206 case LibFunc_expm1f:
207 case LibFunc_expm1l:
208 {
209 Cond = generateOneRangeCond(CI, Func);
210 break;
211 }
212 default:
213 return false;
214 }
215 shrinkWrapCI(CI, Cond);
216 return true;
217}
218
219
220bool LibCallsShrinkWrap::performCallErrors(CallInst *CI,
221 const LibFunc &Func) {
223
224 switch (Func) {
225 case LibFunc_atanh:
226
227
228 case LibFunc_atanhf:
229 case LibFunc_atanhl:
230 {
231 ++NumWrappedTwoCond;
233 break;
234 }
235 case LibFunc_log:
236
237
238 case LibFunc_logf:
239 case LibFunc_logl:
240 case LibFunc_log10:
241 case LibFunc_log10f:
242 case LibFunc_log10l:
243 case LibFunc_log2:
244 case LibFunc_log2f:
245 case LibFunc_log2l:
246 case LibFunc_logb:
247 case LibFunc_logbf:
248 case LibFunc_logbl:
249 {
250 ++NumWrappedOneCond;
252 break;
253 }
254 case LibFunc_log1p:
255
256
257 case LibFunc_log1pf:
258 case LibFunc_log1pl:
259 {
260 ++NumWrappedOneCond;
262 break;
263 }
264 case LibFunc_pow:
265
266
267 case LibFunc_powf:
268 case LibFunc_powl: {
269 Cond = generateCondForPow(CI, Func);
270 if (Cond == nullptr)
271 return false;
272 break;
273 }
274 default:
275 return false;
276 }
277 assert(Cond && "performCallErrors should not see an empty condition");
278 shrinkWrapCI(CI, Cond);
279 return true;
280}
281
282
283
284void LibCallsShrinkWrap::checkCandidate(CallInst &CI) {
286 return;
287
288
289
290
292 return;
293
294 LibFunc Func;
296 if (!Callee)
297 return;
298 if (!TLI.getLibFunc(*Callee, Func) || !TLI.has(Func))
299 return;
300
302 return;
303
307 return;
308
309 WorkList.push_back(&CI);
310}
311
312
313Value *LibCallsShrinkWrap::generateOneRangeCond(CallInst *CI,
314 const LibFunc &Func) {
315 float UpperBound;
316 switch (Func) {
317 case LibFunc_expm1:
318 UpperBound = 709.0f;
319 break;
320 case LibFunc_expm1f:
321 UpperBound = 88.0f;
322 break;
323 case LibFunc_expm1l:
324 UpperBound = 11356.0f;
325 break;
326 default:
328 }
329
330 ++NumWrappedOneCond;
332}
333
334
335Value *LibCallsShrinkWrap::generateTwoRangeCond(CallInst *CI,
336 const LibFunc &Func) {
337 float UpperBound, LowerBound;
338 switch (Func) {
339 case LibFunc_cosh:
340 case LibFunc_sinh:
341 LowerBound = -710.0f;
342 UpperBound = 710.0f;
343 break;
344 case LibFunc_coshf:
345 case LibFunc_sinhf:
346 LowerBound = -89.0f;
347 UpperBound = 89.0f;
348 break;
349 case LibFunc_coshl:
350 case LibFunc_sinhl:
351 LowerBound = -11357.0f;
352 UpperBound = 11357.0f;
353 break;
354 case LibFunc_exp:
355 LowerBound = -745.0f;
356 UpperBound = 709.0f;
357 break;
358 case LibFunc_expf:
359 LowerBound = -103.0f;
360 UpperBound = 88.0f;
361 break;
362 case LibFunc_expl:
363 LowerBound = -11399.0f;
364 UpperBound = 11356.0f;
365 break;
366 case LibFunc_exp10:
367 LowerBound = -323.0f;
368 UpperBound = 308.0f;
369 break;
370 case LibFunc_exp10f:
371 LowerBound = -45.0f;
372 UpperBound = 38.0f;
373 break;
374 case LibFunc_exp10l:
375 LowerBound = -4950.0f;
376 UpperBound = 4932.0f;
377 break;
378 case LibFunc_exp2:
379 LowerBound = -1074.0f;
380 UpperBound = 1023.0f;
381 break;
382 case LibFunc_exp2f:
383 LowerBound = -149.0f;
384 UpperBound = 127.0f;
385 break;
386 case LibFunc_exp2l:
387 LowerBound = -16445.0f;
388 UpperBound = 11383.0f;
389 break;
390 default:
392 }
393
394 ++NumWrappedTwoCond;
396 LowerBound);
397}
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414Value *LibCallsShrinkWrap::generateCondForPow(CallInst *CI,
415 const LibFunc &Func) {
416
417 if (Func != LibFunc_pow) {
418 LLVM_DEBUG(dbgs() << "Not handled powf() and powl()\n");
419 return nullptr;
420 }
421
424
425
427 double D = CF->getValueAPF().convertToDouble();
429 LLVM_DEBUG(dbgs() << "Not handled pow(): constant base out of range\n");
430 return nullptr;
431 }
432
433 ++NumWrappedOneCond;
435 }
436
437
439 if () {
440 LLVM_DEBUG(dbgs() << "Not handled pow(): FP type base\n");
441 return nullptr;
442 }
443 unsigned Opcode = I->getOpcode();
444 if (Opcode == Instruction::UIToFP || Opcode == Instruction::SIToFP) {
445 unsigned BW = I->getOperand(0)->getType()->getPrimitiveSizeInBits();
446 float UpperV = 0.0f;
447 if (BW == 8)
448 UpperV = 128.0f;
449 else if (BW == 16)
450 UpperV = 64.0f;
451 else if (BW == 32)
452 UpperV = 32.0f;
453 else {
454 LLVM_DEBUG(dbgs() << "Not handled pow(): type too wide\n");
455 return nullptr;
456 }
457
458 ++NumWrappedTwoCond;
461 }
462 LLVM_DEBUG(dbgs() << "Not handled pow(): base not from integer convert\n");
463 return nullptr;
464}
465
466
467void LibCallsShrinkWrap::shrinkWrapCI(CallInst *CI, Value *Cond) {
468 assert(Cond != nullptr && "ShrinkWrapCI is not expecting an empty call inst");
469 MDNode *BranchWeights =
470 MDBuilder(CI->getContext()).createUnlikelyBranchWeights();
471
475 CallBB->setName("cdce.call");
477 assert(SuccBB && "The split block should have a single successor");
478 SuccBB->setName("cdce.end");
484}
485
486
487bool LibCallsShrinkWrap::perform(CallInst *CI) {
488 LibFunc Func;
490 assert(Callee && "perform() should apply to a non-empty callee");
492 assert(Func && "perform() is not expecting an empty function");
493
494 if (performCallDomainErrorOnly(CI, Func) || performCallRangeErrorOnly(CI, Func))
495 return true;
496 return performCallErrors(CI, Func);
497}
498
501 if (F.hasOptSize())
502 return false;
503 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
504 LibCallsShrinkWrap CCDCE(TLI, DTU);
505 CCDCE.visit(F);
506 bool Changed = CCDCE.perform();
507
508
510 DTU.getDomTree().verify(DominatorTree::VerificationLevel::Fast));
512}
513
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runImpl(Function &F, const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)
This is the interface for a simple mod/ref and alias analysis over globals.
FunctionAnalysisManager FAM
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static APInt getMaxValue(unsigned numBits)
Gets maximum unsigned value of APInt for specific bit width.
LLVM_ABI const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
bool isNoBuiltin() const
Return true if the call should not be treated as a call to a builtin.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
Value * getArgOperand(unsigned i) const
This class represents a function call, abstracting a target machine's calling convention.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
Analysis pass which computes a DominatorTree.
bool verify(VerificationLevel VL=VerificationLevel::Full) const
verify - checks if the tree is correct.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
DomTreeT & getDomTree()
Flush DomTree updates and return DomTree.
Value * CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)
BasicBlock * GetInsertBlock() const
void setIsFPConstrained(bool IsCon)
Enable/Disable use of constrained floating point math.
LLVMContext & getContext() const
Base class for instruction visitors.
LLVM_ABI void removeFromParent()
This method unlinks 'this' from the containing basic block, but does not delete it.
LLVM_ABI InstListType::iterator insertInto(BasicBlock *ParentBB, InstListType::iterator It)
Inserts an unlinked instruction into ParentBB at position It and returns the iterator of the inserted...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
Definition LibCallsShrinkWrap.cpp:514
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
bool has(LibFunc F) const
Tests whether a library function is available.
bool getLibFunc(StringRef funcName, LibFunc &F) const
Searches for a particular function name.
bool isX86_FP80Ty() const
Return true if this is x86 long double.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BasicBlock
Various leaf nodes.
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI Constant * ConstantFoldCastInstruction(unsigned opcode, Constant *V, Type *DestTy)
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.