26#define DEBUG_TYPE "amdgpu-simplifylib"
32 cl::desc(
"Enable pre-link mode optimizations"),
37 cl::desc(
"Comma separated list of functions to replace with native, or all"),
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
57 bool AllNative =
false;
81 bool evaluateScalarMathFunc(
const FuncInfo &FInfo,
double &Res0,
double &Res1,
87 std::tuple<Value *, Value *, Value *> insertSinCos(
Value *Arg,
104 bool shouldReplaceLibcallWithIntrinsic(
const CallInst *CI,
105 bool AllowMinSizeF32 =
false,
106 bool AllowF64 =
false,
107 bool AllowStrictFP =
false);
113 bool AllowMinSizeF32 =
false,
114 bool AllowF64 =
false,
115 bool AllowStrictFP =
false);
123 I->replaceAllUsesWith(With);
124 I->eraseFromParent();
145template <
typename IRB>
149 if (
Function *
F = dyn_cast<Function>(Callee.getCallee()))
150 R->setCallingConv(
F->getCallingConv());
154template <
typename IRB>
158 if (
Function *
F = dyn_cast<Function>(Callee.getCallee()))
159 R->setCallingConv(
F->getCallingConv());
165 if (
VectorType *VecTy = dyn_cast<VectorType>(FT->getReturnType()))
166 PowNExpTy = VectorType::get(PowNExpTy, VecTy->getElementCount());
168 return FunctionType::get(FT->getReturnType(),
169 {FT->getParamType(0), PowNExpTy},
false);
327 case AMDGPULibFunc::EI_DIVIDE:
328 case AMDGPULibFunc::EI_COS:
329 case AMDGPULibFunc::EI_EXP:
330 case AMDGPULibFunc::EI_EXP2:
331 case AMDGPULibFunc::EI_EXP10:
332 case AMDGPULibFunc::EI_LOG:
333 case AMDGPULibFunc::EI_LOG2:
334 case AMDGPULibFunc::EI_LOG10:
335 case AMDGPULibFunc::EI_POWR:
336 case AMDGPULibFunc::EI_RECIP:
337 case AMDGPULibFunc::EI_RSQRT:
338 case AMDGPULibFunc::EI_SIN:
339 case AMDGPULibFunc::EI_SINCOS:
340 case AMDGPULibFunc::EI_SQRT:
341 case AMDGPULibFunc::EI_TAN:
362 case AMDGPULibFunc::EI_NCOS:
369 case AMDGPULibFunc::EI_NEXP2:
374 case AMDGPULibFunc::EI_NLOG2:
377 case AMDGPULibFunc::EI_NRSQRT:
379 case AMDGPULibFunc::EI_NSIN:
383 case AMDGPULibFunc::EI_NSQRT:
410bool AMDGPULibCalls::parseFunctionName(
const StringRef &FMangledName,
431bool AMDGPULibCalls::useNativeFunc(
const StringRef F)
const {
436 AllNative = useNativeFunc(
"all") ||
441bool AMDGPULibCalls::sincosUseNative(
CallInst *aCI,
const FuncInfo &FInfo) {
442 bool native_sin = useNativeFunc(
"sin");
443 bool native_cos = useNativeFunc(
"cos");
445 if (native_sin && native_cos) {
460 if (sinExpr && cosExpr) {
468 <<
" with native version of sin/cos");
483 if (!parseFunctionName(Callee->getName(), FInfo) || !FInfo.
isMangled() ||
486 !(AllNative || useNativeFunc(FInfo.
getName()))) {
491 return sincosUseNative(aCI, FInfo);
500 <<
" with native version");
512 const FuncInfo &FInfo) {
514 if (!Callee->isDeclaration())
517 assert(Callee->hasName() &&
"Invalid read_pipe/write_pipe function");
518 auto *M = Callee->getParent();
519 std::string
Name = std::string(Callee->getName());
521 if (NumArg != 4 && NumArg != 6)
527 if (!PacketSize || !PacketAlign)
532 if (Alignment !=
Size)
535 unsigned PtrArgLoc = CI->
arg_size() - 3;
540 for (
unsigned I = 0;
I != PtrArgLoc; ++
I)
553 for (
unsigned I = 0;
I != PtrArgLoc; ++
I)
555 Args.push_back(PtrArg);
557 auto *NCI =
B.CreateCall(
F, Args);
568 if (isa<PoisonValue>(V))
570 if (isa<UndefValue>(V))
573 if (
const ConstantFP *CF = dyn_cast<ConstantFP>(V))
574 return CF->getValueAPF().isInteger();
576 auto *VFVTy = dyn_cast<FixedVectorType>(V->getType());
577 const Constant *CV = dyn_cast<Constant>(V);
579 unsigned NumElts = VFVTy->getNumElements();
580 for (
unsigned i = 0; i != NumElts; ++i) {
584 if (isa<PoisonValue>(Elt))
587 const ConstantFP *CFP = dyn_cast<ConstantFP>(Elt);
599 switch (
I->getOpcode()) {
600 case Instruction::SIToFP:
601 case Instruction::UIToFP:
609 case Instruction::Call: {
612 case Intrinsic::trunc:
613 case Intrinsic::floor:
614 case Intrinsic::ceil:
615 case Intrinsic::rint:
616 case Intrinsic::nearbyint:
617 case Intrinsic::round:
618 case Intrinsic::roundeven:
638 if (!Callee || Callee->isIntrinsic() || CI->
isNoBuiltin())
642 if (!parseFunctionName(Callee->getName(), FInfo))
652 if (TDOFold(CI, FInfo))
657 B.setIsFPConstrained(
true);
668 B.setFastMathFlags(FMF);
673 switch (FInfo.
getId()) {
677 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::exp,
682 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::exp2,
687 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::log,
692 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::log2,
697 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::log10,
700 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::minnum,
703 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::maxnum,
706 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::fma,
true,
709 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::fmuladd,
712 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::fabs,
true,
715 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::copysign,
718 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::floor,
true,
721 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::ceil,
true,
724 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::trunc,
true,
727 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::rint,
true,
730 return tryReplaceLibcallWithSimpleIntrinsic(
B, CI, Intrinsic::round,
true,
733 if (!shouldReplaceLibcallWithIntrinsic(CI,
true,
true))
738 VecTy && !isa<VectorType>(Arg1->
getType())) {
739 Value *SplatArg1 =
B.CreateVectorSplat(VecTy->getElementCount(), Arg1);
745 {CI->getType(), CI->getArgOperand(1)->getType()}));
749 Module *M = Callee->getParent();
752 CallInst *Call = cast<CallInst>(FPOp);
760 Call->setCalledFunction(PowrFunc);
761 return fold_pow(FPOp,
B, PowrInfo) ||
true;
766 FPOp->getFastMathFlags())) {
775 B.CreateFPToSI(FPOp->getOperand(1), PownType->
getParamType(1));
777 Call->removeParamAttrs(
779 Call->getParamAttributes(1)));
780 Call->setCalledFunction(PownFunc);
781 Call->setArgOperand(1, CastedArg);
782 return fold_pow(FPOp,
B, PownInfo) ||
true;
786 return fold_pow(FPOp,
B, FInfo);
790 return fold_pow(FPOp,
B, FInfo);
792 return fold_rootn(FPOp,
B, FInfo);
795 return tryReplaceLibcallWithSimpleIntrinsic(
796 B, CI, Intrinsic::sqrt,
true,
true,
false);
799 return fold_sincos(FPOp,
B, FInfo);
805 switch (FInfo.
getId()) {
810 return fold_read_write_pipe(CI,
B, FInfo);
819bool AMDGPULibCalls::TDOFold(
CallInst *CI,
const FuncInfo &FInfo) {
825 int const sz = (int)tr.
size();
831 for (
int eltNo = 0; eltNo <
getVecSize(FInfo); ++eltNo) {
833 CV->getElementAsConstant((
unsigned)eltNo));
834 assert(eltval &&
"Non-FP arguments in math function!");
836 for (
int i=0; i < sz; ++i) {
852 for (
double D : DVal)
860 LLVM_DEBUG(
errs() <<
"AMDIC: " << *CI <<
" ---> " << *nval <<
"\n");
866 if (
ConstantFP *CF = dyn_cast<ConstantFP>(opr0)) {
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");
883#if _XOPEN_SOURCE >= 600 || defined(_ISOC99_SOURCE) || _POSIX_C_SOURCE >= 200112L
892 const FuncInfo &FInfo) {
896 "fold_pow: encounter a wrong function call");
898 Module *
M =
B.GetInsertBlock()->getModule();
904 const APInt *CINT =
nullptr;
909 int ci_opr1 = (CINT ? (int)CINT->
getSExtValue() : 0x1111111);
911 if ((CF && CF->
isZero()) || (CINT && ci_opr1 == 0)) {
914 Constant *cnval = ConstantFP::get(eltType, 1.0);
923 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> " << *opr0 <<
"\n");
929 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> " << *opr0 <<
" * "
931 Value *nval =
B.CreateFMul(opr0, opr0,
"__pow2");
935 if ((CF && CF->
isExactlyValue(-1.0)) || (CINT && ci_opr1 == -1)) {
937 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> 1 / " << *opr0 <<
"\n");
938 Constant *cnval = ConstantFP::get(eltType, 1.0);
942 Value *nval =
B.CreateFDiv(cnval, opr0,
"__powrecip");
954 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> " << FInfo.getName()
955 <<
'(' << *opr0 <<
")\n");
973 int ival = (int)dval;
974 if ((
double)ival == dval) {
977 ci_opr1 = 0x11111111;
982 unsigned abs_opr1 = (ci_opr1 < 0) ? -ci_opr1 : ci_opr1;
983 if (abs_opr1 <= 12) {
987 cnval = ConstantFP::get(eltType, 1.0);
993 Value *valx2 =
nullptr;
995 while (abs_opr1 > 0) {
996 valx2 = valx2 ?
B.CreateFMul(valx2, valx2,
"__powx2") : opr0;
998 nval = nval ?
B.CreateFMul(nval, valx2,
"__powprod") : valx2;
1005 cnval = ConstantFP::get(eltType, 1.0);
1009 nval =
B.CreateFDiv(cnval, nval,
"__1powprod");
1012 << ((ci_opr1 < 0) ?
"1/prod(" :
"prod(") << *opr0
1024 if (ShouldUseIntrinsic)
1033 bool needlog =
false;
1034 bool needabs =
false;
1035 bool needcopysign =
false;
1046 V =
log2(std::abs(V));
1047 cnval = ConstantFP::get(eltType, V);
1062 "Wrong vector size detected");
1067 if (V < 0.0) needcopysign =
true;
1068 V =
log2(std::abs(V));
1073 for (
double D : DVal)
1093 nval =
B.CreateUnaryIntrinsic(Intrinsic::fabs, opr0,
nullptr,
"__fabs");
1095 nval = cnval ? cnval : opr0;
1099 if (ShouldUseIntrinsic) {
1113 opr1 =
B.CreateSIToFP(opr1, nval->
getType(),
"pownI2F");
1115 nval =
B.CreateFMul(opr1, nval,
"__ylogx");
1124 opr_n =
B.CreateZExtOrTrunc(opr_n, nTy,
"__ytou");
1126 opr_n =
B.CreateFPToSI(opr1, nTy,
"__ytou");
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());
1135 <<
"exp2(" << *opr1 <<
" * log2(" << *opr0 <<
"))\n");
1142 const FuncInfo &FInfo) {
1146 const APInt *CINT =
nullptr;
1150 Function *Parent =
B.GetInsertBlock()->getParent();
1153 if (ci_opr1 == 1 && !Parent->
hasFnAttribute(Attribute::StrictFP)) {
1157 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> " << *opr0 <<
'\n');
1162 Module *
M =
B.GetInsertBlock()->getModule();
1164 CallInst *CI = cast<CallInst>(FPOp);
1166 shouldReplaceLibcallWithIntrinsic(CI,
1170 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> sqrt(" << *opr0 <<
")\n");
1172 CallInst *NewCall =
B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1179 NewCall->
setMetadata(LLVMContext::MD_fpmath, FPMD);
1188 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> cbrt(" << *opr0
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),
1203 if (ci_opr1 == -2 &&
1204 shouldReplaceLibcallWithIntrinsic(CI,
1218 CallInst *Sqrt =
B.CreateUnaryIntrinsic(Intrinsic::sqrt, opr0, CI);
1220 B.CreateFDiv(ConstantFP::get(opr0->
getType(), 1.0), Sqrt));
1225 LLVM_DEBUG(
errs() <<
"AMDIC: " << *FPOp <<
" ---> rsqrt(" << *opr0
1236 const FuncInfo &FInfo) {
1239 FuncInfo nf = FInfo;
1241 return getFunction(M, nf);
1247bool AMDGPULibCalls::shouldReplaceLibcallWithIntrinsic(
const CallInst *CI,
1248 bool AllowMinSizeF32,
1250 bool AllowStrictFP) {
1265 if (!AllowStrictFP && ParentF->
hasFnAttribute(Attribute::StrictFP))
1268 if (IsF32 && !AllowMinSizeF32 && ParentF->
hasMinSize())
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);
1291 CI->
getModule(), IntrID, {CI->getType()}));
1294bool AMDGPULibCalls::tryReplaceLibcallWithSimpleIntrinsic(
1296 bool AllowF64,
bool AllowStrictFP) {
1297 if (!shouldReplaceLibcallWithIntrinsic(CI, AllowMinSizeF32, AllowF64,
1300 replaceLibCallWithSimpleIntrinsic(
B, CI, IntrID);
1304std::tuple<Value *, Value *, Value *>
1308 Function *
F =
B.GetInsertBlock()->getParent();
1309 B.SetInsertPointPastAllocas(
F);
1313 if (
Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
1318 B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
1321 B.SetCurrentDebugLocation(
DL);
1329 Value *CastAlloc =
B.CreateAddrSpaceCast(
Alloc, CosPtrTy);
1337 return {SinCos, LoadCos, SinCos};
1342 const FuncInfo &fInfo) {
1356 if (isa<ConstantData>(CArgVal))
1359 CallInst *CI = cast<CallInst>(FPOp);
1361 Function *
F =
B.GetInsertBlock()->getParent();
1367 SinCosLibFuncPrivate.getLeads()[0].PtrKind =
1371 SinCosLibFuncGeneric.getLeads()[0].PtrKind =
1374 FunctionCallee FSinCosPrivate = getFunction(M, SinCosLibFuncPrivate);
1375 FunctionCallee FSinCosGeneric = getFunction(M, SinCosLibFuncGeneric);
1376 FunctionCallee FSinCos = FSinCosPrivate ? FSinCosPrivate : FSinCosGeneric;
1385 const std::string PairName = PartnerInfo.mangle();
1389 const std::string SinCosPrivateName = SinCosLibFuncPrivate.mangle();
1390 const std::string SinCosGenericName = SinCosLibFuncGeneric.mangle();
1399 CallInst *XI = dyn_cast<CallInst>(U);
1407 bool Handled =
true;
1409 if (UCallee->
getName() == SinName)
1411 else if (UCallee->
getName() == CosName)
1413 else if (UCallee->
getName() == SinCosPrivateName ||
1414 UCallee->
getName() == SinCosGenericName)
1421 auto *OtherOp = cast<FPMathOperator>(XI);
1422 FMF &= OtherOp->getFastMathFlags();
1431 B.setFastMathFlags(FMF);
1432 B.setDefaultFPMathTag(FPMath);
1434 B.SetCurrentDebugLocation(DbgLoc);
1436 auto [Sin, Cos, SinCos] = insertSinCos(CArgVal, FMF,
B, FSinCos);
1440 C->replaceAllUsesWith(Res);
1445 replaceTrigInsts(SinCalls, Sin);
1446 replaceTrigInsts(CosCalls, Cos);
1447 replaceTrigInsts(SinCosCalls, SinCos);
1454bool AMDGPULibCalls::evaluateScalarMathFunc(
const FuncInfo &FInfo,
double &Res0,
1460 double opr0 = 0.0, opr1 = 0.0;
1461 ConstantFP *fpopr0 = dyn_cast_or_null<ConstantFP>(copr0);
1462 ConstantFP *fpopr1 = dyn_cast_or_null<ConstantFP>(copr1);
1475 switch (FInfo.getId()) {
1476 default :
return false;
1484 Res0 = log(opr0 + sqrt(opr0*opr0 - 1.0));
1497 Res0 = log(opr0 + sqrt(opr0*opr0 + 1.0));
1510 Res0 = (log(opr0 + 1.0) - log(opr0 - 1.0))/2.0;
1518 Res0 = (opr0 < 0.0) ? -
pow(-opr0, 1.0/3.0) :
pow(opr0, 1.0/3.0);
1538 Res0 =
pow(2.0, opr0);
1542 Res0 =
pow(10.0, opr0);
1550 Res0 = log(opr0) / log(2.0);
1554 Res0 = log(opr0) / log(10.0);
1558 Res0 = 1.0 / sqrt(opr0);
1588 Res0 =
pow(opr0, opr1);
1592 if (
ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
1593 double val = (double)iopr1->getSExtValue();
1594 Res0 =
pow(opr0, val);
1601 if (
ConstantInt *iopr1 = dyn_cast_or_null<ConstantInt>(copr1)) {
1602 double val = (double)iopr1->getSExtValue();
1603 Res0 =
pow(opr0, 1.0 / val);
1619bool AMDGPULibCalls::evaluateCall(
CallInst *aCI,
const FuncInfo &FInfo) {
1620 int numArgs = (int)aCI->
arg_size();
1627 if ((copr0 = dyn_cast<Constant>(aCI->
getArgOperand(0))) ==
nullptr)
1632 if ((copr1 = dyn_cast<Constant>(aCI->
getArgOperand(1))) ==
nullptr) {
1641 double DVal0[16], DVal1[16];
1644 if (FuncVecSize == 1) {
1645 if (!evaluateScalarMathFunc(FInfo, DVal0[0], DVal1[0], copr0, copr1)) {
1651 for (
int i = 0; i < FuncVecSize; ++i) {
1654 if (!evaluateScalarMathFunc(FInfo, DVal0[i], DVal1[i], celt0, celt1)) {
1662 if (FuncVecSize == 1) {
1663 nval0 = ConstantFP::get(aCI->
getType(), DVal0[0]);
1665 nval1 = ConstantFP::get(aCI->
getType(), DVal1[0]);
1668 SmallVector <float, 0> FVal0, FVal1;
1669 for (
int i = 0; i < FuncVecSize; ++i)
1673 if (hasTwoResults) {
1674 for (
int i = 0; i < FuncVecSize; ++i)
1682 if (hasTwoResults) {
1689 if (hasTwoResults) {
1692 "math function with ptr arg not supported yet");
1706 bool Changed =
false;
1709 F.printAsOperand(
dbgs(),
false,
F.getParent());
dbgs() <<
'\n';);
1711 for (
auto &BB :
F) {
1718 if (Simplifier.
fold(CI))
1735 bool Changed =
false;
1736 for (
auto &BB :
F) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isKnownIntegral(const Value *V, const DataLayout &DL, FastMathFlags FMF)
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[]
static const TableEntry tbl_exp10[]
static CallInst * CreateCallEx(IRB &B, FunctionCallee Callee, Value *Arg, const Twine &Name="")
static CallInst * CreateCallEx2(IRB &B, FunctionCallee Callee, Value *Arg1, Value *Arg2, const Twine &Name="")
static const TableEntry tbl_rsqrt[]
static const TableEntry tbl_atanh[]
static const TableEntry tbl_cosh[]
static const TableEntry tbl_asin[]
static const TableEntry tbl_sinh[]
static const TableEntry tbl_acos[]
static const TableEntry tbl_tan[]
static const TableEntry tbl_cospi[]
static const TableEntry tbl_tanpi[]
static cl::opt< bool > EnablePreLink("amdgpu-prelink", cl::desc("Enable pre-link mode optimizations"), cl::init(false), cl::Hidden)
static bool HasNative(AMDGPULibFunc::EFuncId id)
ArrayRef< TableEntry > TableRef
static int getVecSize(const AMDGPULibFunc &FInfo)
static const TableEntry tbl_sin[]
static const TableEntry tbl_atan[]
static const TableEntry tbl_log2[]
static const TableEntry tbl_acospi[]
static const TableEntry tbl_sqrt[]
static const TableEntry tbl_asinh[]
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[]
static FunctionType * getPownType(FunctionType *FT)
static const TableEntry tbl_erf[]
static const TableEntry tbl_log10[]
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 const TableEntry tbl_exp2[]
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
FunctionAnalysisManager FAM
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static void replaceCall(FPMathOperator *I, Value *With)
bool isUnsafeFiniteOnlyMath(const FPMathOperator *FPOp) const
bool canIncreasePrecisionOfConstantFold(const FPMathOperator *FPOp) const
static void replaceCall(Instruction *I, Value *With)
bool useNative(CallInst *CI)
void initFunction(Function &F, FunctionAnalysisManager &FAM)
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.
Class for arbitrary precision integers.
int64_t getSExtValue() const
Get sign extended value.
an instruction to allocate memory on the stack
A container for analyses that lazily runs them and caches their results.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
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.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
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.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
bool isHalfTy() const
Return true if this is 'half', a 16-bit IEEE fp type.
bool isDoubleTy() const
Return true if this is 'double', a 64-bit IEEE fp type.
LLVM_ABI unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
Type * getScalarType() const
If this is a vector type, return the element type, otherwise return 'this'.
LLVM_ABI Type * getWithNewType(Type *EltTy) const
Given vector type, change the element type, whilst keeping the old number of elements.
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.
const ParentTy * getParent() const
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.
LLVM_ABI AttributeMask typeIncompatible(Type *Ty, AttributeSet AS, AttributeSafetyKind ASK=ASK_ALL)
Which attributes cannot be applied to a type.
@ 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.
bool match(Val *V, const Pattern &P)
apint_match m_APIntAllowPoison(const APInt *&Res)
Match APInt while allowing poison in splat vector constants.
apfloat_match m_APFloatAllowPoison(const APFloat *&Res)
Match APFloat while allowing poison in splat vector constants.
initializer< Ty > init(const Ty &Val)
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.
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...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
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.