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