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