LLVM: lib/Target/AMDGPU/AMDGPULibCalls.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
24#include
25
26#define DEBUG_TYPE "amdgpu-simplifylib"
27
28using namespace llvm;
30
32 cl::desc("Enable pre-link mode optimizations"),
35
37 cl::desc("Comma separated list of functions to replace with native, or all"),
40
41#define MATH_PI numbers::pi
42#define MATH_E numbers::e
43#define MATH_SQRT2 numbers::sqrt2
44#define MATH_SQRT1_2 numbers::inv_sqrt2
45
46namespace llvm {
47
49private:
53
55
56
57 bool AllNative = false;
58
59 bool useNativeFunc(const StringRef F) const;
60
61
62
64
65 bool parseFunctionName(const StringRef &FMangledName, FuncInfo &FInfo);
66
67 bool TDOFold(CallInst *CI, const FuncInfo &FInfo);
68
69
70
71
73
74
76
77
78 bool sincosUseNative(CallInst *aCI, const FuncInfo &FInfo);
79
80
81 bool evaluateScalarMathFunc(const FuncInfo &FInfo, double &Res0, double &Res1,
83 bool evaluateCall(CallInst *aCI, const FuncInfo &FInfo);
84
85
86
87 std::tuple<Value *, Value *, Value *> insertSinCos(Value *Arg,
91
92
94
95
97 const FuncInfo &FInfo);
98
99
101
102
103
104 bool shouldReplaceLibcallWithIntrinsic(const CallInst *CI,
105 bool AllowMinSizeF32 = false,
106 bool AllowF64 = false,
107 bool AllowStrictFP = false);
110
113 bool AllowMinSizeF32 = false,
114 bool AllowF64 = false,
115 bool AllowStrictFP = false);
116
117protected:
119
121
123 I->replaceAllUsesWith(With);
124 I->eraseFromParent();
125 }
126
130
131public:
133
135
138
139
141};
142
143}
144
145template
147 const Twine &Name = "") {
148 CallInst *R = B.CreateCall(Callee, Arg, Name);
150 R->setCallingConv(F->getCallingConv());
151 return R;
152}
153
154template
156 Value *Arg2, const Twine &Name = "") {
157 CallInst *R = B.CreateCall(Callee, {Arg1, Arg2}, Name);
159 R->setCallingConv(F->getCallingConv());
160 return R;
161}
162
166 PowNExpTy = VectorType::get(PowNExpTy, VecTy->getElementCount());
167
169 {FT->getParamType(0), PowNExpTy}, false);
170}
171
172
173
174
179
180
191 {0.5, 0.0},
192 {0.5, -0.0},
193 {0.0, 1.0},
194 {1.0, -1.0}
195};
197 {0.0, 0.0},
198 {-0.0, -0.0},
201};
203 {0.0, 0.0},
204 {-0.0, -0.0}
205};
207 {0.0, 0.0},
208 {-0.0, -0.0},
209 {0.5, 1.0},
210 {-0.5, -1.0}
211};
213 {0.0, 0.0},
214 {-0.0, -0.0},
217};
219 {0.0, 0.0},
220 {-0.0, -0.0}
221};
223 {0.0, 0.0},
224 {-0.0, -0.0},
225 {0.25, 1.0},
226 {-0.25, -1.0}
227};
229 {0.0, 0.0},
230 {-0.0, -0.0},
231 {1.0, 1.0},
232 {-1.0, -1.0},
233};
235 {1.0, 0.0},
236 {1.0, -0.0}
237};
239 {1.0, 0.0},
240 {1.0, -0.0}
241};
243 {1.0, 0.0},
244 {1.0, -0.0}
245};
247 {1.0, 0.0},
248 {1.0, -0.0}
249};
251 {0.0, 0.0},
252 {-0.0, -0.0}
253};
255 {1.0, 0.0},
256 {1.0, -0.0},
258};
260 {1.0, 0.0},
261 {1.0, -0.0},
262 {2.0, 1.0}
263};
265 {1.0, 0.0},
266 {1.0, -0.0},
267 {10.0, 1.0}
268};
270 {0.0, 0.0},
271 {-0.0, -0.0}
272};
278 {0.0, 1.0},
279 {1.0, 2.0}
280};
282 {0.0, 1.0},
283 {1.0, 10.0}
284};
290 {0.0, 0.0},
291 {-0.0, -0.0}
292};
294 {0.0, 0.0},
295 {-0.0, -0.0}
296};
298 {0.0, 0.0},
299 {-0.0, -0.0}
300};
302 {0.0, 0.0},
303 {1.0, 1.0},
305};
307 {0.0, 0.0},
308 {-0.0, -0.0}
309};
311 {0.0, 0.0},
312 {-0.0, -0.0}
313};
315 {0.0, 0.0},
316 {-0.0, -0.0}
317};
319 {1.0, 1.0},
320 {1.0, 2.0},
321 {2.0, 3.0},
322 {6.0, 4.0}
323};
324
326 switch(id) {
342 return true;
343 default:;
344 }
345 return false;
346}
347
349
351 switch(id) {
389 default:;
390 }
392}
393
397
401
402FunctionCallee AMDGPULibCalls::getFunction(Module *M, const FuncInfo &fInfo) {
403
404
405
407 : AMDGPULibFunc::getFunction(M, fInfo);
408}
409
410bool AMDGPULibCalls::parseFunctionName(const StringRef &FMangledName,
411 FuncInfo &FInfo) {
413}
414
418
421
422 return FPOp->isFast();
423}
424
430
431bool AMDGPULibCalls::useNativeFunc(const StringRef F) const {
433}
434
436 AllNative = useNativeFunc("all") ||
439}
440
441bool AMDGPULibCalls::sincosUseNative(CallInst *aCI, const FuncInfo &FInfo) {
442 bool native_sin = useNativeFunc("sin");
443 bool native_cos = useNativeFunc("cos");
444
445 if (native_sin && native_cos) {
448
452
456
460 if (sinExpr && cosExpr) {
466
468 << " with native version of sin/cos");
469
471 return true;
472 }
473 }
474 return false;
475}
476
480 return false;
481
482 FuncInfo FInfo;
483 if (!parseFunctionName(Callee->getName(), FInfo) || !FInfo.isMangled() ||
486 !(AllNative || useNativeFunc(FInfo.getName()))) {
487 return false;
488 }
489
491 return sincosUseNative(aCI, FInfo);
492
495 if ()
496 return false;
497
500 << " with native version");
501 return true;
502}
503
504
505
506
507
508
509
510
512 const FuncInfo &FInfo) {
514 if (!Callee->isDeclaration())
515 return false;
516
517 assert(Callee->hasName() && "Invalid read_pipe/write_pipe function");
518 auto *M = Callee->getParent();
519 std::string Name = std::string(Callee->getName());
520 auto NumArg = CI->arg_size();
521 if (NumArg != 4 && NumArg != 6)
522 return false;
527 if (!PacketSize || !PacketAlign)
528 return false;
529
532 if (Alignment != Size)
533 return false;
534
535 unsigned PtrArgLoc = CI->arg_size() - 3;
538
540 for (unsigned I = 0; I != PtrArgLoc; ++I)
543
544 Name = Name + "_" + std::to_string(Size);
549 if ()
550 return false;
551
553 for (unsigned I = 0; I != PtrArgLoc; ++I)
555 Args.push_back(PtrArg);
556
557 auto *NCI = B.CreateCall(F, Args);
562
563 return true;
564}
565
569 return true;
571 return false;
572
574 return CF->getValueAPF().isInteger();
575
578 if (VFVTy && CV) {
579 unsigned NumElts = VFVTy->getNumElements();
580 for (unsigned i = 0; i != NumElts; ++i) {
582 if (!Elt)
583 return false;
585 continue;
586
589 return false;
590 }
591
592 return true;
593 }
594
596 if ()
597 return false;
598
599 switch (I->getOpcode()) {
600 case Instruction::SIToFP:
601 case Instruction::UIToFP:
602
604 return true;
605
606
607
609 case Instruction::Call: {
612 case Intrinsic::trunc:
613 case Intrinsic:🤣
614 case Intrinsic::ceil:
615 case Intrinsic::rint:
616 case Intrinsic::nearbyint:
617 case Intrinsic::round:
618 case Intrinsic::roundeven:
621 default:
622 break;
623 }
624
625 break;
626 }
627 default:
628 break;
629 }
630
631 return false;
632}
633
634
637
638 if (!Callee || Callee->isIntrinsic() || CI->isNoBuiltin())
639 return false;
640
641 FuncInfo FInfo;
642 if (!parseFunctionName(Callee->getName(), FInfo))
643 return false;
644
645
646
648 return false;
649
650 LLVM_DEBUG(dbgs() << "AMDIC: try folding " << *CI << '\n');
651
652 if (TDOFold(CI, FInfo))
653 return true;
654
657 B.setIsFPConstrained(true);
658
660
661
662
664 return true;
665
666
668 B.setFastMathFlags(FMF);
669
670
671
672
673 switch (FInfo.getId()) {
675 if (FMF.none())
676 return false;
677 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::exp,
680 if (FMF.none())
681 return false;
682 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::exp2,
685 if (FMF.none())
686 return false;
687 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log,
690 if (FMF.none())
691 return false;
692 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log2,
695 if (FMF.none())
696 return false;
697 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::log10,
700 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::minnum,
701 true, true);
703 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::maxnum,
704 true, true);
706 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fma, true,
707 true);
709 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fmuladd,
710 true, true);
712 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::fabs, true,
713 true, true);
715 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::copysign,
716 true, true, true);
718 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::floor, true,
719 true);
721 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::ceil, true,
722 true);
724 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::trunc, true,
725 true);
727 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::rint, true,
728 true);
730 return tryReplaceLibcallWithSimpleIntrinsic(B, CI, Intrinsic::round, true,
731 true);
733 if (!shouldReplaceLibcallWithIntrinsic(CI, true, true))
734 return false;
735
739 Value *SplatArg1 = B.CreateVectorSplat(VecTy->getElementCount(), Arg1);
741 }
742
744 CI->getModule(), Intrinsic::ldexp,
745 {CI->getType(), CI->getArgOperand(1)->getType()}));
746 return true;
747 }
749 Module *M = Callee->getParent();
753
754
755
756 if (PowrFunc &&
758 FPOp->getOperand(0),
760 Call->setCalledFunction(PowrFunc);
761 return fold_pow(FPOp, B, PowrInfo) || true;
762 }
763
764
765 if (isKnownIntegral(FPOp->getOperand(1), M->getDataLayout(),
766 FPOp->getFastMathFlags())) {
770 if (PownFunc) {
771
772
773
774 Value *CastedArg =
775 B.CreateFPToSI(FPOp->getOperand(1), PownType->getParamType(1));
776
777 Call->removeParamAttrs(
778 1, AttributeFuncs::typeIncompatible(CastedArg->getType(),
779 Call->getParamAttributes(1)));
780 Call->setCalledFunction(PownFunc);
781 Call->setArgOperand(1, CastedArg);
782 return fold_pow(FPOp, B, PownInfo) || true;
783 }
784 }
785
786 return fold_pow(FPOp, B, FInfo);
787 }
790 return fold_pow(FPOp, B, FInfo);
792 return fold_rootn(FPOp, B, FInfo);
794
795 return tryReplaceLibcallWithSimpleIntrinsic(
796 B, CI, Intrinsic::sqrt, true, true, false);
799 return fold_sincos(FPOp, B, FInfo);
800 default:
801 break;
802 }
803 } else {
804
805 switch (FInfo.getId()) {
810 return fold_read_write_pipe(CI, B, FInfo);
811 default:
812 break;
813 }
814 }
815
816 return false;
817}
818
819bool AMDGPULibCalls::TDOFold(CallInst *CI, const FuncInfo &FInfo) {
820
823 return false;
824
825 int const sz = (int)tr.size();
827
831 for (int eltNo = 0; eltNo < getVecSize(FInfo); ++eltNo) {
833 CV->getElementAsConstant((unsigned)eltNo));
834 assert(eltval && "Non-FP arguments in math function!");
835 bool found = false;
836 for (int i=0; i < sz; ++i) {
839 found = true;
840 break;
841 }
842 }
843 if (!found) {
844
845 return false;
846 }
847 }
848 LLVMContext &context = CI->getContext();
852 for (double D : DVal)
856 } else {
859 }
860 LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");
862 return true;
863 }
864 } else {
865
867 for (int i = 0; i < sz; ++i) {
868 if (CF->isExactlyValue(tr[i].input)) {
869 Value *nval = ConstantFP::get(CF->getType(), tr[i].result);
870 LLVM_DEBUG(errs() << "AMDIC: " << *CI << " ---> " << *nval << "\n");
872 return true;
873 }
874 }
875 }
876 }
877
878 return false;
879}
880
881namespace llvm {
882static double log2(double V) {
883#if _XOPEN_SOURCE >= 600 || defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
884 return ::log2(V);
885#else
887#endif
888}
889}
890
892 const FuncInfo &FInfo) {
896 "fold_pow: encounter a wrong function call");
897
898 Module *M = B.GetInsertBlock()->getModule();
902
903 const APFloat *CF = nullptr;
904 const APInt *CINT = nullptr;
907
908
909 int ci_opr1 = (CINT ? (int)CINT->getSExtValue() : 0x1111111);
910
911 if ((CF && CF->isZero()) || (CINT && ci_opr1 == 0)) {
912
913 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1\n");
914 Constant *cnval = ConstantFP::get(eltType, 1.0);
917 }
919 return true;
920 }
921 if ((CF && CF->isExactlyValue(1.0)) || (CINT && ci_opr1 == 1)) {
922
923 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << "\n");
925 return true;
926 }
927 if ((CF && CF->isExactlyValue(2.0)) || (CINT && ci_opr1 == 2)) {
928
929 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << " * "
930 << *opr0 << "\n");
931 Value *nval = B.CreateFMul(opr0, opr0, "__pow2");
933 return true;
934 }
935 if ((CF && CF->isExactlyValue(-1.0)) || (CINT && ci_opr1 == -1)) {
936
937 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1 / " << *opr0 << "\n");
938 Constant *cnval = ConstantFP::get(eltType, 1.0);
941 }
942 Value *nval = B.CreateFDiv(cnval, opr0, "__powrecip");
944 return true;
945 }
946
948
950 if (FunctionCallee FPExpr =
953 FInfo))) {
954 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << FInfo.getName()
955 << '(' << *opr0 << ")\n");
957 : "__pow2rsqrt");
959 return true;
960 }
961 }
962
964 return false;
965
966
967
968
969 if (CF) {
973 int ival = (int)dval;
974 if ((double)ival == dval) {
975 ci_opr1 = ival;
976 } else
977 ci_opr1 = 0x11111111;
978 }
979
980
981
982 unsigned abs_opr1 = (ci_opr1 < 0) ? -ci_opr1 : ci_opr1;
983 if (abs_opr1 <= 12) {
986 if (abs_opr1 == 0) {
987 cnval = ConstantFP::get(eltType, 1.0);
990 }
991 nval = cnval;
992 } else {
993 Value *valx2 = nullptr;
994 nval = nullptr;
995 while (abs_opr1 > 0) {
996 valx2 = valx2 ? B.CreateFMul(valx2, valx2, "__powx2") : opr0;
997 if (abs_opr1 & 1) {
998 nval = nval ? B.CreateFMul(nval, valx2, "__powprod") : valx2;
999 }
1000 abs_opr1 >>= 1;
1001 }
1002 }
1003
1004 if (ci_opr1 < 0) {
1005 cnval = ConstantFP::get(eltType, 1.0);
1008 }
1009 nval = B.CreateFDiv(cnval, nval, "__1powprod");
1010 }
1012 << ((ci_opr1 < 0) ? "1/prod(" : "prod(") << *opr0
1013 << ")\n");
1015 return true;
1016 }
1017
1018
1019 const bool ShouldUseIntrinsic = eltType->isFloatTy() || eltType->isHalfTy();
1020
1021
1022
1023 FunctionCallee ExpExpr;
1024 if (ShouldUseIntrinsic)
1027 else {
1029 if (!ExpExpr)
1030 return false;
1031 }
1032
1033 bool needlog = false;
1034 bool needabs = false;
1035 bool needcopysign = false;
1038 CF = nullptr;
1040
1041 if (CF) {
1045
1047 cnval = ConstantFP::get(eltType, V);
1050 } else {
1051 needlog = true;
1053 }
1054 } else {
1056
1057 if (!CDV) {
1058 needlog = true;
1060 } else {
1062 "Wrong vector size detected");
1063
1065 for (int i=0; i < getVecSize(FInfo); ++i) {
1067 if (V < 0.0) needcopysign = true;
1070 }
1073 for (double D : DVal)
1077 } else {
1080 }
1081 }
1082 }
1083
1085
1086
1088 return false;
1089 }
1090
1092 if (needabs) {
1093 nval = B.CreateUnaryIntrinsic(Intrinsic::fabs, opr0, nullptr, "__fabs");
1094 } else {
1095 nval = cnval ? cnval : opr0;
1096 }
1097 if (needlog) {
1098 FunctionCallee LogExpr;
1099 if (ShouldUseIntrinsic) {
1102 } else {
1104 if (!LogExpr)
1105 return false;
1106 }
1107
1109 }
1110
1112
1113 opr1 = B.CreateSIToFP(opr1, nval->getType(), "pownI2F");
1114 }
1115 nval = B.CreateFMul(opr1, nval, "__ylogx");
1117
1118 if (needcopysign) {
1124 opr_n = B.CreateZExtOrTrunc(opr_n, nTy, "__ytou");
1125 else
1126 opr_n = B.CreateFPToSI(opr1, nTy, "__ytou");
1127
1128 Value *sign = B.CreateShl(opr_n, size-1, "__yeven");
1129 sign = B.CreateAnd(B.CreateBitCast(opr0, nTy), sign, "__pow_sign");
1130 nval = B.CreateOr(B.CreateBitCast(nval, nTy), sign);
1131 nval = B.CreateBitCast(nval, opr0->getType());
1132 }
1133
1135 << "exp2(" << *opr1 << " * log2(" << *opr0 << "))\n");
1137
1138 return true;
1139}
1140
1142 const FuncInfo &FInfo) {
1145
1146 const APInt *CINT = nullptr;
1148 return false;
1149
1150 Function *Parent = B.GetInsertBlock()->getParent();
1151
1153 if (ci_opr1 == 1 && !Parent->hasFnAttribute(Attribute::StrictFP)) {
1154
1155
1156
1157 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> " << *opr0 << '\n');
1159 return true;
1160 }
1161
1162 Module *M = B.GetInsertBlock()->getModule();
1163
1165 if (ci_opr1 == 2 &&
1166 shouldReplaceLibcallWithIntrinsic(CI,
1167 true,
1168 true)) {
1169
1170 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> sqrt(" << *opr0 << ")\n");
1171
1172 CallInst *NewCall = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1174
1175
1176
1177 MDBuilder MDHelper(M->getContext());
1178 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));
1179 NewCall->setMetadata(LLVMContext::MD_fpmath, FPMD);
1180
1182 return true;
1183 }
1184
1185 if (ci_opr1 == 3) {
1186 if (FunctionCallee FPExpr =
1188 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> cbrt(" << *opr0
1189 << ")\n");
1192 return true;
1193 }
1194 } else if (ci_opr1 == -1) {
1195 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> 1.0 / " << *opr0 << "\n");
1196 Value *nval = B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0),
1197 opr0,
1198 "__rootn2div");
1200 return true;
1201 }
1202
1203 if (ci_opr1 == -2 &&
1204 shouldReplaceLibcallWithIntrinsic(CI,
1205 true,
1206 true)) {
1207
1208
1209
1210
1211 MDBuilder MDHelper(M->getContext());
1212 MDNode *FPMD = MDHelper.createFPMath(std::max(FPOp->getFPAccuracy(), 2.0f));
1213
1214
1217
1218 CallInst *Sqrt = B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1220 B.CreateFDiv(ConstantFP::get(opr0->getType(), 1.0), Sqrt));
1223 RSqrt->setMetadata(LLVMContext::MD_fpmath, FPMD);
1224
1225 LLVM_DEBUG(errs() << "AMDIC: " << *FPOp << " ---> rsqrt(" << *opr0
1226 << ")\n");
1228 return true;
1229 }
1230
1231 return false;
1232}
1233
1234
1236 const FuncInfo &FInfo) {
1238 return nullptr;
1239 FuncInfo nf = FInfo;
1241 return getFunction(M, nf);
1242}
1243
1244
1245
1246
1247bool AMDGPULibCalls::shouldReplaceLibcallWithIntrinsic(const CallInst *CI,
1248 bool AllowMinSizeF32,
1249 bool AllowF64,
1250 bool AllowStrictFP) {
1252 const bool IsF32 = FltTy->isFloatTy();
1253
1254
1255 if (!IsF32 && !FltTy->isHalfTy() && (!AllowF64 || !FltTy->isDoubleTy()))
1256 return false;
1257
1258
1259
1261 return false;
1262
1264
1265 if (!AllowStrictFP && ParentF->hasFnAttribute(Attribute::StrictFP))
1266 return false;
1267
1268 if (IsF32 && !AllowMinSizeF32 && ParentF->hasMinSize())
1269 return false;
1270 return true;
1271}
1272
1273void AMDGPULibCalls::replaceLibCallWithSimpleIntrinsic(IRBuilder<> &B,
1281 if (Arg0VecTy && !Arg1VecTy) {
1282 Value *SplatRHS = B.CreateVectorSplat(Arg0VecTy->getElementCount(), Arg1);
1284 } else if (!Arg0VecTy && Arg1VecTy) {
1285 Value *SplatLHS = B.CreateVectorSplat(Arg1VecTy->getElementCount(), Arg0);
1287 }
1288 }
1289
1291 CI->getModule(), IntrID, {CI->getType()}));
1292}
1293
1294bool AMDGPULibCalls::tryReplaceLibcallWithSimpleIntrinsic(
1296 bool AllowF64, bool AllowStrictFP) {
1297 if (!shouldReplaceLibcallWithIntrinsic(CI, AllowMinSizeF32, AllowF64,
1298 AllowStrictFP))
1299 return false;
1300 replaceLibCallWithSimpleIntrinsic(B, CI, IntrID);
1301 return true;
1302}
1303
1304std::tuple<Value *, Value *, Value *>
1307 DebugLoc DL = B.getCurrentDebugLocation();
1308 Function *F = B.GetInsertBlock()->getParent();
1309 B.SetInsertPointPastAllocas(F);
1310
1311 AllocaInst *Alloc = B.CreateAlloca(Arg->getType(), nullptr, "__sincos_");
1312
1314
1315
1316
1317
1318 B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
1319
1320
1321 B.SetCurrentDebugLocation(DL);
1322 }
1323
1325
1326
1327
1328
1329 Value *CastAlloc = B.CreateAddrSpaceCast(Alloc, CosPtrTy);
1330
1331 CallInst *SinCos = CreateCallEx2(B, Fsincos, Arg, CastAlloc);
1332
1333
1334
1335
1336 LoadInst *LoadCos = B.CreateLoad(Alloc->getAllocatedType(), Alloc);
1337 return {SinCos, LoadCos, SinCos};
1338}
1339
1340
1342 const FuncInfo &fInfo) {
1345
1349 return false;
1350
1352
1354
1355
1357 return false;
1358
1360
1361 Function *F = B.GetInsertBlock()->getParent();
1363
1364
1365
1367 SinCosLibFuncPrivate.getLeads()[0].PtrKind =
1369
1371 SinCosLibFuncGeneric.getLeads()[0].PtrKind =
1373
1374 FunctionCallee FSinCosPrivate = getFunction(M, SinCosLibFuncPrivate);
1375 FunctionCallee FSinCosGeneric = getFunction(M, SinCosLibFuncGeneric);
1376 FunctionCallee FSinCos = FSinCosPrivate ? FSinCosPrivate : FSinCosGeneric;
1377 if (!FSinCos)
1378 return false;
1379
1384 fInfo);
1385 const std::string PairName = PartnerInfo.mangle();
1386
1389 const std::string SinCosPrivateName = SinCosLibFuncPrivate.mangle();
1390 const std::string SinCosGenericName = SinCosLibFuncGeneric.mangle();
1391
1392
1394 MDNode *FPMath = CI->getMetadata(LLVMContext::MD_fpmath);
1395
1397
1398 for (User* U : CArgVal->users()) {
1401 continue;
1402
1404 if (!UCallee)
1405 continue;
1406
1407 bool Handled = true;
1408
1409 if (UCallee->getName() == SinName)
1411 else if (UCallee->getName() == CosName)
1413 else if (UCallee->getName() == SinCosPrivateName ||
1414 UCallee->getName() == SinCosGenericName)
1416 else
1417 Handled = false;
1418
1419 if (Handled) {
1422 FMF &= OtherOp->getFastMathFlags();
1424 FPMath, XI->getMetadata(LLVMContext::MD_fpmath));
1425 }
1426 }
1427
1428 if (SinCalls.empty() || CosCalls.empty())
1429 return false;
1430
1431 B.setFastMathFlags(FMF);
1432 B.setDefaultFPMathTag(FPMath);
1434 B.SetCurrentDebugLocation(DbgLoc);
1435
1436 auto [Sin, Cos, SinCos] = insertSinCos(CArgVal, FMF, B, FSinCos);
1437
1439 for (CallInst *C : Calls)
1440 C->replaceAllUsesWith(Res);
1441
1442
1443 };
1444
1445 replaceTrigInsts(SinCalls, Sin);
1446 replaceTrigInsts(CosCalls, Cos);
1447 replaceTrigInsts(SinCosCalls, SinCos);
1448
1449
1451 return true;
1452}
1453
1454bool AMDGPULibCalls::evaluateScalarMathFunc(const FuncInfo &FInfo, double &Res0,
1455 double &Res1, Constant *copr0,
1457
1458
1459
1460 double opr0 = 0.0, opr1 = 0.0;
1463 if (fpopr0) {
1467 }
1468
1469 if (fpopr1) {
1473 }
1474
1475 switch (FInfo.getId()) {
1476 default : return false;
1477
1479 Res0 = acos(opr0);
1480 return true;
1481
1483
1484 Res0 = log(opr0 + sqrt(opr0*opr0 - 1.0));
1485 return true;
1486
1488 Res0 = acos(opr0) / MATH_PI;
1489 return true;
1490
1492 Res0 = asin(opr0);
1493 return true;
1494
1496
1497 Res0 = log(opr0 + sqrt(opr0*opr0 + 1.0));
1498 return true;
1499
1501 Res0 = asin(opr0) / MATH_PI;
1502 return true;
1503
1505 Res0 = atan(opr0);
1506 return true;
1507
1509
1510 Res0 = (log(opr0 + 1.0) - log(opr0 - 1.0))/2.0;
1511 return true;
1512
1514 Res0 = atan(opr0) / MATH_PI;
1515 return true;
1516
1518 Res0 = (opr0 < 0.0) ? -pow(-opr0, 1.0/3.0) : pow(opr0, 1.0/3.0);
1519 return true;
1520
1522 Res0 = cos(opr0);
1523 return true;
1524
1526 Res0 = cosh(opr0);
1527 return true;
1528
1530 Res0 = cos(MATH_PI * opr0);
1531 return true;
1532
1534 Res0 = exp(opr0);
1535 return true;
1536
1538 Res0 = pow(2.0, opr0);
1539 return true;
1540
1542 Res0 = pow(10.0, opr0);
1543 return true;
1544
1546 Res0 = log(opr0);
1547 return true;
1548
1550 Res0 = log(opr0) / log(2.0);
1551 return true;
1552
1554 Res0 = log(opr0) / log(10.0);
1555 return true;
1556
1558 Res0 = 1.0 / sqrt(opr0);
1559 return true;
1560
1562 Res0 = sin(opr0);
1563 return true;
1564
1566 Res0 = sinh(opr0);
1567 return true;
1568
1570 Res0 = sin(MATH_PI * opr0);
1571 return true;
1572
1574 Res0 = tan(opr0);
1575 return true;
1576
1578 Res0 = tanh(opr0);
1579 return true;
1580
1582 Res0 = tan(MATH_PI * opr0);
1583 return true;
1584
1585
1588 Res0 = pow(opr0, opr1);
1589 return true;
1590
1593 double val = (double)iopr1->getSExtValue();
1594 Res0 = pow(opr0, val);
1595 return true;
1596 }
1597 return false;
1598 }
1599
1602 double val = (double)iopr1->getSExtValue();
1603 Res0 = pow(opr0, 1.0 / val);
1604 return true;
1605 }
1606 return false;
1607 }
1608
1609
1611 Res0 = sin(opr0);
1612 Res1 = cos(opr0);
1613 return true;
1614 }
1615
1616 return false;
1617}
1618
1619bool AMDGPULibCalls::evaluateCall(CallInst *aCI, const FuncInfo &FInfo) {
1620 int numArgs = (int)aCI->arg_size();
1621 if (numArgs > 3)
1622 return false;
1623
1626 if (numArgs > 0) {
1628 return false;
1629 }
1630
1631 if (numArgs > 1) {
1634 return false;
1635 }
1636 }
1637
1638
1639
1640
1641 double DVal0[16], DVal1[16];
1642 int FuncVecSize = getVecSize(FInfo);
1644 if (FuncVecSize == 1) {
1645 if (!evaluateScalarMathFunc(FInfo, DVal0[0], DVal1[0], copr0, copr1)) {
1646 return false;
1647 }
1648 } else {
1651 for (int i = 0; i < FuncVecSize; ++i) {
1654 if (!evaluateScalarMathFunc(FInfo, DVal0[i], DVal1[i], celt0, celt1)) {
1655 return false;
1656 }
1657 }
1658 }
1659
1660 LLVMContext &context = aCI->getContext();
1662 if (FuncVecSize == 1) {
1663 nval0 = ConstantFP::get(aCI->getType(), DVal0[0]);
1664 if (hasTwoResults)
1665 nval1 = ConstantFP::get(aCI->getType(), DVal1[0]);
1666 } else {
1669 for (int i = 0; i < FuncVecSize; ++i)
1670 FVal0.push_back((float)DVal0[i]);
1673 if (hasTwoResults) {
1674 for (int i = 0; i < FuncVecSize; ++i)
1675 FVal1.push_back((float)DVal1[i]);
1678 }
1679 } else {
1682 if (hasTwoResults) {
1685 }
1686 }
1687 }
1688
1689 if (hasTwoResults) {
1690
1692 "math function with ptr arg not supported yet");
1694 }
1695
1697 return true;
1698}
1699
1704 Simplifier.initFunction(F, AM);
1705
1707
1709 F.printAsOperand(dbgs(), false, F.getParent()); dbgs() << '\n';);
1710
1711 for (auto &BB : F) {
1713
1715 ++I;
1716
1717 if (CI) {
1718 if (Simplifier.fold(CI))
1720 }
1721 }
1722 }
1724}
1725
1730
1733 Simplifier.initFunction(F, AM);
1734
1736 for (auto &BB : F) {
1738
1740 ++I;
1741 if (CI && Simplifier.useNative(CI))
1743 }
1744 }
1746}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isKnownIntegral(const Value *V, const DataLayout &DL, FastMathFlags FMF)
Definition AMDGPULibCalls.cpp:566
static const TableEntry tbl_log[]
Definition AMDGPULibCalls.cpp:273
static const TableEntry tbl_tgamma[]
Definition AMDGPULibCalls.cpp:318
static AMDGPULibFunc::EType getArgType(const AMDGPULibFunc &FInfo)
Definition AMDGPULibCalls.cpp:398
static const TableEntry tbl_expm1[]
Definition AMDGPULibCalls.cpp:269
static const TableEntry tbl_asinpi[]
Definition AMDGPULibCalls.cpp:206
static const TableEntry tbl_cos[]
Definition AMDGPULibCalls.cpp:234
#define MATH_SQRT2
Definition AMDGPULibCalls.cpp:43
static const TableEntry tbl_exp10[]
Definition AMDGPULibCalls.cpp:264
static CallInst * CreateCallEx(IRB &B, FunctionCallee Callee, Value *Arg, const Twine &Name="")
Definition AMDGPULibCalls.cpp:146
static CallInst * CreateCallEx2(IRB &B, FunctionCallee Callee, Value *Arg1, Value *Arg2, const Twine &Name="")
Definition AMDGPULibCalls.cpp:155
static const TableEntry tbl_rsqrt[]
Definition AMDGPULibCalls.cpp:285
static const TableEntry tbl_atanh[]
Definition AMDGPULibCalls.cpp:218
static const TableEntry tbl_cosh[]
Definition AMDGPULibCalls.cpp:238
static const TableEntry tbl_asin[]
Definition AMDGPULibCalls.cpp:196
static const TableEntry tbl_sinh[]
Definition AMDGPULibCalls.cpp:293
static const TableEntry tbl_acos[]
Definition AMDGPULibCalls.cpp:181
static const TableEntry tbl_tan[]
Definition AMDGPULibCalls.cpp:306
static const TableEntry tbl_cospi[]
Definition AMDGPULibCalls.cpp:242
static const TableEntry tbl_tanpi[]
Definition AMDGPULibCalls.cpp:314
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)
Definition AMDGPULibCalls.cpp:325
ArrayRef< TableEntry > TableRef
Definition AMDGPULibCalls.cpp:348
static int getVecSize(const AMDGPULibFunc &FInfo)
Definition AMDGPULibCalls.cpp:394
static const TableEntry tbl_sin[]
Definition AMDGPULibCalls.cpp:289
static const TableEntry tbl_atan[]
Definition AMDGPULibCalls.cpp:212
static const TableEntry tbl_log2[]
Definition AMDGPULibCalls.cpp:277
static const TableEntry tbl_acospi[]
Definition AMDGPULibCalls.cpp:190
static const TableEntry tbl_sqrt[]
Definition AMDGPULibCalls.cpp:301
static const TableEntry tbl_asinh[]
Definition AMDGPULibCalls.cpp:202
#define MATH_E
Definition AMDGPULibCalls.cpp:42
static TableRef getOptTable(AMDGPULibFunc::EFuncId id)
Definition AMDGPULibCalls.cpp:350
static const TableEntry tbl_acosh[]
Definition AMDGPULibCalls.cpp:187
static const TableEntry tbl_exp[]
Definition AMDGPULibCalls.cpp:254
static const TableEntry tbl_cbrt[]
Definition AMDGPULibCalls.cpp:228
static const TableEntry tbl_sinpi[]
Definition AMDGPULibCalls.cpp:297
static const TableEntry tbl_atanpi[]
Definition AMDGPULibCalls.cpp:222
#define MATH_PI
Definition AMDGPULibCalls.cpp:41
static FunctionType * getPownType(FunctionType *FT)
Definition AMDGPULibCalls.cpp:163
static const TableEntry tbl_erf[]
Definition AMDGPULibCalls.cpp:250
static const TableEntry tbl_log10[]
Definition AMDGPULibCalls.cpp:281
#define MATH_SQRT1_2
Definition AMDGPULibCalls.cpp:44
static const TableEntry tbl_erfc[]
Definition AMDGPULibCalls.cpp:246
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[]
Definition AMDGPULibCalls.cpp:310
static const TableEntry tbl_exp2[]
Definition AMDGPULibCalls.cpp:259
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Machine Check Debug Module
FunctionAnalysisManager FAM
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static Function * getFunction(FunctionType *Ty, const Twine &Name, Module *M)
Definition AMDGPULibCalls.cpp:48
static void replaceCall(FPMathOperator *I, Value *With)
Definition AMDGPULibCalls.cpp:127
bool isUnsafeFiniteOnlyMath(const FPMathOperator *FPOp) const
Definition AMDGPULibCalls.cpp:415
bool canIncreasePrecisionOfConstantFold(const FPMathOperator *FPOp) const
Definition AMDGPULibCalls.cpp:419
bool fold(CallInst *CI)
Definition AMDGPULibCalls.cpp:635
void initNativeFuncs()
Definition AMDGPULibCalls.cpp:435
static void replaceCall(Instruction *I, Value *With)
Definition AMDGPULibCalls.cpp:122
bool useNative(CallInst *CI)
Definition AMDGPULibCalls.cpp:477
void initFunction(Function &F, FunctionAnalysisManager &FAM)
Definition AMDGPULibCalls.cpp:425
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
Param * getLeads()
Get leading parameters for mangled lib functions.
ENamePrefix getPrefix() const
LLVM_ABI double convertToDouble() const
Converts this APFloat to host double value.
bool isExactlyValue(double V) const
We don't rely on operator== working on double values, as it returns true for things that are clearly ...
LLVM_ABI float convertToFloat() const
Converts this APFloat to host float value.
int64_t getSExtValue() const
Get sign extended value.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
bool empty() const
empty - Check if the array is empty.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
InstListType::iterator iterator
Instruction iterators...
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.
bool isNoInline() const
Return true if the call should not be inlined.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
FunctionType * getFunctionType() const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
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.
A vector constant whose element type is a simple 1/2/4/8-byte integer or float/double,...
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...
ConstantFP - Floating Point Values [float, double].
const APFloat & getValue() const
const APFloat & getValueAPF() const
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 ...
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Align getAlignValue() const
Return the constant as an llvm::Align, interpreting 0 as Align(1).
This is an important base class in LLVM.
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.
A parsed version of the target data layout string in and methods for querying it.
Analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Utility class for floating point operations which can have information about relaxed accuracy require...
bool isFast() const
Test if this operation allows all non-strict floating-point transforms.
bool hasNoNaNs() const
Test if this operation's arguments and results are assumed not-NaN.
FastMathFlags getFastMathFlags() const
Convenience function for getting all the fast-math flags.
bool hasNoInfs() const
Test if this operation's arguments and results are assumed not-infinite.
bool hasApproxFunc() const
Test if this operation allows approximations of math library functions or intrinsics.
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.
void setAllowContract(bool B=true)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
FunctionType * getFunctionType()
Class to represent function types.
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).
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
StringRef - Represent a constant reference to a string, i.e.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
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.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
void dropAllReferences()
Drop all references to operands.
Value * getOperand(unsigned i) const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
LLVM_ABI void takeName(Value *V)
Transfer the name from V to this value.
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()
@ 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.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
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)
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
static double log2(double V)
Definition AMDGPULibCalls.cpp:882
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.
LLVM_ABI bool isKnownNeverInfinity(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point scalar value is not an infinity or if the floating-point vector val...
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
auto dyn_cast_or_null(const Y &Val)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI bool isKnownNeverInfOrNaN(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if the floating-point value can never contain a NaN or infinity.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
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....
Definition AMDGPULibCalls.cpp:175
double result
Definition AMDGPULibCalls.cpp:176
double input
Definition AMDGPULibCalls.cpp:177
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition AMDGPULibCalls.cpp:1700
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
Definition AMDGPULibCalls.cpp:1726
This struct is a compact representation of a valid (non-zero power of two) alignment.