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 uint64_t 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 =
1158 B.getIntNTy(static_cast<unsigned>(eltType->getPrimitiveSizeInBits()));
1159 Type *nTy = FPOp->getType()->getWithNewType(nTyS);
1160 Value *opr_n = FPOp->getOperand(1);
1161 if (opr_n->getType()->getScalarType()->isIntegerTy())
1162 opr_n = B.CreateZExtOrTrunc(opr_n, nTy, "__ytou");
1163 else
1164 opr_n = B.CreateFPToSI(opr1, nTy, "__ytou");
1165
1166 unsigned size = nTy->getScalarSizeInBits();
1167 Value *sign = B.CreateShl(opr_n, size-1, "__yeven");
1168 sign = B.CreateAnd(B.CreateBitCast(opr0, nTy), sign, "__pow_sign");
1169
1170 nval = B.CreateCopySign(nval, B.CreateBitCast(sign, nval->getType()),
1171 nullptr, "__pow_sign");
1172 }
1173
1174 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> "
1175 << "exp2(" << *opr1 << " * log2(" << *opr0 << "))\n");
1176 replaceCall(FPOp, nval);
1177
1178 return true;
1179}
1180
1181bool AMDGPULibCalls::fold_rootn(FPMathOperator *FPOp, IRBuilder<> &B,
1182 const FuncInfo &FInfo) {
1183 Value *opr0 = FPOp->getOperand(0);
1184 Value *opr1 = FPOp->getOperand(1);
1185
1186 const APInt *CINT = nullptr;
1187 if (!match(opr1, m_APIntAllowPoison(CINT)))
1188 return false;
1189
1190 Function *Parent = B.GetInsertBlock()->getParent();
1191
1192 int ci_opr1 = (int)CINT->getSExtValue();
1193 if (ci_opr1 == 1 && !Parent->hasFnAttribute(Attribute::StrictFP)) {
1194 // rootn(x, 1) = x
1195 //
1196 // TODO: Insert constrained canonicalize for strictfp case.
1197 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << '\n');
1198 replaceCall(FPOp, opr0);
1199 return true;
1200 }
1201
1202 Module *M = B.getModule();
1203
1204 CallInst *CI = cast<CallInst>(FPOp);
1205
1206 // rootn and sqrt disagree on signed-zero / -Inf inputs (e.g. rootn(-0.0, 2)
1207 // is +0.0, sqrt(-0.0) is -0.0), so require nsz/ninf.
1208 bool FMFOkForSqrt = FPOp->hasNoSignedZeros() && FPOp->hasNoInfs();
1209
1210 if (ci_opr1 == 2 && FMFOkForSqrt &&
1211 shouldReplaceLibcallWithIntrinsic(CI,
1212 /*AllowMinSizeF32=*/true,
1213 /*AllowF64=*/true)) {
1214 // rootn(x, 2) = sqrt(x)
1215 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> sqrt(" << *opr0 << ")\n");
1216
1217 Value *NewCall = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1218 NewCall->takeName(CI);
1219
1220 // OpenCL rootn has a looser ulp of 2 requirement than sqrt, so add some
1221 // metadata.
1222 MDBuilder MDHelper(M->getContext());
1223 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));
1224 if (auto *NewCallI = dyn_cast<Instruction>(NewCall))
1225 NewCallI->setMetadata(LLVMContext::MD_fpmath, FPMD);
1226
1227 replaceCall(CI, NewCall);
1228 return true;
1229 }
1230
1231 if (ci_opr1 == 3) { // rootn(x, 3) = cbrt(x)
1232 if (FunctionCallee FPExpr =
1233 getFunction(M, AMDGPULibFunc(AMDGPULibFunc::EI_CBRT, FInfo))) {
1234 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> cbrt(" << *opr0
1235 << ")\n");
1236 Value *nval = CreateCallEx(B,FPExpr, opr0, "__rootn2cbrt");
1237 replaceCall(FPOp, nval);
1238 return true;
1239 }
1240 } else if (ci_opr1 == -1) { // rootn(x, -1) = 1.0/x
1241 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1.0 / " << *opr0 << "\n");
1242 Value *nval = B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0),
1243 opr0,
1244 "__rootn2div");
1245 replaceCall(FPOp, nval);
1246 return true;
1247 }
1248
1249 if (ci_opr1 == -2 && FMFOkForSqrt &&
1250 shouldReplaceLibcallWithIntrinsic(CI,
1251 /*AllowMinSizeF32=*/true,
1252 /*AllowF64=*/true)) {
1253 // rootn(x, -2) = rsqrt(x)
1254
1255 // The original rootn had looser ulp requirements than the resultant sqrt
1256 // and fdiv.
1257 MDBuilder MDHelper(M->getContext());
1258 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));
1259
1260 // TODO: Could handle strictfp but need to fix strict sqrt emission
1261 FastMathFlags FMF = FPOp->getFastMathFlags();
1262 FMF.setAllowContract(true);
1263
1264 Value *Sqrt = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1266 B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0), Sqrt));
1267 if (auto *SqrtI = dyn_cast<Instruction>(Sqrt))
1268 SqrtI->setFastMathFlags(FMF);
1269 RSqrt->setFastMathFlags(FMF);
1270 RSqrt->setMetadata(LLVMContext::MD_fpmath, FPMD);
1271
1272 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> rsqrt(" << *opr0
1273 << ")\n");
1274 replaceCall(CI, RSqrt);
1275 return true;
1276 }
1277
1278 return false;
1279}
1280
1281// is_integer(y) => trunc(y) == y
1283 Value *TruncY = B.CreateUnaryIntrinsic(Intrinsic::trunc, Y);
1284 return B.CreateFCmpOEQ(TruncY, Y);
1285}
1286
1288 // Even integers are still integers after division by 2.
1289 auto *HalfY = B.CreateFMul(Y, ConstantFP::get(Y->getType(), 0.5));
1290 return emitIsInteger(B, HalfY);
1291}
1292
1293// is_odd_integer(y) => is_integer(y) && !is_even_integer(y)
1295 Value *IsIntY = emitIsInteger(B, Y);
1296 Value *IsEvenY = emitIsEvenInteger(B, Y);
1297 Value *NotEvenY = B.CreateNot(IsEvenY);
1298 return B.CreateAnd(IsIntY, NotEvenY);
1299}
1300
1301// isinf(val) => fabs(val) == +inf
1303 auto *fabsVal = B.CreateFAbs(val);
1304 return B.CreateFCmpOEQ(fabsVal, ConstantFP::getInfinity(val->getType()));
1305}
1306
1307// y * log2(fabs(x))
1309 Value *AbsX = B.CreateFAbs(X);
1310 Value *LogAbsX = B.CreateUnaryIntrinsic(Intrinsic::log2, AbsX);
1311 Value *YTimesLogX = B.CreateFMul(Y, LogAbsX);
1312 return B.CreateUnaryIntrinsic(Intrinsic::exp2, YTimesLogX);
1313}
1314
1315/// Emit special case management epilog code for fast pow, powr, pown, and rootn
1316/// expansions. \p x and \p y should be the arguments to the library call
1317/// (possibly with some values clamped). \p expylnx should be the result to use
1318/// in normal circumstances.
1320 PowKind Kind) {
1321 Constant *Zero = ConstantFP::getZero(X->getType());
1322 Constant *One = ConstantFP::get(X->getType(), 1.0);
1323 Constant *QNaN = ConstantFP::getQNaN(X->getType());
1324 Constant *PInf = ConstantFP::getInfinity(X->getType());
1325
1326 switch (Kind) {
1327 case PowKind::Pow: {
1328 // is_odd_integer(y)
1329 Value *IsOddY = emitIsOddInteger(B, Y);
1330
1331 // ret = copysign(expylnx, is_odd_y ? x : 1.0f)
1332 Value *SelSign = B.CreateSelect(IsOddY, X, One);
1333 Value *Ret = B.CreateCopySign(ExpYLnX, SelSign);
1334
1335 // if (x < 0 && !is_integer(y)) ret = QNAN
1336 Value *IsIntY = emitIsInteger(B, Y);
1337 Value *condNegX = B.CreateFCmpOLT(X, Zero);
1338 Value *condNotIntY = B.CreateNot(IsIntY);
1339 Value *condNaN = B.CreateAnd(condNegX, condNotIntY);
1340 Ret = B.CreateSelect(condNaN, QNaN, Ret);
1341
1342 // if (isinf(ay)) { ... }
1343
1344 // FIXME: Missing backend optimization to save on materialization cost of
1345 // mixed sign constant infinities.
1346 Value *YIsInf = emitIsInf(B, Y);
1347
1348 Value *AY = B.CreateFAbs(Y);
1349 Value *YIsNegInf = B.CreateFCmpUNE(Y, AY);
1350
1351 Value *AX = B.CreateFAbs(X);
1352 Value *AxEqOne = B.CreateFCmpOEQ(AX, One);
1353 Value *AxLtOne = B.CreateFCmpOLT(AX, One);
1354 Value *XorCond = B.CreateXor(AxLtOne, YIsNegInf);
1355 Value *SelInf =
1356 B.CreateSelect(AxEqOne, AX, B.CreateSelect(XorCond, Zero, AY));
1357 Ret = B.CreateSelect(YIsInf, SelInf, Ret);
1358
1359 // if (isinf(ax) || x == 0.0f) { ... }
1360 Value *XIsInf = emitIsInf(B, X);
1361 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1362 Value *AxInfOrZero = B.CreateOr(XIsInf, XEqZero);
1363 Value *YLtZero = B.CreateFCmpOLT(Y, Zero);
1364 Value *XorZeroInf = B.CreateXor(XEqZero, YLtZero);
1365 Value *SelVal = B.CreateSelect(XorZeroInf, Zero, PInf);
1366 Value *SelSign2 = B.CreateSelect(IsOddY, X, Zero);
1367 Value *Copysign = B.CreateCopySign(SelVal, SelSign2);
1368 Ret = B.CreateSelect(AxInfOrZero, Copysign, Ret);
1369
1370 // if (isunordered(x, y)) ret = QNAN
1371 Value *isUnordered = B.CreateFCmpUNO(X, Y);
1372 return B.CreateSelect(isUnordered, QNaN, Ret);
1373 }
1374 case PowKind::PowR: {
1375 Value *YIsNeg = B.CreateFCmpOLT(Y, Zero);
1376 Value *IZ = B.CreateSelect(YIsNeg, PInf, Zero);
1377 Value *ZI = B.CreateSelect(YIsNeg, Zero, PInf);
1378
1379 Value *YEqZero = B.CreateFCmpOEQ(Y, Zero);
1380 Value *SelZeroCase = B.CreateSelect(YEqZero, QNaN, IZ);
1381 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1382 Value *Ret = B.CreateSelect(XEqZero, SelZeroCase, ExpYLnX);
1383
1384 Value *XEqInf = B.CreateFCmpOEQ(X, PInf);
1385 Value *YNeZero = B.CreateFCmpUNE(Y, Zero);
1386 Value *CondInfCase = B.CreateAnd(XEqInf, YNeZero);
1387 Ret = B.CreateSelect(CondInfCase, ZI, Ret);
1388
1389 Value *IsInfY = emitIsInf(B, Y);
1390 Value *XNeOne = B.CreateFCmpUNE(X, One);
1391 Value *CondInfY = B.CreateAnd(IsInfY, XNeOne);
1392 Value *XLtOne = B.CreateFCmpOLT(X, One);
1393 Value *SelInfYCase = B.CreateSelect(XLtOne, IZ, ZI);
1394 Ret = B.CreateSelect(CondInfY, SelInfYCase, Ret);
1395
1396 Value *IsUnordered = B.CreateFCmpUNO(X, Y);
1397 return B.CreateSelect(IsUnordered, QNaN, Ret);
1398 }
1399 case PowKind::PowN: {
1400 Constant *ZeroI = ConstantInt::get(Y->getType(), 0);
1401
1402 // is_odd_y = (ny & 1) != 0
1403 Value *OneI = ConstantInt::get(Y->getType(), 1);
1404 Value *YAnd1 = B.CreateAnd(Y, OneI);
1405 Value *IsOddY = B.CreateICmpNE(YAnd1, ZeroI);
1406
1407 // ret = copysign(expylnx, is_odd_y ? x : 1.0f)
1408 Value *SelSign = B.CreateSelect(IsOddY, X, One);
1409 Value *Ret = B.CreateCopySign(ExpYLnX, SelSign);
1410
1411 // if (isinf(x) || x == 0.0f)
1412 Value *FabsX = B.CreateFAbs(X);
1413 Value *XIsInf = B.CreateFCmpOEQ(FabsX, PInf);
1414 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1415 Value *InfOrZero = B.CreateOr(XIsInf, XEqZero);
1416
1417 // (x == 0.0f) ^ (ny < 0) ? 0.0f : +inf
1418 Value *YLtZero = B.CreateICmpSLT(Y, ZeroI);
1419 Value *XorZeroInf = B.CreateXor(XEqZero, YLtZero);
1420 Value *SelVal = B.CreateSelect(XorZeroInf, Zero, PInf);
1421
1422 // copysign(selVal, is_odd_y ? x : 0.0f)
1423 Value *SelSign2 = B.CreateSelect(IsOddY, X, Zero);
1424 Value *Copysign = B.CreateCopySign(SelVal, SelSign2);
1425
1426 return B.CreateSelect(InfOrZero, Copysign, Ret);
1427 }
1428 case PowKind::RootN: {
1429 Constant *ZeroI = ConstantInt::get(Y->getType(), 0);
1430
1431 // is_odd_y = (ny & 1) != 0
1432 Value *YAnd1 = B.CreateAnd(Y, ConstantInt::get(Y->getType(), 1));
1433 Value *IsOddY = B.CreateICmpNE(YAnd1, ZeroI);
1434
1435 // ret = copysign(expylnx, is_odd_y ? x : 1.0f)
1436 Value *SelSign = B.CreateSelect(IsOddY, X, One);
1437 Value *Ret = B.CreateCopySign(ExpYLnX, SelSign);
1438
1439 // if (isinf(x) || x == 0.0f)
1440 Value *FabsX = B.CreateFAbs(X);
1441 Value *IsInfX = B.CreateFCmpOEQ(FabsX, PInf);
1442 Value *XEqZero = B.CreateFCmpOEQ(X, Zero);
1443 Value *CondInfOrZero = B.CreateOr(IsInfX, XEqZero);
1444
1445 // (x == 0.0f) ^ (ny < 0) ? 0.0f : +inf
1446 Value *YLtZero = B.CreateICmpSLT(Y, ZeroI);
1447 Value *XorZeroInf = B.CreateXor(XEqZero, YLtZero);
1448 Value *SelVal = B.CreateSelect(XorZeroInf, Zero, PInf);
1449
1450 // copysign(selVal, is_odd_y ? x : 0.0f)
1451 Value *SelSign2 = B.CreateSelect(IsOddY, X, Zero);
1452 Value *Copysign = B.CreateCopySign(SelVal, SelSign2);
1453
1454 Ret = B.CreateSelect(CondInfOrZero, Copysign, Ret);
1455
1456 // if ((x < 0.0f && !is_odd_y) || ny == 0) ret = QNAN
1457 Value *XIsNeg = B.CreateFCmpOLT(X, Zero);
1458 Value *NotOddY = B.CreateNot(IsOddY);
1459 Value *CondNegAndNotOdd = B.CreateAnd(XIsNeg, NotOddY);
1460 Value *YEqZero = B.CreateICmpEQ(Y, ZeroI);
1461 Value *CondBad = B.CreateOr(CondNegAndNotOdd, YEqZero);
1462 return B.CreateSelect(CondBad, QNaN, Ret);
1463 }
1464 }
1465
1466 llvm_unreachable("covered switch");
1467}
1468
1469// TODO: Move the fold_pow folding to sqrt/fdiv here
1470bool AMDGPULibCalls::expandFastPow(FPMathOperator *FPOp, IRBuilder<> &B,
1471 PowKind Kind) {
1472 Type *Ty = FPOp->getType();
1473
1474 // There's currently no reason to do this for half. The correct path is
1475 // promote to float and use the fast float expansion.
1476 //
1477 // TODO: We could move this expansion to lowering to get half pow to work.
1478 if (!Ty->getScalarType()->isFloatTy())
1479 return false;
1480
1481 // TODO: Verify optimization for double and bfloat.
1482 Value *X = FPOp->getOperand(0);
1483 Value *Y = FPOp->getOperand(1);
1484
1485 switch (Kind) {
1486 case PowKind::Pow: {
1487 Constant *One = ConstantFP::get(X->getType(), 1.0);
1488
1489 // if (x == 1.0f) y = 1.0f;
1490 Value *XEqOne = B.CreateFCmpOEQ(X, One);
1491 Y = B.CreateSelect(XEqOne, One, Y);
1492
1493 // if (y == 0.0f) x = 1.0f;
1494 Value *YEqZero = B.CreateFCmpOEQ(Y, ConstantFP::getZero(X->getType()));
1495 X = B.CreateSelect(YEqZero, One, X);
1496
1497 Value *ExpYLnX = emitFastExpYLnx(B, X, Y);
1498 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1499 replaceCall(FPOp, Fixed);
1500 return true;
1501 }
1502 case PowKind::PowR: {
1503 Value *NegX = B.CreateFCmpOLT(X, ConstantFP::getZero(X->getType()));
1504 X = B.CreateSelect(NegX, ConstantFP::getQNaN(X->getType()), X);
1505
1506 Value *ExpYLnX = emitFastExpYLnx(B, X, Y);
1507 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1508 replaceCall(FPOp, Fixed);
1509 return true;
1510 }
1511 case PowKind::PowN: {
1512 // ny == 0
1513 Value *YEqZero = B.CreateICmpEQ(Y, ConstantInt::get(Y->getType(), 0));
1514
1515 // x = (ny == 0 ? 1.0f : x)
1516 X = B.CreateSelect(YEqZero, ConstantFP::get(X->getType(), 1.0), X);
1517
1518 Value *CastY = B.CreateSIToFP(Y, X->getType());
1519 Value *ExpYLnX = emitFastExpYLnx(B, X, CastY);
1520 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1521 replaceCall(FPOp, Fixed);
1522 return true;
1523 }
1524 case PowKind::RootN: {
1525 Value *CastY = B.CreateSIToFP(Y, X->getType());
1526
1527 // This is afn anyway, so we will turn into rcp.
1528 Value *RcpY = B.CreateFDiv(ConstantFP::get(X->getType(), 1.0), CastY);
1529
1530 Value *ExpYLnX = emitFastExpYLnx(B, X, RcpY);
1531 Value *Fixed = emitPowFixup(B, X, Y, ExpYLnX, Kind);
1532 replaceCall(FPOp, Fixed);
1533 return true;
1534 }
1535 }
1536 llvm_unreachable("Unhandled PowKind enum");
1537}
1538
1539bool AMDGPULibCalls::tryOptimizePow(FPMathOperator *FPOp, IRBuilder<> &B,
1540 const FuncInfo &FInfo) {
1541 FastMathFlags FMF = FPOp->getFastMathFlags();
1542 CallInst *Call = cast<CallInst>(FPOp);
1543 Module *M = Call->getModule();
1544
1545 FuncInfo PowrInfo;
1546 AMDGPULibFunc::EFuncId FastPowrFuncId =
1547 FMF.approxFunc() || FInfo.getId() == AMDGPULibFunc::EI_POW_FAST
1550 FunctionCallee PowrFunc = getFloatFastVariant(
1551 M, FInfo, PowrInfo, AMDGPULibFunc::EI_POWR, FastPowrFuncId);
1552
1553 // TODO: Prefer fast pown to fast powr, but slow powr to slow pown.
1554
1555 // pow(x, y) -> powr(x, y) for x >= -0.0
1556 // TODO: Account for flags on current call
1557 if (PowrFunc && cannotBeOrderedLessThanZero(FPOp->getOperand(0),
1558 SQ.getWithInstruction(Call))) {
1559 Call->setCalledFunction(PowrFunc);
1560 return fold_pow(FPOp, B, PowrInfo) || true;
1561 }
1562
1563 // pow(x, y) -> pown(x, y) for known integral y
1564 if (isKnownIntegral(FPOp->getOperand(1), SQ.getWithInstruction(Call),
1565 FPOp->getFastMathFlags())) {
1566 FunctionType *PownType = getPownType(Call->getFunctionType());
1567
1568 FuncInfo PownInfo;
1569 AMDGPULibFunc::EFuncId FastPownFuncId =
1570 FMF.approxFunc() || FInfo.getId() == AMDGPULibFunc::EI_POW_FAST
1573 FunctionCallee PownFunc = getFloatFastVariant(
1574 M, FInfo, PownInfo, AMDGPULibFunc::EI_POWN, FastPownFuncId);
1575
1576 if (PownFunc) {
1577 // TODO: If the incoming integral value is an sitofp/uitofp, it won't
1578 // fold out without a known range. We can probably take the source
1579 // value directly.
1580 Value *CastedArg =
1581 B.CreateFPToSI(FPOp->getOperand(1), PownType->getParamType(1));
1582 // Have to drop any nofpclass attributes on the original call site.
1584 1, AttributeFuncs::typeIncompatible(CastedArg->getType(),
1586 Call->setCalledFunction(PownFunc);
1587 Call->setArgOperand(1, CastedArg);
1588 return fold_pow(FPOp, B, PownInfo) || true;
1589 }
1590 }
1591
1592 if (fold_pow(FPOp, B, FInfo))
1593 return true;
1594
1595 if (!FMF.approxFunc())
1596 return false;
1597
1598 if (FInfo.getId() == AMDGPULibFunc::EI_POW && FMF.approxFunc() &&
1599 getArgType(FInfo) == AMDGPULibFunc::F32) {
1600 AMDGPULibFunc PowFastInfo(AMDGPULibFunc::EI_POW_FAST, FInfo);
1601 if (FunctionCallee PowFastFunc = getFunction(M, PowFastInfo)) {
1602 Call->setCalledFunction(PowFastFunc);
1603 return fold_pow(FPOp, B, PowFastInfo) || true;
1604 }
1605 }
1606
1607 return expandFastPow(FPOp, B, PowKind::Pow);
1608}
1609
1610// Some library calls are just wrappers around llvm intrinsics, but compiled
1611// conservatively. Preserve the flags from the original call site by
1612// substituting them with direct calls with all the flags.
1613bool AMDGPULibCalls::shouldReplaceLibcallWithIntrinsic(const CallInst *CI,
1614 bool AllowMinSizeF32,
1615 bool AllowF64,
1616 bool AllowStrictFP) {
1617 Type *FltTy = CI->getType()->getScalarType();
1618 const bool IsF32 = FltTy->isFloatTy();
1619
1620 // f64 intrinsics aren't implemented for most operations.
1621 if (!IsF32 && !FltTy->isHalfTy() && (!AllowF64 || !FltTy->isDoubleTy()))
1622 return false;
1623
1624 // We're implicitly inlining by replacing the libcall with the intrinsic, so
1625 // don't do it for noinline call sites.
1626 if (CI->isNoInline())
1627 return false;
1628
1629 const Function *ParentF = CI->getFunction();
1630 // TODO: Handle strictfp
1631 if (!AllowStrictFP && ParentF->hasFnAttribute(Attribute::StrictFP))
1632 return false;
1633
1634 if (IsF32 && !AllowMinSizeF32 && ParentF->hasMinSize())
1635 return false;
1636 return true;
1637}
1638
1639void AMDGPULibCalls::replaceLibCallWithSimpleIntrinsic(IRBuilder<> &B,
1640 CallInst *CI,
1641 Intrinsic::ID IntrID) {
1642 if (CI->arg_size() == 2) {
1643 Value *Arg0 = CI->getArgOperand(0);
1644 Value *Arg1 = CI->getArgOperand(1);
1645 VectorType *Arg0VecTy = dyn_cast<VectorType>(Arg0->getType());
1646 VectorType *Arg1VecTy = dyn_cast<VectorType>(Arg1->getType());
1647 if (Arg0VecTy && !Arg1VecTy) {
1648 Value *SplatRHS = B.CreateVectorSplat(Arg0VecTy->getElementCount(), Arg1);
1649 CI->setArgOperand(1, SplatRHS);
1650 } else if (!Arg0VecTy && Arg1VecTy) {
1651 Value *SplatLHS = B.CreateVectorSplat(Arg1VecTy->getElementCount(), Arg0);
1652 CI->setArgOperand(0, SplatLHS);
1653 }
1654 }
1655
1657 CI->getModule(), IntrID, {CI->getType()}));
1659}
1660
1661bool AMDGPULibCalls::tryReplaceLibcallWithSimpleIntrinsic(
1662 IRBuilder<> &B, CallInst *CI, Intrinsic::ID IntrID, bool AllowMinSizeF32,
1663 bool AllowF64, bool AllowStrictFP) {
1664 if (!shouldReplaceLibcallWithIntrinsic(CI, AllowMinSizeF32, AllowF64,
1665 AllowStrictFP))
1666 return false;
1667 replaceLibCallWithSimpleIntrinsic(B, CI, IntrID);
1668 return true;
1669}
1670
1671std::tuple<Value *, Value *, Value *>
1672AMDGPULibCalls::insertSinCos(Value *Arg, FastMathFlags FMF, IRBuilder<> &B,
1673 FunctionCallee Fsincos) {
1674 DebugLoc DL = B.getCurrentDebugLocation();
1675 Function *F = B.GetInsertBlock()->getParent();
1676 B.SetInsertPointPastAllocas(F);
1677
1678 AllocaInst *Alloc = B.CreateAlloca(Arg->getType(), nullptr, "__sincos_");
1679
1680 if (Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
1681 // If the argument is an instruction, it must dominate all uses so put our
1682 // sincos call there. Otherwise, right after the allocas works well enough
1683 // if it's an argument or constant.
1684
1685 B.SetInsertPoint(*ArgInst->getInsertionPointAfterDef());
1686
1687 // SetInsertPoint unwelcomely always tries to set the debug loc.
1688 B.SetCurrentDebugLocation(DL);
1689 }
1690
1691 Type *CosPtrTy = Fsincos.getFunctionType()->getParamType(1);
1692
1693 // The allocaInst allocates the memory in private address space. This need
1694 // to be addrspacecasted to point to the address space of cos pointer type.
1695 // In OpenCL 2.0 this is generic, while in 1.2 that is private.
1696 Value *CastAlloc = B.CreateAddrSpaceCast(Alloc, CosPtrTy);
1697
1698 CallInst *SinCos = CreateCallEx2(B, Fsincos, Arg, CastAlloc);
1699
1700 // TODO: Is it worth trying to preserve the location for the cos calls for the
1701 // load?
1702
1703 LoadInst *LoadCos = B.CreateLoad(Arg->getType(), Alloc);
1704 return {SinCos, LoadCos, SinCos};
1705}
1706
1707// fold sin, cos -> sincos.
1708bool AMDGPULibCalls::fold_sincos(FPMathOperator *FPOp, IRBuilder<> &B,
1709 const FuncInfo &fInfo) {
1710 assert(fInfo.getId() == AMDGPULibFunc::EI_SIN ||
1711 fInfo.getId() == AMDGPULibFunc::EI_COS);
1712
1713 if ((getArgType(fInfo) != AMDGPULibFunc::F32 &&
1714 getArgType(fInfo) != AMDGPULibFunc::F64) ||
1715 fInfo.getPrefix() != AMDGPULibFunc::NOPFX)
1716 return false;
1717
1718 bool const isSin = fInfo.getId() == AMDGPULibFunc::EI_SIN;
1719
1720 Value *CArgVal = FPOp->getOperand(0);
1721
1722 // TODO: Constant fold the call
1723 if (isa<ConstantData>(CArgVal))
1724 return false;
1725
1726 CallInst *CI = cast<CallInst>(FPOp);
1727
1728 Function *F = B.GetInsertBlock()->getParent();
1729 Module *M = F->getParent();
1730
1731 // Merge the sin and cos. For OpenCL 2.0, there may only be a generic pointer
1732 // implementation. Prefer the private form if available.
1733 AMDGPULibFunc SinCosLibFuncPrivate(AMDGPULibFunc::EI_SINCOS, fInfo);
1734 SinCosLibFuncPrivate.getLeads()[0].PtrKind =
1736
1737 AMDGPULibFunc SinCosLibFuncGeneric(AMDGPULibFunc::EI_SINCOS, fInfo);
1738 SinCosLibFuncGeneric.getLeads()[0].PtrKind =
1740
1741 FunctionCallee FSinCosPrivate = getFunction(M, SinCosLibFuncPrivate);
1742 FunctionCallee FSinCosGeneric = getFunction(M, SinCosLibFuncGeneric);
1743 FunctionCallee FSinCos = FSinCosPrivate ? FSinCosPrivate : FSinCosGeneric;
1744 if (!FSinCos)
1745 return false;
1746
1747 SmallVector<CallInst *> SinCalls;
1748 SmallVector<CallInst *> CosCalls;
1749 SmallVector<CallInst *> SinCosCalls;
1750 FuncInfo PartnerInfo(isSin ? AMDGPULibFunc::EI_COS : AMDGPULibFunc::EI_SIN,
1751 fInfo);
1752 const std::string PairName = PartnerInfo.mangle();
1753
1754 StringRef SinName = isSin ? CI->getCalledFunction()->getName() : PairName;
1755 StringRef CosName = isSin ? PairName : CI->getCalledFunction()->getName();
1756 const std::string SinCosPrivateName = SinCosLibFuncPrivate.mangle();
1757 const std::string SinCosGenericName = SinCosLibFuncGeneric.mangle();
1758
1759 // Intersect the two sets of flags.
1760 FastMathFlags FMF = FPOp->getFastMathFlags();
1761 MDNode *FPMath = CI->getMetadata(LLVMContext::MD_fpmath);
1762
1763 SmallVector<DILocation *> MergeDbgLocs = {CI->getDebugLoc()};
1764
1765 for (User* U : CArgVal->users()) {
1766 CallInst *XI = dyn_cast<CallInst>(U);
1767 if (!XI || XI->getFunction() != F || XI->isNoBuiltin())
1768 continue;
1769
1770 Function *UCallee = XI->getCalledFunction();
1771 if (!UCallee)
1772 continue;
1773
1774 bool Handled = true;
1775
1776 if (UCallee->getName() == SinName)
1777 SinCalls.push_back(XI);
1778 else if (UCallee->getName() == CosName)
1779 CosCalls.push_back(XI);
1780 else if (UCallee->getName() == SinCosPrivateName ||
1781 UCallee->getName() == SinCosGenericName)
1782 SinCosCalls.push_back(XI);
1783 else
1784 Handled = false;
1785
1786 if (Handled) {
1787 MergeDbgLocs.push_back(XI->getDebugLoc());
1788 auto *OtherOp = cast<FPMathOperator>(XI);
1789 FMF &= OtherOp->getFastMathFlags();
1791 FPMath, XI->getMetadata(LLVMContext::MD_fpmath));
1792 }
1793 }
1794
1795 if (SinCalls.empty() || CosCalls.empty())
1796 return false;
1797
1798 // insertSinCos needs an insertion point after the argument's def.
1799 if (auto *ArgInst = dyn_cast<Instruction>(CArgVal);
1800 ArgInst && !ArgInst->getInsertionPointAfterDef())
1801 return false;
1802
1803 B.setFastMathFlags(FMF);
1804 B.setDefaultFPMathTag(FPMath);
1805 DILocation *DbgLoc = DILocation::getMergedLocations(MergeDbgLocs);
1806 B.SetCurrentDebugLocation(DbgLoc);
1807
1808 auto [Sin, Cos, SinCos] = insertSinCos(CArgVal, FMF, B, FSinCos);
1809
1810 auto replaceTrigInsts = [](ArrayRef<CallInst *> Calls, Value *Res) {
1811 for (CallInst *C : Calls)
1812 C->replaceAllUsesWith(Res);
1813
1814 // Leave the other dead instructions to avoid clobbering iterators.
1815 };
1816
1817 replaceTrigInsts(SinCalls, Sin);
1818 replaceTrigInsts(CosCalls, Cos);
1819 replaceTrigInsts(SinCosCalls, SinCos);
1820
1821 // It's safe to delete the original now.
1822 CI->eraseFromParent();
1823 return true;
1824}
1825
1826bool AMDGPULibCalls::evaluateScalarMathFunc(const FuncInfo &FInfo,
1827 APFloat &Res0, APFloat &Res1,
1828 Constant *copr0, Constant *copr1) {
1829 // Every function handled below reads its first operand as a floating-point
1830 // value. Refuse anything else, e.g. a poison vector lane: silently treating
1831 // it as 0.0 misfolds the whole call.
1833 if (!fpopr0)
1834 return false;
1835
1836 double opr0 = (getArgType(FInfo) == AMDGPULibFunc::F64)
1837 ? fpopr0->getValueAPF().convertToDouble()
1838 : (double)fpopr0->getValueAPF().convertToFloat();
1839
1840 switch (FInfo.getId()) {
1841 default:
1842 return false;
1843
1845 Res0 = APFloat{acos(opr0)};
1846 return true;
1847
1849 // acosh(x) == log(x + sqrt(x*x - 1))
1850 Res0 = APFloat{log(opr0 + sqrt(opr0 * opr0 - 1.0))};
1851 return true;
1852
1854 Res0 = APFloat{acos(opr0) / MATH_PI};
1855 return true;
1856
1858 Res0 = APFloat{asin(opr0)};
1859 return true;
1860
1862 // asinh(x) == log(x + sqrt(x*x + 1))
1863 Res0 = APFloat{log(opr0 + sqrt(opr0 * opr0 + 1.0))};
1864 return true;
1865
1867 Res0 = APFloat{asin(opr0) / MATH_PI};
1868 return true;
1869
1871 Res0 = APFloat{atan(opr0)};
1872 return true;
1873
1875 // atanh(x) == (log(x+1) - log(x-1))/2;
1876 Res0 = APFloat{(log(opr0 + 1.0) - log(opr0 - 1.0)) / 2.0};
1877 return true;
1878
1880 Res0 = APFloat{atan(opr0) / MATH_PI};
1881 return true;
1882
1884 Res0 =
1885 APFloat{(opr0 < 0.0) ? -pow(-opr0, 1.0 / 3.0) : pow(opr0, 1.0 / 3.0)};
1886 return true;
1887
1889 Res0 = APFloat{cos(opr0)};
1890 return true;
1891
1893 Res0 = APFloat{cosh(opr0)};
1894 return true;
1895
1897 Res0 = APFloat{cos(MATH_PI * opr0)};
1898 return true;
1899
1901 Res0 = APFloat{std::exp(opr0)};
1902 return true;
1903
1905 Res0 = APFloat{pow(2.0, opr0)};
1906 return true;
1907
1909 Res0 = APFloat{pow(10.0, opr0)};
1910 return true;
1911
1913 Res0 = APFloat{log(opr0)};
1914 return true;
1915
1917 Res0 = APFloat{log(opr0) / log(2.0)};
1918 return true;
1919
1921 Res0 = APFloat{log(opr0) / log(10.0)};
1922 return true;
1923
1925 Res0 = APFloat{1.0 / sqrt(opr0)};
1926 return true;
1927
1929 Res0 = APFloat{sin(opr0)};
1930 return true;
1931
1933 Res0 = APFloat{sinh(opr0)};
1934 return true;
1935
1937 Res0 = APFloat{sin(MATH_PI * opr0)};
1938 return true;
1939
1941 Res0 = APFloat{tan(opr0)};
1942 return true;
1943
1945 Res0 = APFloat{tanh(opr0)};
1946 return true;
1947
1949 Res0 = APFloat{tan(MATH_PI * opr0)};
1950 return true;
1951
1952 // two-arg functions
1956 if (!fpopr1)
1957 return false;
1958 double opr1 = (getArgType(FInfo) == AMDGPULibFunc::F64)
1959 ? fpopr1->getValueAPF().convertToDouble()
1960 : (double)fpopr1->getValueAPF().convertToFloat();
1961 Res0 = APFloat{pow(opr0, opr1)};
1962 return true;
1963 }
1964
1966 if (ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
1967 double val = (double)iopr1->getSExtValue();
1968 Res0 = APFloat{pow(opr0, val)};
1969 return true;
1970 }
1971 return false;
1972 }
1973
1975 if (ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
1976 double val = (double)iopr1->getSExtValue();
1977 Res0 = APFloat{pow(opr0, 1.0 / val)};
1978 return true;
1979 }
1980 return false;
1981 }
1982
1983 // with ptr arg
1985 Res0 = APFloat{sin(opr0)};
1986 Res1 = APFloat{cos(opr0)};
1987 return true;
1988 }
1989
1990 return false;
1991}
1992
1993bool AMDGPULibCalls::evaluateCall(CallInst *aCI, const FuncInfo &FInfo) {
1994 int numArgs = (int)aCI->arg_size();
1995 if (numArgs > 3)
1996 return false;
1997
1998 Constant *copr0 = nullptr;
1999 Constant *copr1 = nullptr;
2000 if (numArgs > 0) {
2001 if ((copr0 = dyn_cast<Constant>(aCI->getArgOperand(0))) == nullptr)
2002 return false;
2003 }
2004
2005 if (numArgs > 1) {
2006 if ((copr1 = dyn_cast<Constant>(aCI->getArgOperand(1))) == nullptr) {
2007 if (FInfo.getId() != AMDGPULibFunc::EI_SINCOS)
2008 return false;
2009 }
2010 }
2011
2012 // At this point, all arguments to aCI are constants.
2013
2014 // max vector size is 16, and sincos will generate two results.
2015 SmallVector<APFloat, 16> Val0, Val1;
2016 int FuncVecSize = getVecSize(FInfo);
2017 if (FuncVecSize == 1) {
2018 if (!evaluateScalarMathFunc(FInfo, Val0.emplace_back(0.0),
2019 Val1.emplace_back(0.0), copr0, copr1)) {
2020 return false;
2021 }
2022 } else {
2023 // An operand of a vector variant is not necessarily a vector: sincos takes
2024 // a pointer as its second operand, and fmin/fmax/ldexp accept an
2025 // implicitly splatted scalar. Only index into actual vectors.
2026 Constant *CV0 = copr0 && copr0->getType()->isVectorTy() ? copr0 : nullptr;
2027 Constant *CV1 = copr1 && copr1->getType()->isVectorTy() ? copr1 : nullptr;
2028 for (int i = 0; i < FuncVecSize; ++i) {
2029 Constant *celt0 = CV0 ? CV0->getAggregateElement((unsigned)i) : nullptr;
2030 Constant *celt1 = CV1 ? CV1->getAggregateElement((unsigned)i) : nullptr;
2031 if (!evaluateScalarMathFunc(FInfo, Val0.emplace_back(0.0),
2032 Val1.emplace_back(0.0), celt0, celt1)) {
2033 return false;
2034 }
2035 }
2036 }
2037
2038 Constant *nval0 = getConstantFloat(Val0, aCI->getType());
2039
2040 // sincos
2041 if (FInfo.getId() == AMDGPULibFunc::EI_SINCOS) {
2042 Constant *nval1 = getConstantFloat(Val1, aCI->getType());
2043 new StoreInst(nval1, aCI->getArgOperand(1), aCI->getIterator());
2044 }
2045
2046 replaceCall(aCI, nval0);
2047 return true;
2048}
2049
2052 AMDGPULibCalls Simplifier(F, AM);
2053 Simplifier.initNativeFuncs();
2054
2055 bool Changed = false;
2056
2057 LLVM_DEBUG(dbgs() << "AMDIC: process function ";
2058 F.printAsOperand(dbgs(), false, F.getParent()); dbgs() << '\n';);
2059
2060 for (auto &BB : F) {
2061 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E;) {
2062 // Ignore non-calls.
2064 ++I;
2065
2066 if (CI) {
2067 if (Simplifier.fold(CI))
2068 Changed = true;
2069 }
2070 }
2071 }
2073}
2074
2077 if (UseNative.empty())
2078 return PreservedAnalyses::all();
2079
2080 AMDGPULibCalls Simplifier(F, AM);
2081 Simplifier.initNativeFuncs();
2082
2083 bool Changed = false;
2084 for (auto &BB : F) {
2085 for (BasicBlock::iterator I = BB.begin(), E = BB.end(); I != E;) {
2086 // Ignore non-calls.
2088 ++I;
2089 if (CI && Simplifier.useNative(CI))
2090 Changed = true;
2091 }
2092 }
2094}
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 char 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:6104
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:6132
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:731
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2909
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:549
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:315
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
Definition Value.cpp:396
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:3199
@ 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