LLVM 24.0.0git
AMDGPULibCalls.cpp
Go to the documentation of this file.
1//===- AMDGPULibCalls.cpp -------------------------------------------------===//
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/// \file
10/// This file does AMD library function optimizations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "AMDGPU.h"
15#include "AMDGPULibFunc.h"
20#include "llvm/IR/Dominators.h"
21#include "llvm/IR/IRBuilder.h"
22#include "llvm/IR/MDBuilder.h"
24#include <cmath>
25
26#define DEBUG_TYPE "amdgpu-simplifylib"
27
28using namespace llvm;
29using namespace llvm::PatternMatch;
30
31static cl::opt<bool> EnablePreLink("amdgpu-prelink",
32 cl::desc("Enable pre-link mode optimizations"),
33 cl::init(false),
35
36static cl::list<std::string> UseNative("amdgpu-use-native",
37 cl::desc("Comma separated list of functions to replace with native, or all"),
40
41#define MATH_PI numbers::pi
42#define MATH_E numbers::e
43#define MATH_SQRT2 numbers::sqrt2
44#define MATH_SQRT1_2 numbers::inv_sqrt2
45
46enum class PowKind { Pow, PowR, PowN, RootN };
47
48namespace llvm {
49
51private:
53
54 using FuncInfo = llvm::AMDGPULibFunc;
55
56 // -fuse-native.
57 bool AllNative = false;
58
59 bool useNativeFunc(const StringRef F) const;
60
61 // Return a pointer (pointer expr) to the function if function definition with
62 // "FuncName" exists. It may create a new function prototype in pre-link mode.
63 FunctionCallee getFunction(Module *M, const FuncInfo &fInfo);
64
65 /// Wrapper around getFunction which tries to use a faster variant if
66 /// available, and falls back to a less fast option.
67 ///
68 /// Return a replacement function for \p fInfo that has float-typed fast
69 /// variants. \p NewFunc is a base replacement function to use. \p
70 /// NewFuncFastVariant is a faster version to use if the calling context knows
71 /// it's legal. If there is no fast variant to use, \p NewFuncFastVariant
72 /// should be EI_NONE.
73 FunctionCallee getFloatFastVariant(Module *M, const FuncInfo &fInfo,
74 FuncInfo &newInfo,
76 AMDGPULibFunc::EFuncId NewFuncFastVariant);
77
78 bool parseFunctionName(const StringRef &FMangledName, FuncInfo &FInfo);
79
80 bool TDOFold(CallInst *CI, const FuncInfo &FInfo);
81
82 /* Specialized optimizations */
83
84 // pow/powr/pown
85 bool fold_pow(FPMathOperator *FPOp, IRBuilder<> &B, const FuncInfo &FInfo);
86
87 /// Peform a fast math expansion of pow, powr, pown or rootn.
88 bool expandFastPow(FPMathOperator *FPOp, IRBuilder<> &B, PowKind Kind);
89
90 bool tryOptimizePow(FPMathOperator *FPOp, IRBuilder<> &B,
91 const FuncInfo &FInfo);
92
93 // rootn
94 bool fold_rootn(FPMathOperator *FPOp, IRBuilder<> &B, const FuncInfo &FInfo);
95
96 // -fuse-native for sincos
97 bool sincosUseNative(CallInst *aCI, const FuncInfo &FInfo);
98
99 // evaluate calls if calls' arguments are constants.
100 bool evaluateScalarMathFunc(const FuncInfo &FInfo, APFloat &Res0,
101 APFloat &Res1, Constant *copr0, Constant *copr1);
102 bool evaluateCall(CallInst *aCI, const FuncInfo &FInfo);
103
104 /// Insert a value to sincos function \p Fsincos. Returns (value of sin, value
105 /// of cos, sincos call).
106 std::tuple<Value *, Value *, Value *> insertSinCos(Value *Arg,
107 FastMathFlags FMF,
108 IRBuilder<> &B,
109 FunctionCallee Fsincos);
110
111 // sin/cos
112 bool fold_sincos(FPMathOperator *FPOp, IRBuilder<> &B, const FuncInfo &FInfo);
113
114 // __read_pipe/__write_pipe
115 bool fold_read_write_pipe(CallInst *CI, IRBuilder<> &B,
116 const FuncInfo &FInfo);
117
118 /// Substitute a call to a known libcall with an intrinsic call. If \p
119 /// AllowMinSize is true, allow the replacement in a minsize function.
120 bool shouldReplaceLibcallWithIntrinsic(const CallInst *CI,
121 bool AllowMinSizeF32 = false,
122 bool AllowF64 = false,
123 bool AllowStrictFP = false);
124 void replaceLibCallWithSimpleIntrinsic(IRBuilder<> &B, CallInst *CI,
125 Intrinsic::ID IntrID);
126
127 bool tryReplaceLibcallWithSimpleIntrinsic(IRBuilder<> &B, CallInst *CI,
128 Intrinsic::ID IntrID,
129 bool AllowMinSizeF32 = false,
130 bool AllowF64 = false,
131 bool AllowStrictFP = false);
132
133protected:
134 bool isUnsafeFiniteOnlyMath(const FPMathOperator *FPOp) const;
135
137
138 static void replaceCall(Instruction *I, Value *With) {
139 I->replaceAllUsesWith(With);
140 I->eraseFromParent();
141 }
142
143 static void replaceCall(FPMathOperator *I, Value *With) {
145 }
146
147public:
149
150 bool fold(CallInst *CI);
151
152 void initNativeFuncs();
153
154 // Replace a normal math function call with that native version
155 bool useNative(CallInst *CI);
156};
157
158} // end namespace llvm
159
160template <typename IRB>
161static CallInst *CreateCallEx(IRB &B, FunctionCallee Callee, Value *Arg,
162 const Twine &Name = "") {
163 CallInst *R = B.CreateCall(Callee, Arg, Name);
164 if (Function *F = dyn_cast<Function>(Callee.getCallee()))
165 R->setCallingConv(F->getCallingConv());
166 return R;
167}
168
169template <typename IRB>
170static CallInst *CreateCallEx2(IRB &B, FunctionCallee Callee, Value *Arg1,
171 Value *Arg2, const Twine &Name = "") {
172 CallInst *R = B.CreateCall(Callee, {Arg1, Arg2}, Name);
173 if (Function *F = dyn_cast<Function>(Callee.getCallee()))
174 R->setCallingConv(F->getCallingConv());
175 return R;
176}
177
179 Type *PowNExpTy = Type::getInt32Ty(FT->getContext());
180 if (VectorType *VecTy = dyn_cast<VectorType>(FT->getReturnType()))
181 PowNExpTy = VectorType::get(PowNExpTy, VecTy->getElementCount());
182
183 return FunctionType::get(FT->getReturnType(),
184 {FT->getParamType(0), PowNExpTy}, false);
185}
186
187// Data structures for table-driven optimizations.
188// FuncTbl works for both f32 and f64 functions with 1 input argument
189
191 double result;
192 double input;
193};
194
195/* a list of {result, input} */
196static const TableEntry tbl_acos[] = {
197 {MATH_PI / 2.0, 0.0},
198 {MATH_PI / 2.0, -0.0},
199 {0.0, 1.0},
200 {MATH_PI, -1.0}
201};
202static const TableEntry tbl_acosh[] = {
203 {0.0, 1.0}
204};
205static const TableEntry tbl_acospi[] = {
206 {0.5, 0.0},
207 {0.5, -0.0},
208 {0.0, 1.0},
209 {1.0, -1.0}
210};
211static const TableEntry tbl_asin[] = {
212 {0.0, 0.0},
213 {-0.0, -0.0},
214 {MATH_PI / 2.0, 1.0},
215 {-MATH_PI / 2.0, -1.0}
216};
217static const TableEntry tbl_asinh[] = {
218 {0.0, 0.0},
219 {-0.0, -0.0}
220};
221static const TableEntry tbl_asinpi[] = {
222 {0.0, 0.0},
223 {-0.0, -0.0},
224 {0.5, 1.0},
225 {-0.5, -1.0}
226};
227static const TableEntry tbl_atan[] = {
228 {0.0, 0.0},
229 {-0.0, -0.0},
230 {MATH_PI / 4.0, 1.0},
231 {-MATH_PI / 4.0, -1.0}
232};
233static const TableEntry tbl_atanh[] = {
234 {0.0, 0.0},
235 {-0.0, -0.0}
236};
237static const TableEntry tbl_atanpi[] = {
238 {0.0, 0.0},
239 {-0.0, -0.0},
240 {0.25, 1.0},
241 {-0.25, -1.0}
242};
243static const TableEntry tbl_cbrt[] = {
244 {0.0, 0.0},
245 {-0.0, -0.0},
246 {1.0, 1.0},
247 {-1.0, -1.0},
248};
249static const TableEntry tbl_cos[] = {
250 {1.0, 0.0},
251 {1.0, -0.0}
252};
253static const TableEntry tbl_cosh[] = {
254 {1.0, 0.0},
255 {1.0, -0.0}
256};
257static const TableEntry tbl_cospi[] = {
258 {1.0, 0.0},
259 {1.0, -0.0}
260};
261static const TableEntry tbl_erfc[] = {
262 {1.0, 0.0},
263 {1.0, -0.0}
264};
265static const TableEntry tbl_erf[] = {
266 {0.0, 0.0},
267 {-0.0, -0.0}
268};
269static const TableEntry tbl_exp[] = {
270 {1.0, 0.0},
271 {1.0, -0.0},
272 {MATH_E, 1.0}
273};
274static const TableEntry tbl_exp2[] = {
275 {1.0, 0.0},
276 {1.0, -0.0},
277 {2.0, 1.0}
278};
279static const TableEntry tbl_exp10[] = {
280 {1.0, 0.0},
281 {1.0, -0.0},
282 {10.0, 1.0}
283};
284static const TableEntry tbl_expm1[] = {
285 {0.0, 0.0},
286 {-0.0, -0.0}
287};
288static const TableEntry tbl_log[] = {
289 {0.0, 1.0},
290 {1.0, MATH_E}
291};
292static const TableEntry tbl_log2[] = {
293 {0.0, 1.0},
294 {1.0, 2.0}
295};
296static const TableEntry tbl_log10[] = {
297 {0.0, 1.0},
298 {1.0, 10.0}
299};
300static const TableEntry tbl_rsqrt[] = {
301 {1.0, 1.0},
302 {MATH_SQRT1_2, 2.0}
303};
304static const TableEntry tbl_sin[] = {
305 {0.0, 0.0},
306 {-0.0, -0.0}
307};
308static const TableEntry tbl_sinh[] = {
309 {0.0, 0.0},
310 {-0.0, -0.0}
311};
312static const TableEntry tbl_sinpi[] = {
313 {0.0, 0.0},
314 {-0.0, -0.0}
315};
316static const TableEntry tbl_sqrt[] = {
317 {0.0, 0.0},
318 {1.0, 1.0},
319 {MATH_SQRT2, 2.0}
320};
321static const TableEntry tbl_tan[] = {
322 {0.0, 0.0},
323 {-0.0, -0.0}
324};
325static const TableEntry tbl_tanh[] = {
326 {0.0, 0.0},
327 {-0.0, -0.0}
328};
329static const TableEntry tbl_tanpi[] = {
330 {0.0, 0.0},
331 {-0.0, -0.0}
332};
333static const TableEntry tbl_tgamma[] = {
334 {1.0, 1.0},
335 {1.0, 2.0},
336 {2.0, 3.0},
337 {6.0, 4.0}
338};
339
341 switch(id) {
357 return true;
358 default:;
359 }
360 return false;
361}
362
364
366 switch(id) {
404 default:;
405 }
406 return TableRef();
407}
408
409static inline int getVecSize(const AMDGPULibFunc& FInfo) {
410 return FInfo.getLeads()[0].VectorSize;
411}
412
413static inline AMDGPULibFunc::EType getArgType(const AMDGPULibFunc& FInfo) {
414 return (AMDGPULibFunc::EType)FInfo.getLeads()[0].ArgType;
415}
416
417FunctionCallee AMDGPULibCalls::getFunction(Module *M, const FuncInfo &fInfo) {
418 // If we are doing PreLinkOpt, the function is external. So it is safe to
419 // use getOrInsertFunction() at this stage.
420
422 : AMDGPULibFunc::getFunction(M, fInfo);
423}
424
425FunctionCallee AMDGPULibCalls::getFloatFastVariant(
426 Module *M, const FuncInfo &fInfo, FuncInfo &newInfo,
427 AMDGPULibFunc::EFuncId NewFunc, AMDGPULibFunc::EFuncId FastVariant) {
428 assert(NewFunc != FastVariant);
429
430 if (FastVariant != AMDGPULibFunc::EI_NONE &&
431 getArgType(fInfo) == AMDGPULibFunc::F32) {
432 newInfo = AMDGPULibFunc(FastVariant, fInfo);
433 if (FunctionCallee NewCallee = getFunction(M, newInfo))
434 return NewCallee;
435 }
436
437 newInfo = AMDGPULibFunc(NewFunc, fInfo);
438 return getFunction(M, newInfo);
439}
440
441bool AMDGPULibCalls::parseFunctionName(const StringRef &FMangledName,
442 FuncInfo &FInfo) {
443 return AMDGPULibFunc::parse(FMangledName, FInfo);
444}
445
447 return FPOp->hasApproxFunc() && FPOp->hasNoNaNs() && FPOp->hasNoInfs();
448}
449
451 const FPMathOperator *FPOp) const {
452 // TODO: Refine to approxFunc or contract
453 return FPOp->isFast();
454}
455
457 : SQ(F.getDataLayout(), &FAM.getResult<TargetLibraryAnalysis>(F),
458 FAM.getCachedResult<DominatorTreeAnalysis>(F),
459 &FAM.getResult<AssumptionAnalysis>(F)) {}
460
461bool AMDGPULibCalls::useNativeFunc(const StringRef F) const {
462 return AllNative || llvm::is_contained(UseNative, F);
463}
464
466 AllNative = useNativeFunc("all") ||
467 (UseNative.getNumOccurrences() && UseNative.size() == 1 &&
468 UseNative.begin()->empty());
469}
470
471bool AMDGPULibCalls::sincosUseNative(CallInst *aCI, const FuncInfo &FInfo) {
472 bool native_sin = useNativeFunc("sin");
473 bool native_cos = useNativeFunc("cos");
474
475 if (native_sin && native_cos) {
476 Module *M = aCI->getModule();
477 Value *opr0 = aCI->getArgOperand(0);
478
479 AMDGPULibFunc nf;
480 nf.getLeads()[0].ArgType = FInfo.getLeads()[0].ArgType;
481 nf.getLeads()[0].VectorSize = FInfo.getLeads()[0].VectorSize;
482
485 FunctionCallee sinExpr = getFunction(M, nf);
486
489 FunctionCallee cosExpr = getFunction(M, nf);
490 if (sinExpr && cosExpr) {
491 Value *sinval =
492 CallInst::Create(sinExpr, opr0, "splitsin", aCI->getIterator());
493 Value *cosval =
494 CallInst::Create(cosExpr, opr0, "splitcos", aCI->getIterator());
495 new StoreInst(cosval, aCI->getArgOperand(1), aCI->getIterator());
496
497 DEBUG_WITH_TYPE("usenative", dbgs() << "<useNative> replace " << *aCI
498 << " with native version of sin/cos");
499
500 replaceCall(aCI, sinval);
501 return true;
502 }
503 }
504 return false;
505}
506
508 Function *Callee = aCI->getCalledFunction();
509 if (!Callee || aCI->isNoBuiltin())
510 return false;
511
512 FuncInfo FInfo;
513 if (!parseFunctionName(Callee->getName(), FInfo) || !FInfo.isMangled() ||
514 FInfo.getPrefix() != AMDGPULibFunc::NOPFX ||
515 getArgType(FInfo) == AMDGPULibFunc::F64 || !HasNative(FInfo.getId()) ||
516 !(AllNative || useNativeFunc(FInfo.getName()))) {
517 return false;
518 }
519
520 if (FInfo.getId() == AMDGPULibFunc::EI_SINCOS)
521 return sincosUseNative(aCI, FInfo);
522
524 FunctionCallee F = getFunction(aCI->getModule(), FInfo);
525 if (!F)
526 return false;
527
528 aCI->setCalledFunction(F);
529 DEBUG_WITH_TYPE("usenative", dbgs() << "<useNative> replace " << *aCI
530 << " with native version");
531 return true;
532}
533
534// Clang emits call of __read_pipe_2 or __read_pipe_4 for OpenCL read_pipe
535// builtin, with appended type size and alignment arguments, where 2 or 4
536// indicates the original number of arguments. The library has optimized version
537// of __read_pipe_2/__read_pipe_4 when the type size and alignment has the same
538// power of 2 value. This function transforms __read_pipe_2 to __read_pipe_2_N
539// for such cases where N is the size in bytes of the type (N = 1, 2, 4, 8, ...,
540// 128). The same for __read_pipe_4, write_pipe_2, and write_pipe_4.
541bool AMDGPULibCalls::fold_read_write_pipe(CallInst *CI, IRBuilder<> &B,
542 const FuncInfo &FInfo) {
543 auto *Callee = CI->getCalledFunction();
544 if (!Callee->isDeclaration())
545 return false;
546
547 assert(Callee->hasName() && "Invalid read_pipe/write_pipe function");
548 auto *M = Callee->getParent();
549 std::string Name = std::string(Callee->getName());
550 auto NumArg = CI->arg_size();
551 if (NumArg != 4 && NumArg != 6)
552 return false;
553 ConstantInt *PacketSize =
554 dyn_cast<ConstantInt>(CI->getArgOperand(NumArg - 2));
555 ConstantInt *PacketAlign =
556 dyn_cast<ConstantInt>(CI->getArgOperand(NumArg - 1));
557 if (!PacketSize || !PacketAlign)
558 return false;
559
560 unsigned Size = PacketSize->getZExtValue();
561 Align Alignment = PacketAlign->getAlignValue();
562 if (Alignment != Size)
563 return false;
564
565 unsigned PtrArgLoc = CI->arg_size() - 3;
566 Value *PtrArg = CI->getArgOperand(PtrArgLoc);
567 Type *PtrTy = PtrArg->getType();
568
570 for (unsigned I = 0; I != PtrArgLoc; ++I)
571 ArgTys.push_back(CI->getArgOperand(I)->getType());
572 ArgTys.push_back(PtrTy);
573
574 Name = Name + "_" + std::to_string(Size);
575 auto *FTy = FunctionType::get(Callee->getReturnType(),
576 ArrayRef<Type *>(ArgTys), false);
577 AMDGPULibFunc NewLibFunc(Name, FTy);
579 if (!F)
580 return false;
581
583 for (unsigned I = 0; I != PtrArgLoc; ++I)
584 Args.push_back(CI->getArgOperand(I));
585 Args.push_back(PtrArg);
586
587 auto *NCI = B.CreateCall(F, Args);
588 NCI->setAttributes(CI->getAttributes());
589 CI->replaceAllUsesWith(NCI);
590 CI->dropAllReferences();
591 CI->eraseFromParent();
592
593 return true;
594}
595
596// This function returns false if no change; return true otherwise.
598 Function *Callee = CI->getCalledFunction();
599 // Ignore indirect calls.
600 if (!Callee || Callee->isIntrinsic() || CI->isNoBuiltin())
601 return false;
602
603 FuncInfo FInfo;
604 if (!parseFunctionName(Callee->getName(), FInfo))
605 return false;
606
607 // Further check the number of arguments to see if they match.
608 // TODO: Check calling convention matches too
609 if (!FInfo.isCompatibleSignature(*Callee->getParent(), CI->getFunctionType()))
610 return false;
611
612 LLVM_DEBUG(dbgs() << "AMDIC: try folding " << *CI << '\n');
613
614 if (TDOFold(CI, FInfo))
615 return true;
616
617 IRBuilder<> B(CI);
618 if (CI->isStrictFP())
619 B.setIsFPConstrained(true);
620
622 // Under unsafe-math, evaluate calls if possible.
623 // According to Brian Sumner, we can do this for all f32 function calls
624 // using host's double function calls.
625 if (canIncreasePrecisionOfConstantFold(FPOp) && evaluateCall(CI, FInfo))
626 return true;
627
628 // Copy fast flags from the original call.
629 FastMathFlags FMF = FPOp->getFastMathFlags();
630 B.setFastMathFlags(FMF);
631
632 // Specialized optimizations for each function call.
633 //
634 // TODO: Handle native functions
635 switch (FInfo.getId()) {
637 if (FMF.none())
638 return false;
639 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::exp,
640 FMF.approxFunc());
642 if (FMF.none())
643 return false;
644 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::exp2,
645 FMF.approxFunc());
647 if (FMF.none())
648 return false;
649 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log,
650 FMF.approxFunc());
652 if (FMF.none())
653 return false;
654 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log2,
655 FMF.approxFunc());
657 if (FMF.none())
658 return false;
659 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log10,
660 FMF.approxFunc());
662 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::minnum,
663 true, true);
665 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::maxnum,
666 true, true);
668 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fma, true,
669 true);
671 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fmuladd,
672 true, true);
674 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fabs, true,
675 true, true);
677 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::copysign,
678 true, true, true);
680 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::floor, true,
681 true);
683 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::ceil, true,
684 true);
686 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::trunc, true,
687 true);
689 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::rint, true,
690 true);
692 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::round, true,
693 true);
695 if (!shouldReplaceLibcallWithIntrinsic(CI, true, true))
696 return false;
697
698 Value *Arg1 = CI->getArgOperand(1);
699 if (VectorType *VecTy = dyn_cast<VectorType>(CI->getType());
700 VecTy && !isa<VectorType>(Arg1->getType())) {
701 Value *SplatArg1 = B.CreateVectorSplat(VecTy->getElementCount(), Arg1);
702 CI->setArgOperand(1, SplatArg1);
703 }
704
706 CI->getModule(), Intrinsic::ldexp,
707 {CI->getType(), CI->getArgOperand(1)->getType()}));
709 return true;
710 }
713 return tryOptimizePow(FPOp, B, FInfo);
716 if (fold_pow(FPOp, B, FInfo))
717 return true;
718 if (!FMF.approxFunc())
719 return false;
720
721 if (FInfo.getId() == AMDGPULibFunc::EI_POWR && FMF.approxFunc() &&
722 getArgType(FInfo) == AMDGPULibFunc::F32) {
723 Module *M = Callee->getParent();
724 AMDGPULibFunc PowrFastInfo(AMDGPULibFunc::EI_POWR_FAST, FInfo);
725 if (FunctionCallee PowrFastFunc = getFunction(M, PowrFastInfo)) {
726 CI->setCalledFunction(PowrFastFunc);
727 return true;
728 }
729 }
730
731 if (!shouldReplaceLibcallWithIntrinsic(CI))
732 return false;
733 return expandFastPow(FPOp, B, PowKind::PowR);
734 }
737 if (fold_pow(FPOp, B, FInfo))
738 return true;
739 if (!FMF.approxFunc())
740 return false;
741
742 if (FInfo.getId() == AMDGPULibFunc::EI_POWN &&
743 getArgType(FInfo) == AMDGPULibFunc::F32) {
744 Module *M = Callee->getParent();
745 AMDGPULibFunc PownFastInfo(AMDGPULibFunc::EI_POWN_FAST, FInfo);
746 if (FunctionCallee PownFastFunc = getFunction(M, PownFastInfo)) {
747 CI->setCalledFunction(PownFastFunc);
748 return true;
749 }
750 }
751
752 if (!shouldReplaceLibcallWithIntrinsic(CI))
753 return false;
754 return expandFastPow(FPOp, B, PowKind::PowN);
755 }
758 if (fold_rootn(FPOp, B, FInfo))
759 return true;
760 if (!FMF.approxFunc())
761 return false;
762
763 if (getArgType(FInfo) == AMDGPULibFunc::F32) {
764 Module *M = Callee->getParent();
765 AMDGPULibFunc RootnFastInfo(AMDGPULibFunc::EI_ROOTN_FAST, FInfo);
766 if (FunctionCallee RootnFastFunc = getFunction(M, RootnFastInfo)) {
767 CI->setCalledFunction(RootnFastFunc);
768 return true;
769 }
770 }
771
772 return expandFastPow(FPOp, B, PowKind::RootN);
773 }
775 // TODO: Allow with strictfp + constrained intrinsic
776 return tryReplaceLibcallWithSimpleIntrinsic(
777 B, CI, Intrinsic::sqrt, true, true, /*AllowStrictFP=*/false);
780 return fold_sincos(FPOp, B, FInfo);
781 default:
782 break;
783 }
784 } else {
785 // Specialized optimizations for each function call
786 switch (FInfo.getId()) {
791 return fold_read_write_pipe(CI, B, FInfo);
792 default:
793 break;
794 }
795 }
796
797 return false;
798}
799
801 const Type *Ty) {
802
803 assert(Ty->isSingleValueType() &&
804 "Type must either be a scalar or a vector.");
805 assert((!Ty->isVectorTy() || Ty->isScalableTy() ||
806 Values.size() == cast<FixedVectorType>(Ty)->getNumElements()) &&
807 "Unexpected number of constant values.");
808 assert((Ty->isVectorTy() || Values.size() == 1) &&
809 "Expected exactly one constant value");
810
811 Type *ElemTy = Ty->getScalarType();
812 const fltSemantics &FltSem = ElemTy->getFltSemantics();
813
814 SmallVector<Constant *, 4> ConstValues;
815 ConstValues.reserve(Values.size());
816 for (APFloat APF : Values) {
817 bool Unused;
818 APF.convert(FltSem, APFloat::rmNearestTiesToEven, &Unused);
819 ConstValues.push_back(ConstantFP::get(ElemTy, APF));
820 }
821
822 return Ty->isVectorTy() ? ConstantVector::get(ConstValues) : ConstValues[0];
823}
824
825bool AMDGPULibCalls::TDOFold(CallInst *CI, const FuncInfo &FInfo) {
826 // Table-Driven optimization
827 const TableRef tr = getOptTable(FInfo.getId());
828 if (tr.empty())
829 return false;
830
831 int const sz = (int)tr.size();
832 Value *opr0 = CI->getArgOperand(0);
833
834 int vecSize = getVecSize(FInfo);
835 if (vecSize > 1) {
836 // Vector version
837 Constant *CV = dyn_cast<Constant>(opr0);
838 if (CV && CV->getType()->isVectorTy()) {
840 Values.reserve(vecSize);
841 for (int eltNo = 0; eltNo < vecSize; ++eltNo) {
842 // A lane may be undef or poison, in which case there is nothing to
843 // look up in the table.
845 CV->getAggregateElement((unsigned)eltNo));
846 if (!eltval)
847 return false;
848 auto MatchingRow = llvm::find_if(tr, [eltval](const TableEntry &entry) {
849 return eltval->isExactlyValue(entry.input);
850 });
851 if (MatchingRow == tr.end())
852 return false;
853 Values.push_back(APFloat(MatchingRow->result));
854 }
855 Constant *NewValues = getConstantFloat(Values, CI->getType());
856 LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *NewValues << "\n");
857 replaceCall(CI, NewValues);
858 return true;
859 }
860 } else {
861 // Scalar version
862 if (ConstantFP *CF = dyn_cast<ConstantFP>(opr0)) {
863 for (int i = 0; i < sz; ++i) {
864 if (CF->isExactlyValue(tr[i].input)) {
865 Value *nval = ConstantFP::get(CF->getType(), tr[i].result);
866 LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");
867 replaceCall(CI, nval);
868 return true;
869 }
870 }
871 }
872 }
873
874 return false;
875}
876
877namespace llvm {
878static double log2(double V) {
879#if _XOPEN_SOURCE >= 600 || defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
880 return ::log2(V);
881#else
882 return log(V) / numbers::ln2;
883#endif
884}
885} // namespace llvm
886
887bool AMDGPULibCalls::fold_pow(FPMathOperator *FPOp, IRBuilder<> &B,
888 const FuncInfo &FInfo) {
889 assert((FInfo.getId() == AMDGPULibFunc::EI_POW ||
890 FInfo.getId() == AMDGPULibFunc::EI_POW_FAST ||
891 FInfo.getId() == AMDGPULibFunc::EI_POWR ||
892 FInfo.getId() == AMDGPULibFunc::EI_POWR_FAST ||
893 FInfo.getId() == AMDGPULibFunc::EI_POWN ||
894 FInfo.getId() == AMDGPULibFunc::EI_POWN_FAST) &&
895 "fold_pow: encounter a wrong function call");
896
897 Module *M = B.getModule();
898 Type *eltType = FPOp->getType()->getScalarType();
899 Value *opr0 = FPOp->getOperand(0);
900 Value *opr1 = FPOp->getOperand(1);
901
902 const APFloat *CF = nullptr;
903 const APInt *CINT = nullptr;
904 if (!match(opr1, m_APFloatAllowPoison(CF)))
905 match(opr1, m_APIntAllowPoison(CINT));
906
907 // 0x1111111 means that we don't do anything for this call.
908 int ci_opr1 = (CINT ? (int)CINT->getSExtValue() : 0x1111111);
909
910 // OpenCL powr(x<0, y) = NaN, but the folds below would turn it into a
911 // finite number. Skip them unless NaNs are ignored or the base is known
912 // non-negative.
913 bool IsPowr = FInfo.getId() == AMDGPULibFunc::EI_POWR ||
914 FInfo.getId() == AMDGPULibFunc::EI_POWR_FAST;
915 bool SkipConstantFolds =
916 IsPowr && !FPOp->hasNoNaNs() &&
918 opr0, SQ.getWithInstruction(cast<Instruction>(FPOp)));
919
920 if (CF && (CF->isExactlyValue(0.5) || CF->isExactlyValue(-0.5))) {
921 // pow[r](x, [-]0.5) = sqrt(x) / rsqrt(x)
922 //
923 // sqrt/rsqrt and pow disagree on two negative inputs:
924 // pow(-Inf, 0.5) == +Inf but sqrt(-Inf) == NaN (ninf case)
925 // pow(-0.0, 0.5) == +0.0 but sqrt(-0.0) == -0.0 (nsz case)
926 // powr requires x >= 0 by the OpenCL spec, so -Inf is undefined behaviour
927 // and the ninf check can be skipped for powr/powr_fast. -0.0 is a valid
928 // input for powr since -0.0 >= 0 by IEEE comparison, so nsz is still
929 // required for all variants. sqrt/rsqrt already return NaN for a
930 // negative base like powr does, so this fold skips the base-sign check.
931 if (FPOp->hasNoSignedZeros() && (IsPowr || FPOp->hasNoInfs())) {
932 bool issqrt = CF->isExactlyValue(0.5);
933 if (FunctionCallee FPExpr =
934 getFunction(M, AMDGPULibFunc(issqrt ? AMDGPULibFunc::EI_SQRT
936 FInfo))) {
937 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << FInfo.getName()
938 << '(' << *opr0 << ")\n");
939 Value *nval = CreateCallEx(B, FPExpr, opr0,
940 issqrt ? "__pow2sqrt" : "__pow2rsqrt");
941 replaceCall(FPOp, nval);
942 return true;
943 }
944 }
945 }
946
947 if (!SkipConstantFolds) {
948 if ((CF && CF->isZero()) || (CINT && ci_opr1 == 0)) {
949 // pow/powr/pown(x, 0) == 1
950 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1\n");
951 Constant *cnval = ConstantFP::get(eltType, 1.0);
952 if (getVecSize(FInfo) > 1) {
953 cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
954 }
955 replaceCall(FPOp, cnval);
956 return true;
957 }
958 if ((CF && CF->isOne()) || (CINT && ci_opr1 == 1)) {
959 // pow/powr/pown(x, 1.0) = x
960 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << "\n");
961 replaceCall(FPOp, opr0);
962 return true;
963 }
964 if ((CF && CF->isExactlyValue(2.0)) || (CINT && ci_opr1 == 2)) {
965 // pow/powr/pown(x, 2.0) = x*x
966 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << " * "
967 << *opr0 << "\n");
968 Value *nval = B.CreateFMul(opr0, opr0, "__pow2");
969 replaceCall(FPOp, nval);
970 return true;
971 }
972 if ((CF && CF->isMinusOne()) || (CINT && ci_opr1 == -1)) {
973 // pow/powr/pown(x, -1.0) = 1.0/x
974 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1 / " << *opr0 << "\n");
975 Constant *cnval = ConstantFP::get(eltType, 1.0);
976 if (getVecSize(FInfo) > 1) {
977 cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
978 }
979 Value *nval = B.CreateFDiv(cnval, opr0, "__powrecip");
980 replaceCall(FPOp, nval);
981 return true;
982 }
983 }
984
985 if (!isUnsafeFiniteOnlyMath(FPOp))
986 return false;
987
988 // Unsafe Math optimization
989
990 // Remember that ci_opr1 is set if opr1 is integral
991 if (CF) {
992 double dval = (getArgType(FInfo) == AMDGPULibFunc::F32)
993 ? (double)CF->convertToFloat()
994 : CF->convertToDouble();
995 int ival = (int)dval;
996 if ((double)ival == dval) {
997 ci_opr1 = ival;
998 } else
999 ci_opr1 = 0x11111111;
1000 }
1001
1002 // pow/powr/pown(x, c) = [1/](x*x*..x); where
1003 // trunc(c) == c && the number of x == c && |c| <= 12
1004 unsigned abs_opr1 = (ci_opr1 < 0) ? -ci_opr1 : ci_opr1;
1005 if (abs_opr1 <= 12) {
1006 Constant *cnval;
1007 Value *nval;
1008 if (abs_opr1 == 0) {
1009 cnval = ConstantFP::get(eltType, 1.0);
1010 if (getVecSize(FInfo) > 1) {
1011 cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
1012 }
1013 nval = cnval;
1014 } else {
1015 Value *valx2 = nullptr;
1016 nval = nullptr;
1017 while (abs_opr1 > 0) {
1018 valx2 = valx2 ? B.CreateFMul(valx2, valx2, "__powx2") : opr0;
1019 if (abs_opr1 & 1) {
1020 nval = nval ? B.CreateFMul(nval, valx2, "__powprod") : valx2;
1021 }
1022 abs_opr1 >>= 1;
1023 }
1024 }
1025
1026 if (ci_opr1 < 0) {
1027 cnval = ConstantFP::get(eltType, 1.0);
1028 if (getVecSize(FInfo) > 1) {
1029 cnval = ConstantDataVector::getSplat(getVecSize(FInfo), cnval);
1030 }
1031 nval = B.CreateFDiv(cnval, nval, "__1powprod");
1032 }
1033 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> "
1034 << ((ci_opr1 < 0) ? "1/prod(" : "prod(") << *opr0
1035 << ")\n");
1036 replaceCall(FPOp, nval);
1037 return true;
1038 }
1039
1040 // If we should use the generic intrinsic instead of emitting a libcall
1041 const bool ShouldUseIntrinsic = eltType->isFloatTy() || eltType->isHalfTy();
1042
1043 // powr ---> exp2(y * log2(x))
1044 // pown/pow ---> powr(fabs(x), y) | (x & ((int)y << 31))
1045 FunctionCallee ExpExpr;
1046 if (ShouldUseIntrinsic)
1047 ExpExpr = Intrinsic::getOrInsertDeclaration(M, Intrinsic::exp2,
1048 {FPOp->getType()});
1049 else {
1050 ExpExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_EXP2, FInfo));
1051 if (!ExpExpr)
1052 return false;
1053 }
1054
1055 bool needlog = false;
1056 bool needabs = false;
1057 bool needcopysign = false;
1058 Constant *cnval = nullptr;
1059 if (getVecSize(FInfo) == 1) {
1060 CF = nullptr;
1061 match(opr0, m_APFloatAllowPoison(CF));
1062
1063 if (CF) {
1064 double V = (getArgType(FInfo) == AMDGPULibFunc::F32)
1065 ? (double)CF->convertToFloat()
1066 : CF->convertToDouble();
1067
1068 V = log2(std::abs(V));
1069 cnval = ConstantFP::get(eltType, V);
1070 needcopysign = (FInfo.getId() != AMDGPULibFunc::EI_POWR &&
1071 FInfo.getId() != AMDGPULibFunc::EI_POWR_FAST) &&
1072 CF->isNegative();
1073 } else {
1074 needlog = true;
1075 needcopysign = needabs = FInfo.getId() != AMDGPULibFunc::EI_POWR &&
1076 FInfo.getId() != AMDGPULibFunc::EI_POWR_FAST;
1077 }
1078 } else {
1079 ConstantDataVector *CDV = dyn_cast<ConstantDataVector>(opr0);
1080
1081 if (!CDV) {
1082 needlog = true;
1083 needcopysign = needabs = FInfo.getId() != AMDGPULibFunc::EI_POWR &&
1084 FInfo.getId() != AMDGPULibFunc::EI_POWR_FAST;
1085 } else {
1086 assert ((int)CDV->getNumElements() == getVecSize(FInfo) &&
1087 "Wrong vector size detected");
1088
1090 for (int i=0; i < getVecSize(FInfo); ++i) {
1091 double V = CDV->getElementAsAPFloat(i).convertToDouble();
1092 if (V < 0.0) needcopysign = true;
1093 V = log2(std::abs(V));
1094 DVal.push_back(V);
1095 }
1096 if (getArgType(FInfo) == AMDGPULibFunc::F32) {
1098 for (double D : DVal)
1099 FVal.push_back((float)D);
1100 ArrayRef<float> tmp(FVal);
1101 cnval = ConstantDataVector::get(M->getContext(), tmp);
1102 } else {
1103 ArrayRef<double> tmp(DVal);
1104 cnval = ConstantDataVector::get(M->getContext(), tmp);
1105 }
1106 }
1107 }
1108
1109 if (needcopysign && (FInfo.getId() == AMDGPULibFunc::EI_POW ||
1110 FInfo.getId() == AMDGPULibFunc::EI_POW_FAST)) {
1111 // We cannot handle corner cases for a general pow() function, give up
1112 // unless y is a constant integral value. Then proceed as if it were pown.
1113 if (!isKnownIntegral(opr1, SQ.getWithInstruction(cast<Instruction>(FPOp)),
1114 FPOp->getFastMathFlags()))
1115 return false;
1116 }
1117
1118 Value *nval;
1119 if (needabs) {
1120 nval = B.CreateFAbs(opr0, nullptr, "__fabs");
1121 } else {
1122 nval = cnval ? cnval : opr0;
1123 }
1124 if (needlog) {
1125 FunctionCallee LogExpr;
1126 if (ShouldUseIntrinsic) {
1127 LogExpr = Intrinsic::getOrInsertDeclaration(M, Intrinsic::log2,
1128 {FPOp->getType()});
1129 } else {
1130 LogExpr = getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_LOG2, FInfo));
1131 if (!LogExpr)
1132 return false;
1133 }
1134
1135 nval = CreateCallEx(B,LogExpr, nval, "__log2");
1136 }
1137
1138 if (FInfo.getId() == AMDGPULibFunc::EI_POWN ||
1139 FInfo.getId() == AMDGPULibFunc::EI_POWN_FAST) {
1140 // convert int(32) to fp(f32 or f64)
1141 opr1 = B.CreateSIToFP(opr1, nval->getType(), "pownI2F");
1142 }
1143 nval = B.CreateFMul(opr1, nval, "__ylogx");
1144
1145 CallInst *Exp2Call = CreateCallEx(B, ExpExpr, nval, "__exp2");
1146
1147 // TODO: Generalized fpclass logic for pow
1149 if (FPOp->hasNoNaNs())
1150 KnownNot |= FPClassTest::fcNan;
1151
1152 Exp2Call->addRetAttr(
1153 Attribute::getWithNoFPClass(Exp2Call->getContext(), KnownNot));
1154 nval = Exp2Call;
1155
1156 if (needcopysign) {
1157 Type* nTyS = B.getIntNTy(eltType->getPrimitiveSizeInBits());
1158 Type *nTy = FPOp->getType()->getWithNewType(nTyS);
1159 Value *opr_n = FPOp->getOperand(1);
1160 if (opr_n->getType()->getScalarType()->isIntegerTy())
1161 opr_n = B.CreateZExtOrTrunc(opr_n, nTy, "__ytou");
1162 else
1163 opr_n = B.CreateFPToSI(opr1, nTy, "__ytou");
1164
1165 unsigned size = nTy->getScalarSizeInBits();
1166 Value *sign = B.CreateShl(opr_n, size-1, "__yeven");
1167 sign = B.CreateAnd(B.CreateBitCast(opr0, nTy), sign, "__pow_sign");
1168
1169 nval = B.CreateCopySign(nval, B.CreateBitCast(sign, nval->getType()),
1170 nullptr, "__pow_sign");
1171 }
1172
1173 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> "
1174 << "exp2(" << *opr1 << " * log2(" << *opr0 << "))\n");
1175 replaceCall(FPOp, nval);
1176
1177 return true;
1178}
1179
1180bool AMDGPULibCalls::fold_rootn(FPMathOperator *FPOp, IRBuilder<> &B,
1181 const FuncInfo &FInfo) {
1182 Value *opr0 = FPOp->getOperand(0);
1183 Value *opr1 = FPOp->getOperand(1);
1184
1185 const APInt *CINT = nullptr;
1186 if (!match(opr1, m_APIntAllowPoison(CINT)))
1187 return false;
1188
1189 Function *Parent = B.GetInsertBlock()->getParent();
1190
1191 int ci_opr1 = (int)CINT->getSExtValue();
1192 if (ci_opr1 == 1 && !Parent->hasFnAttribute(Attribute::StrictFP)) {
1193 // rootn(x, 1) = x
1194 //
1195 // TODO: Insert constrained canonicalize for strictfp case.
1196 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << '\n');
1197 replaceCall(FPOp, opr0);
1198 return true;
1199 }
1200
1201 Module *M = B.getModule();
1202
1203 CallInst *CI = cast<CallInst>(FPOp);
1204
1205 // rootn and sqrt disagree on signed-zero / -Inf inputs (e.g. rootn(-0.0, 2)
1206 // is +0.0, sqrt(-0.0) is -0.0), so require nsz/ninf.
1207 bool FMFOkForSqrt = FPOp->hasNoSignedZeros() && FPOp->hasNoInfs();
1208
1209 if (ci_opr1 == 2 && FMFOkForSqrt &&
1210 shouldReplaceLibcallWithIntrinsic(CI,
1211 /*AllowMinSizeF32=*/true,
1212 /*AllowF64=*/true)) {
1213 // rootn(x, 2) = sqrt(x)
1214 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> sqrt(" << *opr0 << ")\n");
1215
1216 Value *NewCall = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1217 NewCall->takeName(CI);
1218
1219 // OpenCL rootn has a looser ulp of 2 requirement than sqrt, so add some
1220 // metadata.
1221 MDBuilder MDHelper(M->getContext());
1222 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));
1223 if (auto *NewCallI = dyn_cast<Instruction>(NewCall))
1224 NewCallI->setMetadata(LLVMContext::MD_fpmath, FPMD);
1225
1226 replaceCall(CI, NewCall);
1227 return true;
1228 }
1229
1230 if (ci_opr1 == 3) { // rootn(x, 3) = cbrt(x)
1231 if (FunctionCallee FPExpr =
1232 getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_CBRT, FInfo))) {
1233 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> cbrt(" << *opr0
1234 << ")\n");
1235 Value *nval = CreateCallEx(B,FPExpr, opr0, "__rootn2cbrt");
1236 replaceCall(FPOp, nval);
1237 return true;
1238 }
1239 } else if (ci_opr1 == -1) { // rootn(x, -1) = 1.0/x
1240 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1.0 / " << *opr0 << "\n");
1241 Value *nval = B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0),
1242 opr0,
1243 "__rootn2div");
1244 replaceCall(FPOp, nval);
1245 return true;
1246 }
1247
1248 if (ci_opr1 == -2 && FMFOkForSqrt &&
1249 shouldReplaceLibcallWithIntrinsic(CI,
1250 /*AllowMinSizeF32=*/true,
1251 /*AllowF64=*/true)) {
1252 // rootn(x, -2) = rsqrt(x)
1253
1254 // The original rootn had looser ulp requirements than the resultant sqrt
1255 // and fdiv.
1256 MDBuilder MDHelper(M->getContext());
1257 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));
1258
1259 // TODO: Could handle strictfp but need to fix strict sqrt emission
1260 FastMathFlags FMF = FPOp->getFastMathFlags();
1261 FMF.setAllowContract(true);
1262
1263 Value *Sqrt = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1265 B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0), Sqrt));
1266 if (auto *SqrtI = dyn_cast<Instruction>(Sqrt))
1267 SqrtI->setFastMathFlags(FMF);
1268 RSqrt->setFastMathFlags(FMF);
1269 RSqrt->setMetadata(LLVMContext::MD_fpmath, FPMD);
1270
1271 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> rsqrt(" << *opr0
1272 << ")\n");
1273 replaceCall(CI, RSqrt);
1274 return true;
1275 }
1276
1277 return false;
1278}
1279
1280// is_integer(y) => trunc(y) == y
1282 Value *TruncY = B.CreateUnaryIntrinsic(Intrinsic::trunc, Y);
1283 return B.CreateFCmpOEQ(TruncY, Y);
1284}
1285
1287 // Even integers are still integers after division by 2.
1288 auto *HalfY = B.CreateFMul(Y, ConstantFP::get(Y->getType(), 0.5));
1289 return emitIsInteger(B, HalfY);
1290}
1291
1292// is_odd_integer(y) => is_integer(y) && !is_even_integer(y)
1294 Value *IsIntY = emitIsInteger(B, Y);
1295 Value *IsEvenY = emitIsEvenInteger(B, Y);
1296 Value *NotEvenY = B.CreateNot(IsEvenY);
1297 return B.CreateAnd(IsIntY, NotEvenY);
1298}
1299
1300// isinf(val) => fabs(val) == +inf
1302 auto *fabsVal = B.CreateFAbs(val);
1303 return B.CreateFCmpOEQ(fabsVal, ConstantFP::getInfinity(val->getType()));
1304}
1305
1306// y * log2(fabs(x))
1308 Value *AbsX = B.CreateFAbs(X);
1309 Value *LogAbsX = B.CreateUnaryIntrinsic(Intrinsic::log2, AbsX);
1310 Value *YTimesLogX = B.CreateFMul(Y, LogAbsX);
1311 return B.CreateUnaryIntrinsic(Intrinsic::exp2, YTimesLogX);
1312}
1313
1314/// Emit special case management epilog code for fast pow, powr, pown, and rootn
1315/// expansions. \p x and \p y should be the arguments to the library call
1316/// (possibly with some values clamped). \p expylnx should be the result to use
1317/// in normal circumstances.
1319 PowKind Kind) {
1320 Constant *Zero = ConstantFP::getZero(X->getType());
1321 Constant *One = ConstantFP::get(X->getType(), 1.0);
1322 Constant *QNaN = ConstantFP::getQNaN(X->getType());
1323 Constant *PInf = ConstantFP::getInfinity(X->getType());
1324
1325 switch (Kind) {
1326 case PowKind::Pow: {
1327 // is_odd_integer(y)
1328 Value *IsOddY = emitIsOddInteger(B, Y);
1329
1330 // ret = copysign(expylnx, is_odd_y ? x : 1.0f)
1331 Value *SelSign = B.CreateSelect(IsOddY, X, One);
1332 Value *Ret = B.CreateCopySign(ExpYLnX, SelSign);
1333
1334 // if (x < 0 && !is_integer(y)) ret = QNAN
1335 Value *IsIntY = emitIsInteger(B, Y);
1336 Value *condNegX = B.CreateFCmpOLT(X, Zero);
1337 Value *condNotIntY = B.CreateNot(IsIntY);
1338 Value *condNaN = B.CreateAnd(condNegX, condNotIntY);
1339 Ret = B.CreateSelect(condNaN, QNaN, Ret);
1340
1341 // if (isinf(ay)) { ... }
1342
1343 // FIXME: Missing backend optimization to save on materialization cost of
1344 // mixed sign constant infinities.
1345 Value *YIsInf = emitIsInf(B, Y);
1346
1347 Value *AY = B.CreateFAbs(Y);
1348 Value *YIsNegInf = B.CreateFCmpUNE(Y, AY);
1349
1350 Value *AX = B.CreateFAbs(X);
1351 Value *AxEqOne = B.CreateFCmpOEQ(AX, One);
1352 Value *AxLtOne = B.CreateFCmpOLT(AX, One);
1353 Value *XorCond = B.CreateXor(AxLtOne, YIsNegInf);
1354 Value *SelInf =
1355 B.CreateSelect(AxEqOne, AX, B.CreateSelect(XorCond, Zero, AY));
1356 Ret = B.CreateSelect(YIsInf, SelInf, Ret);
1357
1358 // if (isinf(ax) || x == 0.0f) { ... }
1359 Value *XIsInf = emitIsInf(B, X);
1360 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1361 Value *AxInfOrZero = B.CreateOr(XIsInf, XEqZero);
1362 Value *YLtZero = B.CreateFCmpOLT(Y, Zero);
1363 Value *XorZeroInf = B.CreateXor(XEqZero, YLtZero);
1364 Value *SelVal = B.CreateSelect(XorZeroInf, Zero, PInf);
1365 Value *SelSign2 = B.CreateSelect(IsOddY, X, Zero);
1366 Value *Copysign = B.CreateCopySign(SelVal, SelSign2);
1367 Ret = B.CreateSelect(AxInfOrZero, Copysign, Ret);
1368
1369 // if (isunordered(x, y)) ret = QNAN
1370 Value *isUnordered = B.CreateFCmpUNO(X, Y);
1371 return B.CreateSelect(isUnordered, QNaN, Ret);
1372 }
1373 case PowKind::PowR: {
1374 Value *YIsNeg = B.CreateFCmpOLT(Y, Zero);
1375 Value *IZ = B.CreateSelect(YIsNeg, PInf, Zero);
1376 Value *ZI = B.CreateSelect(YIsNeg, Zero, PInf);
1377
1378 Value *YEqZero = B.CreateFCmpOEQ(Y, Zero);
1379 Value *SelZeroCase = B.CreateSelect(YEqZero, QNaN, IZ);
1380 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1381 Value *Ret = B.CreateSelect(XEqZero, SelZeroCase, ExpYLnX);
1382
1383 Value *XEqInf = B.CreateFCmpOEQ(X, PInf);
1384 Value *YNeZero = B.CreateFCmpUNE(Y, Zero);
1385 Value *CondInfCase = B.CreateAnd(XEqInf, YNeZero);
1386 Ret = B.CreateSelect(CondInfCase, ZI, Ret);
1387
1388 Value *IsInfY = emitIsInf(B, Y);
1389 Value *XNeOne = B.CreateFCmpUNE(X, One);
1390 Value *CondInfY = B.CreateAnd(IsInfY, XNeOne);
1391 Value *XLtOne = B.CreateFCmpOLT(X, One);
1392 Value *SelInfYCase = B.CreateSelect(XLtOne, IZ, ZI);
1393 Ret = B.CreateSelect(CondInfY, SelInfYCase, Ret);
1394
1395 Value *IsUnordered = B.CreateFCmpUNO(X, Y);
1396 return B.CreateSelect(IsUnordered, QNaN, Ret);
1397 }
1398 case PowKind::PowN: {
1399 Constant *ZeroI = ConstantInt::get(Y->getType(), 0);
1400
1401 // is_odd_y = (ny & 1) != 0
1402 Value *OneI = ConstantInt::get(Y->getType(), 1);
1403 Value *YAnd1 = B.CreateAnd(Y, OneI);
1404 Value *IsOddY = B.CreateICmpNE(YAnd1, ZeroI);
1405
1406 // ret = copysign(expylnx, is_odd_y ? x : 1.0f)
1407 Value *SelSign = B.CreateSelect(IsOddY, X, One);
1408 Value *Ret = B.CreateCopySign(ExpYLnX, SelSign);
1409
1410 // if (isinf(x) || x == 0.0f)
1411 Value *FabsX = B.CreateFAbs(X);
1412 Value *XIsInf = B.CreateFCmpOEQ(FabsX, PInf);
1413 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1414 Value *InfOrZero = B.CreateOr(XIsInf, XEqZero);
1415
1416 // (x == 0.0f) ^ (ny < 0) ? 0.0f : +inf
1417 Value *YLtZero = B.CreateICmpSLT(Y, ZeroI);
1418 Value *XorZeroInf = B.CreateXor(XEqZero, YLtZero);
1419 Value *SelVal = B.CreateSelect(XorZeroInf, Zero, PInf);
1420
1421 // copysign(selVal, is_odd_y ? x : 0.0f)
1422 Value *SelSign2 = B.CreateSelect(IsOddY, X, Zero);
1423 Value *Copysign = B.CreateCopySign(SelVal, SelSign2);
1424
1425 return B.CreateSelect(InfOrZero, Copysign, Ret);
1426 }
1427 case PowKind::RootN: {
1428 Constant *ZeroI = ConstantInt::get(Y->getType(), 0);
1429
1430 // is_odd_y = (ny & 1) != 0
1431 Value *YAnd1 = B.CreateAnd(Y, ConstantInt::get(Y->getType(), 1));
1432 Value *IsOddY = B.CreateICmpNE(YAnd1, ZeroI);
1433
1434 // ret = copysign(expylnx, is_odd_y ? x : 1.0f)
1435 Value *SelSign = B.CreateSelect(IsOddY, X, One);
1436 Value *Ret = B.CreateCopySign(ExpYLnX, SelSign);
1437
1438 // if (isinf(x) || x == 0.0f)
1439 Value *FabsX = B.CreateFAbs(X);
1440 Value *IsInfX = B.CreateFCmpOEQ(FabsX, PInf);
1441 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1442 Value *CondInfOrZero = B.CreateOr(IsInfX, XEqZero);
1443
1444 // (x == 0.0f) ^ (ny < 0) ? 0.0f : +inf
1445 Value *YLtZero = B.CreateICmpSLT(Y, ZeroI);
1446 Value *XorZeroInf = B.CreateXor(XEqZero, YLtZero);
1447 Value *SelVal = B.CreateSelect(XorZeroInf, Zero, PInf);
1448
1449 // copysign(selVal, is_odd_y ? x : 0.0f)
1450 Value *SelSign2 = B.CreateSelect(IsOddY, X, Zero);
1451 Value *Copysign = B.CreateCopySign(SelVal, SelSign2);
1452
1453 Ret = B.CreateSelect(CondInfOrZero, Copysign, Ret);
1454
1455 // if ((x < 0.0f && !is_odd_y) || ny == 0) ret = QNAN
1456 Value *XIsNeg = B.CreateFCmpOLT(X, Zero);
1457 Value *NotOddY = B.CreateNot(IsOddY);
1458 Value *CondNegAndNotOdd = B.CreateAnd(XIsNeg, NotOddY);
1459 Value *YEqZero = B.CreateICmpEQ(Y, ZeroI);
1460 Value *CondBad = B.CreateOr(CondNegAndNotOdd, YEqZero);
1461 return B.CreateSelect(CondBad, QNaN, Ret);
1462 }
1463 }
1464
1465 llvm_unreachable("covered switch");
1466}
1467
1468// TODO: Move the fold_pow folding to sqrt/fdiv here
1469bool AMDGPULibCalls::expandFastPow(FPMathOperator *FPOp, IRBuilder<> &B,
1470 PowKind Kind) {
1471 Type *Ty = FPOp->getType();
1472
1473 // There's currently no reason to do this for half. The correct path is
1474 // promote to float and use the fast float expansion.
1475 //
1476 // TODO: We could move this expansion to lowering to get half pow to work.
1477 if (!Ty->getScalarType()->isFloatTy())
1478 return false;
1479
1480 // TODO: Verify optimization for double and bfloat.
1481 Value *X = FPOp->getOperand(0);
1482 Value *Y = FPOp->getOperand(1);
1483
1484 switch (Kind) {
1485 case PowKind::Pow: {
1486 Constant *One = ConstantFP::get(X->getType(), 1.0);
1487
1488 // if (x == 1.0f) y = 1.0f;
1489 Value *XEqOne = B.CreateFCmpOEQ(X, One);
1490 Y = B.CreateSelect(XEqOne, One, Y);
1491
1492 // if (y == 0.0f) x = 1.0f;
1493 Value *YEqZero = B.CreateFCmpOEQ(Y, ConstantFP::getZero(X->getType()));
1494 X = B.CreateSelect(YEqZero, One, X);
1495
1496 Value *ExpYLnX = emitFastExpYLnx(B, X, Y);
1497 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1498 replaceCall(FPOp, Fixed);
1499 return true;
1500 }
1501 case PowKind::PowR: {
1502 Value *NegX = B.CreateFCmpOLT(X, ConstantFP::getZero(X->getType()));
1503 X = B.CreateSelect(NegX, ConstantFP::getQNaN(X->getType()), X);
1504
1505 Value *ExpYLnX = emitFastExpYLnx(B, X, Y);
1506 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1507 replaceCall(FPOp, Fixed);
1508 return true;
1509 }
1510 case PowKind::PowN: {
1511 // ny == 0
1512 Value *YEqZero = B.CreateICmpEQ(Y, ConstantInt::get(Y->getType(), 0));
1513
1514 // x = (ny == 0 ? 1.0f : x)
1515 X = B.CreateSelect(YEqZero, ConstantFP::get(X->getType(), 1.0), X);
1516
1517 Value *CastY = B.CreateSIToFP(Y, X->getType());
1518 Value *ExpYLnX = emitFastExpYLnx(B, X, CastY);
1519 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1520 replaceCall(FPOp, Fixed);
1521 return true;
1522 }
1523 case PowKind::RootN: {
1524 Value *CastY = B.CreateSIToFP(Y, X->getType());
1525
1526 // This is afn anyway, so we will turn into rcp.
1527 Value *RcpY = B.CreateFDiv(ConstantFP::get(X->getType(), 1.0), CastY);
1528
1529 Value *ExpYLnX = emitFastExpYLnx(B, X, RcpY);
1530 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1531 replaceCall(FPOp, Fixed);
1532 return true;
1533 }
1534 }
1535 llvm_unreachable("Unhandled PowKind enum");
1536}
1537
1538bool AMDGPULibCalls::tryOptimizePow(FPMathOperator *FPOp, IRBuilder<> &B,
1539 const FuncInfo &FInfo) {
1540 FastMathFlags FMF = FPOp->getFastMathFlags();
1541 CallInst *Call = cast<CallInst>(FPOp);
1542 Module *M = Call->getModule();
1543
1544 FuncInfo PowrInfo;
1545 AMDGPULibFunc::EFuncId FastPowrFuncId =
1546 FMF.approxFunc() || FInfo.getId() == AMDGPULibFunc::EI_POW_FAST
1549 FunctionCallee PowrFunc = getFloatFastVariant(
1550 M, FInfo, PowrInfo, AMDGPULibFunc::EI_POWR, FastPowrFuncId);
1551
1552 // TODO: Prefer fast pown to fast powr, but slow powr to slow pown.
1553
1554 // pow(x, y) -> powr(x, y) for x >= -0.0
1555 // TODO: Account for flags on current call
1556 if (PowrFunc && cannotBeOrderedLessThanZero(FPOp->getOperand(0),
1557 SQ.getWithInstruction(Call))) {
1558 Call->setCalledFunction(PowrFunc);
1559 return fold_pow(FPOp, B, PowrInfo) || true;
1560 }
1561
1562 // pow(x, y) -> pown(x, y) for known integral y
1563 if (isKnownIntegral(FPOp->getOperand(1), SQ.getWithInstruction(Call),
1564 FPOp->getFastMathFlags())) {
1565 FunctionType *PownType = getPownType(Call->getFunctionType());
1566
1567 FuncInfo PownInfo;
1568 AMDGPULibFunc::EFuncId FastPownFuncId =
1569 FMF.approxFunc() || FInfo.getId() == AMDGPULibFunc::EI_POW_FAST
1572 FunctionCallee PownFunc = getFloatFastVariant(
1573 M, FInfo, PownInfo, AMDGPULibFunc::EI_POWN, FastPownFuncId);
1574
1575 if (PownFunc) {
1576 // TODO: If the incoming integral value is an sitofp/uitofp, it won't
1577 // fold out without a known range. We can probably take the source
1578 // value directly.
1579 Value *CastedArg =
1580 B.CreateFPToSI(FPOp->getOperand(1), PownType->getParamType(1));
1581 // Have to drop any nofpclass attributes on the original call site.
1583 1, AttributeFuncs::typeIncompatible(CastedArg->getType(),
1585 Call->setCalledFunction(PownFunc);
1586 Call->setArgOperand(1, CastedArg);
1587 return fold_pow(FPOp, B, PownInfo) || true;
1588 }
1589 }
1590
1591 if (fold_pow(FPOp, B, FInfo))
1592 return true;
1593
1594 if (!FMF.approxFunc())
1595 return false;
1596
1597 if (FInfo.getId() == AMDGPULibFunc::EI_POW && FMF.approxFunc() &&
1598 getArgType(FInfo) == AMDGPULibFunc::F32) {
1599 AMDGPULibFunc PowFastInfo(AMDGPULibFunc::EI_POW_FAST, FInfo);
1600 if (FunctionCallee PowFastFunc = getFunction(M, PowFastInfo)) {
1601 Call->setCalledFunction(PowFastFunc);
1602 return fold_pow(FPOp, B, PowFastInfo) || true;
1603 }
1604 }
1605
1606 return expandFastPow(FPOp, B, PowKind::Pow);
1607}
1608
1609// Some library calls are just wrappers around llvm intrinsics, but compiled
1610// conservatively. Preserve the flags from the original call site by
1611// substituting them with direct calls with all the flags.
1612bool AMDGPULibCalls::shouldReplaceLibcallWithIntrinsic(const CallInst *CI,
1613 bool AllowMinSizeF32,
1614 bool AllowF64,
1615 bool AllowStrictFP) {
1616 Type *FltTy = CI->getType()->getScalarType();
1617 const bool IsF32 = FltTy->isFloatTy();
1618
1619 // f64 intrinsics aren't implemented for most operations.
1620 if (!IsF32 && !FltTy->isHalfTy() && (!AllowF64 || !FltTy->isDoubleTy()))
1621 return false;
1622
1623 // We're implicitly inlining by replacing the libcall with the intrinsic, so
1624 // don't do it for noinline call sites.
1625 if (CI->isNoInline())
1626 return false;
1627
1628 const Function *ParentF = CI->getFunction();
1629 // TODO: Handle strictfp
1630 if (!AllowStrictFP && ParentF->hasFnAttribute(Attribute::StrictFP))
1631 return false;
1632
1633 if (IsF32 && !AllowMinSizeF32 && ParentF->hasMinSize())
1634 return false;
1635 return true;
1636}
1637
1638void AMDGPULibCalls::replaceLibCallWithSimpleIntrinsic(IRBuilder<> &B,
1639 CallInst *CI,
1640 Intrinsic::ID IntrID) {
1641 if (CI->arg_size() == 2) {
1642 Value *Arg0 = CI->getArgOperand(0);
1643 Value *Arg1 = CI->getArgOperand(1);
1644 VectorType *Arg0VecTy = dyn_cast<VectorType>(Arg0->getType());
1645 VectorType *Arg1VecTy = dyn_cast<VectorType>(Arg1->getType());
1646 if (Arg0VecTy && !Arg1VecTy) {
1647 Value *SplatRHS = B.CreateVectorSplat(Arg0VecTy->getElementCount(), Arg1);
1648 CI->setArgOperand(1, SplatRHS);
1649 } else if (!Arg0VecTy && Arg1VecTy) {
1650 Value *SplatLHS = B.CreateVectorSplat(Arg1VecTy->getElementCount(), Arg0);
1651 CI->setArgOperand(0, SplatLHS);
1652 }
1653 }
1654
1656 CI->getModule(), IntrID, {CI->getType()}));
1658}
1659
1660bool AMDGPULibCalls::tryReplaceLibcallWithSimpleIntrinsic(
1661 IRBuilder<> &B, CallInst *CI, Intrinsic::ID IntrID, bool AllowMinSizeF32,
1662 bool AllowF64, bool AllowStrictFP) {
1663 if (!shouldReplaceLibcallWithIntrinsic(CI, AllowMinSizeF32, AllowF64,
1664 AllowStrictFP))
1665 return false;
1666 replaceLibCallWithSimpleIntrinsic(B, CI, IntrID);
1667 return true;
1668}
1669
1670std::tuple<Value *, Value *, Value *>
1671AMDGPULibCalls::insertSinCos(Value *Arg, FastMathFlags FMF, IRBuilder<> &B,
1672 FunctionCallee Fsincos) {
1673 DebugLoc DL = B.getCurrentDebugLocation();
1674 Function *F = B.GetInsertBlock()->getParent();
1675 B.SetInsertPointPastAllocas(F);
1676
1677 AllocaInst *Alloc = B.CreateAlloca(Arg->getType(), nullptr, "__sincos_");
1678
1679 if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
1680 // If the argument is an instruction, it must dominate all uses so put our
1681 // sincos call there. Otherwise, right after the allocas works well enough
1682 // if it's an argument or constant.
1683
1684 B.SetInsertPoint(*ArgInst->getInsertionPointAfterDef());
1685
1686 // SetInsertPoint unwelcomely always tries to set the debug loc.
1687 B.SetCurrentDebugLocation(DL);
1688 }
1689
1690 Type *CosPtrTy = Fsincos.getFunctionType()->getParamType(1);
1691
1692 // The allocaInst allocates the memory in private address space. This need
1693 // to be addrspacecasted to point to the address space of cos pointer type.
1694 // In OpenCL 2.0 this is generic, while in 1.2 that is private.
1695 Value *CastAlloc = B.CreateAddrSpaceCast(Alloc, CosPtrTy);
1696
1697 CallInst *SinCos = CreateCallEx2(B, Fsincos, Arg, CastAlloc);
1698
1699 // TODO: Is it worth trying to preserve the location for the cos calls for the
1700 // load?
1701
1702 LoadInst *LoadCos = B.CreateLoad(Arg->getType(), Alloc);
1703 return {SinCos, LoadCos, SinCos};
1704}
1705
1706// fold sin, cos -> sincos.
1707bool AMDGPULibCalls::fold_sincos(FPMathOperator *FPOp, IRBuilder<> &B,
1708 const FuncInfo &fInfo) {
1709 assert(fInfo.getId() == AMDGPULibFunc::EI_SIN ||
1710 fInfo.getId() == AMDGPULibFunc::EI_COS);
1711
1712 if ((getArgType(fInfo) != AMDGPULibFunc::F32 &&
1713 getArgType(fInfo) != AMDGPULibFunc::F64) ||
1714 fInfo.getPrefix() != AMDGPULibFunc::NOPFX)
1715 return false;
1716
1717 bool const isSin = fInfo.getId() == AMDGPULibFunc::EI_SIN;
1718
1719 Value *CArgVal = FPOp->getOperand(0);
1720
1721 // TODO: Constant fold the call
1722 if (isa<ConstantData>(CArgVal))
1723 return false;
1724
1725 CallInst *CI = cast<CallInst>(FPOp);
1726
1727 Function *F = B.GetInsertBlock()->getParent();
1728 Module *M = F->getParent();
1729
1730 // Merge the sin and cos. For OpenCL 2.0, there may only be a generic pointer
1731 // implementation. Prefer the private form if available.
1732 AMDGPULibFunc SinCosLibFuncPrivate(AMDGPULibFunc::EI_SINCOS, fInfo);
1733 SinCosLibFuncPrivate.getLeads()[0].PtrKind =
1735
1736 AMDGPULibFunc SinCosLibFuncGeneric(AMDGPULibFunc::EI_SINCOS, fInfo);
1737 SinCosLibFuncGeneric.getLeads()[0].PtrKind =
1739
1740 FunctionCallee FSinCosPrivate = getFunction(M, SinCosLibFuncPrivate);
1741 FunctionCallee FSinCosGeneric = getFunction(M, SinCosLibFuncGeneric);
1742 FunctionCallee FSinCos = FSinCosPrivate ? FSinCosPrivate : FSinCosGeneric;
1743 if (!FSinCos)
1744 return false;
1745
1746 SmallVector<CallInst *> SinCalls;
1747 SmallVector<CallInst *> CosCalls;
1748 SmallVector<CallInst *> SinCosCalls;
1749 FuncInfo PartnerInfo(isSin ? AMDGPULibFunc::EI_COS : AMDGPULibFunc::EI_SIN,
1750 fInfo);
1751 const std::string PairName = PartnerInfo.mangle();
1752
1753 StringRef SinName = isSin ? CI->getCalledFunction()->getName() : PairName;
1754 StringRef CosName = isSin ? PairName : CI->getCalledFunction()->getName();
1755 const std::string SinCosPrivateName = SinCosLibFuncPrivate.mangle();
1756 const std::string SinCosGenericName = SinCosLibFuncGeneric.mangle();
1757
1758 // Intersect the two sets of flags.
1759 FastMathFlags FMF = FPOp->getFastMathFlags();
1760 MDNode *FPMath = CI->getMetadata(LLVMContext::MD_fpmath);
1761
1762 SmallVector<DILocation *> MergeDbgLocs = {CI->getDebugLoc()};
1763
1764 for (User* U : CArgVal->users()) {
1765 CallInst *XI = dyn_cast<CallInst>(U);
1766 if (!XI || XI->getFunction() != F || XI->isNoBuiltin())
1767 continue;
1768
1769 Function *UCallee = XI->getCalledFunction();
1770 if (!UCallee)
1771 continue;
1772
1773 bool Handled = true;
1774
1775 if (UCallee->getName() == SinName)
1776 SinCalls.push_back(XI);
1777 else if (UCallee->getName() == CosName)
1778 CosCalls.push_back(XI);
1779 else if (UCallee->getName() == SinCosPrivateName ||
1780 UCallee->getName() == SinCosGenericName)
1781 SinCosCalls.push_back(XI);
1782 else
1783 Handled = false;
1784
1785 if (Handled) {
1786 MergeDbgLocs.push_back(XI->getDebugLoc());
1787 auto *OtherOp = cast<FPMathOperator>(XI);
1788 FMF &= OtherOp->getFastMathFlags();
1790 FPMath, XI->getMetadata(LLVMContext::MD_fpmath));
1791 }
1792 }
1793
1794 if (SinCalls.empty() || CosCalls.empty())
1795 return false;
1796
1797 // insertSinCos needs an insertion point after the argument's def.
1798 if (auto *ArgInst = dyn_cast<Instruction>(CArgVal);
1799 ArgInst && !ArgInst->getInsertionPointAfterDef())
1800 return false;
1801
1802 B.setFastMathFlags(FMF);
1803 B.setDefaultFPMathTag(FPMath);
1804 DILocation *DbgLoc = DILocation::getMergedLocations(MergeDbgLocs);
1805 B.SetCurrentDebugLocation(DbgLoc);
1806
1807 auto [Sin, Cos, SinCos] = insertSinCos(CArgVal, FMF, B, FSinCos);
1808
1809 auto replaceTrigInsts = [](ArrayRef<CallInst *> Calls, Value *Res) {
1810 for (CallInst *C : Calls)
1811 C->replaceAllUsesWith(Res);
1812
1813 // Leave the other dead instructions to avoid clobbering iterators.
1814 };
1815
1816 replaceTrigInsts(SinCalls, Sin);
1817 replaceTrigInsts(CosCalls, Cos);
1818 replaceTrigInsts(SinCosCalls, SinCos);
1819
1820 // It's safe to delete the original now.
1821 CI->eraseFromParent();
1822 return true;
1823}
1824
1825bool AMDGPULibCalls::evaluateScalarMathFunc(const FuncInfo &FInfo,
1826 APFloat &Res0, APFloat &Res1,
1827 Constant *copr0, Constant *copr1) {
1828 // Every function handled below reads its first operand as a floating-point
1829 // value. Refuse anything else, e.g. a poison vector lane: silently treating
1830 // it as 0.0 misfolds the whole call.
1832 if (!fpopr0)
1833 return false;
1834
1835 double opr0 = (getArgType(FInfo) == AMDGPULibFunc::F64)
1836 ? fpopr0->getValueAPF().convertToDouble()
1837 : (double)fpopr0->getValueAPF().convertToFloat();
1838
1839 switch (FInfo.getId()) {
1840 default:
1841 return false;
1842
1844 Res0 = APFloat{acos(opr0)};
1845 return true;
1846
1848 // acosh(x) == log(x + sqrt(x*x - 1))
1849 Res0 = APFloat{log(opr0 + sqrt(opr0 * opr0 - 1.0))};
1850 return true;
1851
1853 Res0 = APFloat{acos(opr0) / MATH_PI};
1854 return true;
1855
1857 Res0 = APFloat{asin(opr0)};
1858 return true;
1859
1861 // asinh(x) == log(x + sqrt(x*x + 1))
1862 Res0 = APFloat{log(opr0 + sqrt(opr0 * opr0 + 1.0))};
1863 return true;
1864
1866 Res0 = APFloat{asin(opr0) / MATH_PI};
1867 return true;
1868
1870 Res0 = APFloat{atan(opr0)};
1871 return true;
1872
1874 // atanh(x) == (log(x+1) - log(x-1))/2;
1875 Res0 = APFloat{(log(opr0 + 1.0) - log(opr0 - 1.0)) / 2.0};
1876 return true;
1877
1879 Res0 = APFloat{atan(opr0) / MATH_PI};
1880 return true;
1881
1883 Res0 =
1884 APFloat{(opr0 < 0.0) ? -pow(-opr0, 1.0 / 3.0) : pow(opr0, 1.0 / 3.0)};
1885 return true;
1886
1888 Res0 = APFloat{cos(opr0)};
1889 return true;
1890
1892 Res0 = APFloat{cosh(opr0)};
1893 return true;
1894
1896 Res0 = APFloat{cos(MATH_PI * opr0)};
1897 return true;
1898
1900 Res0 = APFloat{std::exp(opr0)};
1901 return true;
1902
1904 Res0 = APFloat{pow(2.0, opr0)};
1905 return true;
1906
1908 Res0 = APFloat{pow(10.0, opr0)};
1909 return true;
1910
1912 Res0 = APFloat{log(opr0)};
1913 return true;
1914
1916 Res0 = APFloat{log(opr0) / log(2.0)};
1917 return true;
1918
1920 Res0 = APFloat{log(opr0) / log(10.0)};
1921 return true;
1922
1924 Res0 = APFloat{1.0 / sqrt(opr0)};
1925 return true;
1926
1928 Res0 = APFloat{sin(opr0)};
1929 return true;
1930
1932 Res0 = APFloat{sinh(opr0)};
1933 return true;
1934
1936 Res0 = APFloat{sin(MATH_PI * opr0)};
1937 return true;
1938
1940 Res0 = APFloat{tan(opr0)};
1941 return true;
1942
1944 Res0 = APFloat{tanh(opr0)};
1945 return true;
1946
1948 Res0 = APFloat{tan(MATH_PI * opr0)};
1949 return true;
1950
1951 // two-arg functions
1955 if (!fpopr1)
1956 return false;
1957 double opr1 = (getArgType(FInfo) == AMDGPULibFunc::F64)
1958 ? fpopr1->getValueAPF().convertToDouble()
1959 : (double)fpopr1->getValueAPF().convertToFloat();
1960 Res0 = APFloat{pow(opr0, opr1)};
1961 return true;
1962 }
1963
1965 if (ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
1966 double val = (double)iopr1->getSExtValue();
1967 Res0 = APFloat{pow(opr0, val)};
1968 return true;
1969 }
1970 return false;
1971 }
1972
1974 if (ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
1975 double val = (double)iopr1->getSExtValue();
1976 Res0 = APFloat{pow(opr0, 1.0 / val)};
1977 return true;
1978 }
1979 return false;
1980 }
1981
1982 // with ptr arg
1984 Res0 = APFloat{sin(opr0)};
1985 Res1 = APFloat{cos(opr0)};
1986 return true;
1987 }
1988
1989 return false;
1990}
1991
1992bool AMDGPULibCalls::evaluateCall(CallInst *aCI, const FuncInfo &FInfo) {
1993 int numArgs = (int)aCI->arg_size();
1994 if (numArgs > 3)
1995 return false;
1996
1997 Constant *copr0 = nullptr;
1998 Constant *copr1 = nullptr;
1999 if (numArgs > 0) {
2000 if ((copr0 = dyn_cast<Constant>(aCI->getArgOperand(0))) == nullptr)
2001 return false;
2002 }
2003
2004 if (numArgs > 1) {
2005 if ((copr1 = dyn_cast<Constant>(aCI->getArgOperand(1))) == nullptr) {
2006 if (FInfo.getId() != AMDGPULibFunc::EI_SINCOS)
2007 return false;
2008 }
2009 }
2010
2011 // At this point, all arguments to aCI are constants.
2012
2013 // max vector size is 16, and sincos will generate two results.
2014 SmallVector<APFloat, 16> Val0, Val1;
2015 int FuncVecSize = getVecSize(FInfo);
2016 if (FuncVecSize == 1) {
2017 if (!evaluateScalarMathFunc(FInfo, Val0.emplace_back(0.0),
2018 Val1.emplace_back(0.0), copr0, copr1)) {
2019 return false;
2020 }
2021 } else {
2022 // An operand of a vector variant is not necessarily a vector: sincos takes
2023 // a pointer as its second operand, and fmin/fmax/ldexp accept an
2024 // implicitly splatted scalar. Only index into actual vectors.
2025 Constant *CV0 = copr0 && copr0->getType()->isVectorTy() ? copr0 : nullptr;
2026 Constant *CV1 = copr1 && copr1->getType()->isVectorTy() ? copr1 : nullptr;
2027 for (int i = 0; i < FuncVecSize; ++i) {
2028 Constant *celt0 = CV0 ? CV0->getAggregateElement((unsigned)i) : nullptr;
2029 Constant *celt1 = CV1 ? CV1->getAggregateElement((unsigned)i) : nullptr;
2030 if (!evaluateScalarMathFunc(FInfo, Val0.emplace_back(0.0),
2031 Val1.emplace_back(0.0), celt0, celt1)) {
2032 return false;
2033 }
2034 }
2035 }
2036
2037 Constant *nval0 = getConstantFloat(Val0, aCI->getType());
2038
2039 // sincos
2040 if (FInfo.getId() == AMDGPULibFunc::EI_SINCOS) {
2041 Constant *nval1 = getConstantFloat(Val1, aCI->getType());
2042 new StoreInst(nval1, aCI->getArgOperand(1), aCI->getIterator());
2043 }
2044
2045 replaceCall(aCI, nval0);
2046 return true;
2047}
2048
2051 AMDGPULibCalls Simplifier(F, AM);
2052 Simplifier.initNativeFuncs();
2053
2054 bool Changed = false;
2055
2056 LLVM_DEBUG(dbgs() << "AMDIC: process function ";
2057 F.printAsOperand(dbgs(), false, F.getParent()); dbgs() << '\n';);
2058
2059 for (auto &BB : F) {
2060 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E;) {
2061 // Ignore non-calls.
2063 ++I;
2064
2065 if (CI) {
2066 if (Simplifier.fold(CI))
2067 Changed = true;
2068 }
2069 }
2070 }
2072}
2073
2076 if (UseNative.empty())
2077 return PreservedAnalyses::all();
2078
2079 AMDGPULibCalls Simplifier(F, AM);
2080 Simplifier.initNativeFuncs();
2081
2082 bool Changed = false;
2083 for (auto &BB : F) {
2084 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E;) {
2085 // Ignore non-calls.
2087 ++I;
2088 if (CI && Simplifier.useNative(CI))
2089 Changed = true;
2090 }
2091 }
2093}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static const TableEntry tbl_log[]
static const TableEntry tbl_tgamma[]
static AMDGPULibFunc::EType getArgType(const AMDGPULibFunc &FInfo)
static const TableEntry tbl_expm1[]
static const TableEntry tbl_asinpi[]
static const TableEntry tbl_cos[]
#define MATH_SQRT2
static const TableEntry tbl_exp10[]
static CallInst * CreateCallEx(IRB &B, FunctionCallee Callee, Value *Arg, const Twine &Name="")
static CallInst * CreateCallEx2(IRB &B, FunctionCallee Callee, Value *Arg1, Value *Arg2, const Twine &Name="")
static const TableEntry tbl_rsqrt[]
static const TableEntry tbl_atanh[]
static const TableEntry tbl_cosh[]
static const TableEntry tbl_asin[]
static const TableEntry tbl_sinh[]
static const TableEntry tbl_acos[]
static const TableEntry tbl_tan[]
static const TableEntry tbl_cospi[]
static const TableEntry tbl_tanpi[]
static cl::opt< bool > EnablePreLink("amdgpu-prelink", cl::desc("Enable pre-link mode optimizations"), cl::init(false), cl::Hidden)
static bool HasNative(AMDGPULibFunc::EFuncId id)
static Value * emitIsInf(IRBuilder<> &B, Value *val)
ArrayRef< TableEntry > TableRef
static int getVecSize(const AMDGPULibFunc &FInfo)
static Value * emitFastExpYLnx(IRBuilder<> &B, Value *X, Value *Y)
static Value * emitIsInteger(IRBuilder<> &B, Value *Y)
static Value * emitIsEvenInteger(IRBuilder<> &B, Value *Y)
static const TableEntry tbl_sin[]
static const TableEntry tbl_atan[]
static const TableEntry tbl_log2[]
static Constant * getConstantFloat(const ArrayRef< APFloat > Values, const Type *Ty)
static const TableEntry tbl_acospi[]
static Value * emitPowFixup(IRBuilder<> &B, Value *X, Value *Y, Value *ExpYLnX, PowKind Kind)
Emit special case management epilog code for fast pow, powr, pown, and rootn expansions.
static const TableEntry tbl_sqrt[]
static const TableEntry tbl_asinh[]
#define MATH_E
static TableRef getOptTable(AMDGPULibFunc::EFuncId id)
static const TableEntry tbl_acosh[]
static const TableEntry tbl_exp[]
static const TableEntry tbl_cbrt[]
static const TableEntry tbl_sinpi[]
static const TableEntry tbl_atanpi[]
#define MATH_PI
static FunctionType * getPownType(FunctionType *FT)
static const TableEntry tbl_erf[]
static const TableEntry tbl_log10[]
#define MATH_SQRT1_2
static const TableEntry tbl_erfc[]
static cl::list< std::string > UseNative("amdgpu-use-native", cl::desc("Comma separated list of functions to replace with native, or all"), cl::CommaSeparated, cl::ValueOptional, cl::Hidden)
static const TableEntry tbl_tanh[]
static Value * emitIsOddInteger(IRBuilder<> &B, Value *Y)
static const TableEntry tbl_exp2[]
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
loop term fold
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
FunctionAnalysisManager FAM
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
static void replaceCall(FPMathOperator *I, Value *With)
bool isUnsafeFiniteOnlyMath(const FPMathOperator *FPOp) const
bool canIncreasePrecisionOfConstantFold(const FPMathOperator *FPOp) const
bool fold(CallInst *CI)
static void replaceCall(Instruction *I, Value *With)
AMDGPULibCalls(Function &F, FunctionAnalysisManager &FAM)
bool useNative(CallInst *CI)
static unsigned getEPtrKindFromAddrSpace(unsigned AS)
Wrapper class for AMDGPULIbFuncImpl.
static bool parse(StringRef MangledName, AMDGPULibFunc &Ptr)
std::string getName() const
Get unmangled name for mangled library function and name for unmangled library function.
static FunctionCallee getOrInsertFunction(llvm::Module *M, const AMDGPULibFunc &fInfo)
void setPrefix(ENamePrefix PFX)
bool isCompatibleSignature(const Module &M, const FunctionType *FuncTy) const
EFuncId getId() const
bool isMangled() const
Param * getLeads()
Get leading parameters for mangled lib functions.
void setId(EFuncId Id)
ENamePrefix getPrefix() const
static constexpr roundingMode rmNearestTiesToEven
Definition APFloat.h:361
bool isNegative() const
Definition APFloat.h:1583
LLVM_ABI double convertToDouble() const
Converts this APFloat to host double value.
Definition APFloat.cpp:6093
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
Definition APFloat.h:1566
LLVM_ABI float convertToFloat() const
Converts this APFloat to host float value.
Definition APFloat.cpp:6121
bool isZero() const
Definition APFloat.h:1579
LLVM_READONLY bool isOne() const
Definition APFloat.h:1661
LLVM_READONLY bool isMinusOne() const
Definition APFloat.h:1664
int64_t getSExtValue() const
Get sign extended value.
Definition APInt.h:1582
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
A function analysis which provides an AssumptionCache.
static LLVM_ABI Attribute getWithNoFPClass(LLVMContext &Context, FPClassTest Mask)
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
void setCallingConv(CallingConv::ID CC)
void removeParamAttrs(unsigned ArgNo, const AttributeMask &AttrsToRemove)
Removes the attributes from the given argument.
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...
bool isStrictFP() const
Determine if the call requires strict floating point semantics.
AttributeSet getParamAttributes(unsigned ArgNo) const
Return the param attributes for this call.
bool isNoInline() const
Return true if the call should not be inlined.
void addRetAttr(Attribute::AttrKind Kind)
Adds the attribute to the return value.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
FunctionType * getFunctionType() const
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
LLVM_ABI APFloat getElementAsAPFloat(uint64_t i) const
If this is a sequential container of floating point type, return the specified element as an APFloat.
LLVM_ABI uint64_t getNumElements() const
Return the number of elements in the array or vector.
static LLVM_ABI Constant * getSplat(unsigned NumElts, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
static LLVM_ABI Constant * get(LLVMContext &Context, ArrayRef< uint8_t > Elts)
get() constructors - Return a constant with vector type with an element count and element type matchi...
const APFloat & getValueAPF() const
Definition Constants.h:463
static LLVM_ABI ConstantFP * getZero(Type *Ty, bool Negative=false)
static LLVM_ABI ConstantFP * getQNaN(Type *Ty, bool Negative=false, APInt *Payload=nullptr)
LLVM_ABI bool isExactlyValue(const APFloat &V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
static LLVM_ABI ConstantFP * getInfinity(Type *Ty, bool Negative=false)
This is the shared class of boolean and integer constants.
Definition Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition Constants.h:168
Align getAlignValue() const
Return the constant as an llvm::Align, interpreting 0 as Align(1).
Definition Constants.h:186
static LLVM_ABI Constant * get(ArrayRef< Constant * > V)
This is an important base class in LLVM.
Definition Constant.h:43
LLVM_ABI Constant * getAggregateElement(unsigned Elt) const
For aggregates (struct/array/vector) return the constant that corresponds to the specified element if...
static LLVM_ABI DILocation * getMergedLocations(ArrayRef< DILocation * > Locs)
Try to combine the vector of locations passed as input in a single one.
Analysis pass which computes a DominatorTree.
Definition Dominators.h:241
Utility class for floating point operations which can have information about relaxed accuracy require...
Definition Operator.h:202
bool isFast() const
Test if this operation allows all non-strict floating-point transforms.
Definition Operator.h:264
bool hasNoNaNs() const
Test if this operation's arguments and results are assumed not-NaN.
Definition Operator.h:270
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
Definition Operator.h:291
bool hasNoSignedZeros() const
Test if this operation can ignore the sign of zero.
Definition Operator.h:276
bool hasNoInfs() const
Test if this operation's arguments and results are assumed not-infinite.
Definition Operator.h:273
bool hasApproxFunc() const
Test if this operation allows approximations of math library functions or intrinsics.
Definition Operator.h:288
LLVM_ABI float getFPAccuracy() const
Get the maximum error permitted by this operation in ULPs.
Convenience struct for specifying and reasoning about fast-math flags.
Definition FMF.h:23
void setAllowContract(bool B=true)
Definition FMF.h:90
bool none() const
Definition FMF.h:57
bool approxFunc() const
Definition FMF.h:70
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionType * getFunctionType()
Type * getParamType(unsigned i) const
Parameter type accessors.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Definition Function.h:696
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:734
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2918
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI void setFastMathFlags(FastMathFlags FMF)
Convenience function for setting multiple fast-math flags on this instruction, which must be an opera...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
static LLVM_ABI MDNode * getMostGenericFPMath(MDNode *A, MDNode *B)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
reference emplace_back(ArgTypes &&... Args)
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Analysis pass providing the TargetLibraryInfo.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
bool isVectorTy() const
True if this is an instance of VectorType.
Definition Type.h:283
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Definition Type.h:155
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
Definition Type.h:363
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:187
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
Definition Type.h:144
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
Definition Type.cpp:222
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
Definition Type.h:158
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition Type.h:252
void dropAllReferences()
Drop all references to operands.
Definition User.h:324
Value * getOperand(unsigned i) const
Definition User.h:207
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
iterator_range< user_iterator > users()
Definition Value.h:428
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:400
Base class of all SIMD vector types.
static LLVM_ABI VectorType * get(Type *ElementType, ElementCount EC)
This static method is the primary way to construct an VectorType.
self_iterator getIterator()
Definition ilist_node.h:123
CallInst * Call
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ FLAT_ADDRESS
Address space for flat memory.
@ PRIVATE_ADDRESS
Address space for private memory.
LLVM_ABI APInt pow(const APInt &X, int64_t N)
Compute X^N for N>=0.
Definition APInt.cpp:3189
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
ap_match< APInt > m_APIntAllowPoison(const APInt *&Res)
Match APInt while allowing poison in splat vector constants.
bool match(Val *V, const Pattern &P)
ap_match< APFloat > m_APFloatAllowPoison(const APFloat *&Res)
Match APFloat while allowing poison in splat vector constants.
initializer< Ty > init(const Ty &Val)
constexpr double ln2
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
static double log2(double V)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1685
RelativeUniformCounterPtr Values
Definition InstrProf.h:91
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
FPClassTest
Floating-point class tests, supported by 'is_fpclass' intrinsic.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
LLVM_ABI bool isKnownIntegral(const Value *V, const SimplifyQuery &SQ, FastMathFlags FMF)
Return true if the floating-point value V is known to be an integer value.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI bool cannotBeOrderedLessThanZero(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if we can prove that the specified FP value is either NaN or never less than -0....
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39