42using namespace PatternMatch;
47 cl::desc(
"Enable unsafe double to float "
48 "shrinking for math lib calls"));
55 cl::desc(
"Enable hot/cold operator new library calls"));
59 "Enable optimization of existing hot/cold operator new library calls"));
66struct HotColdHintParser :
public cl::parser<unsigned> {
71 return O.error(
"'" + Arg +
"' value invalid for uint argument!");
74 return O.error(
"'" + Arg +
"' value must be in the range [0, 255]!");
88 cl::desc(
"Value to pass to hot/cold operator new for cold allocation"));
91 cl::desc(
"Value to pass to hot/cold operator new for "
92 "notcold (warm) allocation"));
95 cl::desc(
"Value to pass to hot/cold operator new for hot allocation"));
102 return Func == LibFunc_abs || Func == LibFunc_labs ||
103 Func == LibFunc_llabs || Func == LibFunc_strlen;
108 for (
User *U : V->users()) {
109 if (
ICmpInst *IC = dyn_cast<ICmpInst>(U))
110 if (IC->isEquality() && IC->getOperand(1) == With)
120 return OI->getType()->isFloatingPointTy();
126 return OI->getType()->isFP128Ty();
139 if (Base < 2 || Base > 36)
148 if (!isSpace((
unsigned char)Str[
Offset])) {
159 bool Negate = Str[0] ==
'-';
160 if (Str[0] ==
'-' || Str[0] ==
'+') {
161 Str = Str.drop_front();
171 unsigned NBits =
RetTy->getPrimitiveSizeInBits();
172 uint64_t Max = AsSigned && Negate ? 1 : 0;
176 if (Str.size() > 1) {
178 if (toUpper((
unsigned char)Str[1]) ==
'X') {
179 if (Str.size() == 2 || (
Base &&
Base != 16))
184 Str = Str.drop_front(2);
190 }
else if (
Base == 0)
200 for (
unsigned i = 0; i != Str.size(); ++i) {
201 unsigned char DigVal = Str[i];
203 DigVal = DigVal -
'0';
205 DigVal = toUpper(DigVal);
207 DigVal = DigVal -
'A' + 10;
220 if (VFlow || Result > Max)
228 Value *StrEnd =
B.CreateInBoundsGEP(
B.getInt8Ty(), StrBeg, Off,
"endptr");
229 B.CreateStore(StrEnd, EndPtr);
236 return ConstantInt::get(
RetTy, Result);
240 for (
User *U : V->users()) {
241 if (
ICmpInst *IC = dyn_cast<ICmpInst>(U))
242 if (
Constant *
C = dyn_cast<Constant>(IC->getOperand(1)))
243 if (
C->isNullValue())
271 for (
unsigned ArgNo : ArgNos) {
272 uint64_t DerefBytes = DereferenceableBytes;
277 DereferenceableBytes);
296 for (
unsigned ArgNo : ArgNos) {
322 DerefMin = std::min(
X->getZExtValue(),
Y->getZExtValue());
336 if (
auto *NewCI = dyn_cast_or_null<CallInst>(New))
343 NewCI->
getContext(), {NewCI->getAttributes(), Old.getAttributes()}));
350 return Len >= Str.size() ? Str : Str.substr(0, Len);
375 return copyFlags(*CI, emitStrLenMemCpy(Src, Dst, Len,
B));
389 Value *CpyDst =
B.CreateInBoundsGEP(
B.getInt8Ty(), Dst, DstLen,
"endptr");
395 ConstantInt::get(DL.
getIntPtrType(Src->getContext()), Len + 1));
439 return copyFlags(*CI, emitStrLenMemCpy(Src, Dst, SrcLen,
B));
452 Type *CharTy =
B.getInt8Ty();
453 Value *Char0 =
B.CreateLoad(CharTy, Src);
454 CharVal =
B.CreateTrunc(CharVal, CharTy);
455 Value *Cmp =
B.CreateICmpEQ(Char0, CharVal,
"char0cmp");
459 Value *
And =
B.CreateICmpNE(NBytes, Zero);
460 Cmp =
B.CreateLogicalAnd(
And, Cmp);
464 return B.CreateSelect(Cmp, Src, NullPtr);
477 ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
488 if (!FT->getParamType(1)->isIntegerTy(IntBits))
495 ConstantInt::get(SizeTTy, Len),
B,
504 return B.CreateIntToPtr(
B.getTrue(), CI->
getType());
513 return B.CreateInBoundsGEP(
B.getInt8Ty(), SrcStr, StrLen,
"strchr");
526 return B.CreateInBoundsGEP(
B.getInt8Ty(), SrcStr,
B.getInt64(
I),
"strchr");
532 ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
538 if (CharC && CharC->
isZero())
549 Value *
Size = ConstantInt::get(SizeTTy, NBytes);
556 return ConstantInt::get(CI->
getType(), 0);
563 if (HasStr1 && HasStr2)
564 return ConstantInt::get(CI->
getType(),
565 std::clamp(Str1.
compare(Str2), -1, 1));
567 if (HasStr1 && Str1.
empty())
568 return B.CreateNeg(
B.CreateZExt(
569 B.CreateLoad(
B.getInt8Ty(), Str2P,
"strcmpload"), CI->
getType()));
571 if (HasStr2 && Str2.
empty())
572 return B.CreateZExt(
B.CreateLoad(
B.getInt8Ty(), Str1P,
"strcmpload"),
587 std::min(Len1, Len2)),
592 if (!HasStr1 && HasStr2) {
599 }
else if (HasStr1 && !HasStr2) {
623 return ConstantInt::get(CI->
getType(), 0);
635 return ConstantInt::get(CI->
getType(), 0);
645 if (HasStr1 && HasStr2) {
649 return ConstantInt::get(CI->
getType(),
650 std::clamp(SubStr1.
compare(SubStr2), -1, 1));
653 if (HasStr1 && Str1.
empty())
654 return B.CreateNeg(
B.CreateZExt(
655 B.CreateLoad(
B.getInt8Ty(), Str2P,
"strcmpload"), CI->
getType()));
657 if (HasStr2 && Str2.
empty())
658 return B.CreateZExt(
B.CreateLoad(
B.getInt8Ty(), Str1P,
"strcmpload"),
669 if (!HasStr1 && HasStr2) {
670 Len2 = std::min(Len2,
Length);
677 }
else if (HasStr1 && !HasStr2) {
678 Len1 = std::min(Len1,
Length);
694 if (SrcLen &&
Size) {
696 if (SrcLen <= Size->getZExtValue() + 1)
735 return StrLen ?
B.CreateInBoundsGEP(
B.getInt8Ty(), Dst, StrLen) :
nullptr;
745 Type *PT =
Callee->getFunctionType()->getParamType(0);
747 Value *DstEnd =
B.CreateInBoundsGEP(
748 B.getInt8Ty(), Dst, ConstantInt::get(DL.
getIntPtrType(PT), Len - 1));
771 NBytes = SizeC->getZExtValue();
780 B.CreateStore(
B.getInt8(0), Dst);
796 bool NulTerm = SrcLen < NBytes;
805 SrcLen = std::min(SrcLen,
uint64_t(Str.size()));
806 NBytes = std::min(NBytes - 1, SrcLen);
811 B.CreateStore(
B.getInt8(0), Dst);
812 return ConstantInt::get(CI->
getType(), 0);
816 Type *PT =
Callee->getFunctionType()->getParamType(0);
825 Value *EndOff = ConstantInt::get(CI->
getType(), NBytes);
826 Value *EndPtr =
B.CreateInBoundsGEP(
B.getInt8Ty(), Dst, EndOff);
827 B.CreateStore(
B.getInt8(0), EndPtr);
833 return ConstantInt::get(CI->
getType(), SrcLen);
838Value *LibCallSimplifier::optimizeStringNCpy(
CallInst *CI,
bool RetEnd,
856 N = SizeC->getZExtValue();
863 Type *CharTy =
B.getInt8Ty();
864 Value *CharVal =
B.CreateLoad(CharTy, Src,
"stxncpy.char0");
865 B.CreateStore(CharVal, Dst);
871 Value *ZeroChar = ConstantInt::get(CharTy, 0);
872 Value *
Cmp =
B.CreateICmpEQ(CharVal, ZeroChar,
"stpncpy.char0cmp");
874 Value *Off1 =
B.getInt32(1);
875 Value *EndPtr =
B.CreateInBoundsGEP(CharTy, Dst, Off1,
"stpncpy.end");
876 return B.CreateSelect(Cmp, Dst, EndPtr,
"stpncpy.sel");
892 CallInst *NewCI =
B.CreateMemSet(Dst,
B.getInt8(
'\0'),
Size, MemSetAlign);
900 if (
N > SrcLen + 1) {
909 std::string SrcStr = Str.str();
912 SrcStr.resize(
N,
'\0');
913 Src =
B.CreateGlobalString(SrcStr,
"str", 0,
917 Type *PT =
Callee->getFunctionType()->getParamType(0);
929 return B.CreateInBoundsGEP(
B.getInt8Ty(), Dst, Off,
"endptr");
936 Type *CharTy =
B.getIntNTy(CharSize);
946 return B.CreateZExt(
B.CreateLoad(CharTy, Src,
"char0"),
951 if (
ConstantInt *BoundCst = dyn_cast<ConstantInt>(Bound)) {
952 if (BoundCst->isZero())
954 return ConstantInt::get(CI->
getType(), 0);
956 if (BoundCst->isOne()) {
958 Value *CharVal =
B.CreateLoad(CharTy, Src,
"strnlen.char0");
959 Value *ZeroChar = ConstantInt::get(CharTy, 0);
960 Value *
Cmp =
B.CreateICmpNE(CharVal, ZeroChar,
"strnlen.char0cmp");
961 return B.CreateZExt(Cmp, CI->
getType());
971 return B.CreateBinaryIntrinsic(Intrinsic::umin, LenC, Bound);
995 if (Slice.
Array ==
nullptr) {
1014 cast<ArrayType>(
GEP->getSourceElementType())->getNumElements();
1021 (isa<GlobalVariable>(
GEP->getOperand(0)) &&
1022 NullTermIdx == ArrSize - 1)) {
1024 return B.CreateSub(ConstantInt::get(CI->
getType(), NullTermIdx),
1031 if (
SelectInst *SI = dyn_cast<SelectInst>(Src)) {
1034 if (LenTrue && LenFalse) {
1037 <<
"folded strlen(select) to select of constants";
1039 return B.CreateSelect(
SI->getCondition(),
1040 ConstantInt::get(CI->
getType(), LenTrue - 1),
1041 ConstantInt::get(CI->
getType(), LenFalse - 1));
1049 if (
Value *V = optimizeStringLength(CI,
B, 8))
1057 if (
Value *V = optimizeStringLength(CI,
B, 8, Bound))
1072 return optimizeStringLength(CI,
B, WCharSize);
1082 if ((HasS1 &&
S1.empty()) || (HasS2 && S2.
empty()))
1086 if (HasS1 && HasS2) {
1087 size_t I =
S1.find_first_of(S2);
1092 B.getInt64(
I),
"strpbrk");
1096 if (HasS2 && S2.
size() == 1)
1104 if (isa<ConstantPointerNull>(EndPtr)) {
1120 if ((HasS1 &&
S1.empty()) || (HasS2 && S2.
empty()))
1124 if (HasS1 && HasS2) {
1125 size_t Pos =
S1.find_first_not_of(S2);
1128 return ConstantInt::get(CI->
getType(), Pos);
1140 if (HasS1 &&
S1.empty())
1144 if (HasS1 && HasS2) {
1145 size_t Pos =
S1.find_first_of(S2);
1148 return ConstantInt::get(CI->
getType(), Pos);
1152 if (HasS2 && S2.
empty())
1169 StrLen,
B, DL, TLI);
1177 replaceAllUsesWith(Old, Cmp);
1188 if (HasStr2 && ToFindStr.
empty())
1192 if (HasStr1 && HasStr2) {
1199 return B.CreateConstInBoundsGEP1_64(
B.getInt8Ty(), CI->
getArgOperand(0),
1204 if (HasStr2 && ToFindStr.
size() == 1) {
1225 if (LenC->
isOne()) {
1228 Value *Val =
B.CreateLoad(
B.getInt8Ty(), SrcStr,
"memrchr.char0");
1230 CharVal =
B.CreateTrunc(CharVal,
B.getInt8Ty());
1231 Value *
Cmp =
B.CreateICmpEQ(Val, CharVal,
"memrchr.char0cmp");
1232 return B.CreateSelect(Cmp, SrcStr, NullPtr,
"memrchr.sel");
1240 if (Str.size() == 0)
1249 if (Str.size() < EndOff)
1254 if (
ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal)) {
1264 return B.CreateInBoundsGEP(
B.getInt8Ty(), SrcStr,
B.getInt64(Pos));
1266 if (Str.find(Str[Pos]) == Pos) {
1273 Value *SrcPlus =
B.CreateInBoundsGEP(
B.getInt8Ty(), SrcStr,
1274 B.getInt64(Pos),
"memrchr.ptr_plus");
1275 return B.CreateSelect(Cmp, NullPtr, SrcPlus,
"memrchr.sel");
1280 Str = Str.substr(0, EndOff);
1288 Type *Int8Ty =
B.getInt8Ty();
1289 Value *NNeZ =
B.CreateICmpNE(
Size, ConstantInt::get(SizeTy, 0));
1291 CharVal =
B.CreateTrunc(CharVal, Int8Ty);
1292 Value *CEqS0 =
B.CreateICmpEQ(ConstantInt::get(Int8Ty, Str[0]), CharVal);
1293 Value *
And =
B.CreateLogicalAnd(NNeZ, CEqS0);
1294 Value *SizeM1 =
B.CreateSub(
Size, ConstantInt::get(SizeTy, 1));
1296 B.CreateInBoundsGEP(Int8Ty, SrcStr, SizeM1,
"memrchr.ptr_plus");
1297 return B.CreateSelect(
And, SrcPlus, NullPtr,
"memrchr.sel");
1311 ConstantInt *CharC = dyn_cast<ConstantInt>(CharVal);
1320 if (LenC->
isOne()) {
1323 Value *Val =
B.CreateLoad(
B.getInt8Ty(), SrcStr,
"memchr.char0");
1325 CharVal =
B.CreateTrunc(CharVal,
B.getInt8Ty());
1326 Value *
Cmp =
B.CreateICmpEQ(Val, CharVal,
"memchr.char0cmp");
1327 return B.CreateSelect(Cmp, SrcStr, NullPtr,
"memchr.sel");
1347 Value *SrcPlus =
B.CreateInBoundsGEP(
B.getInt8Ty(), SrcStr,
B.getInt64(Pos),
1349 return B.CreateSelect(Cmp, NullPtr, SrcPlus);
1352 if (Str.size() == 0)
1361 size_t Pos = Str.find_first_not_of(Str[0]);
1374 Type *Int8Ty =
B.getInt8Ty();
1377 CharVal =
B.CreateTrunc(CharVal, Int8Ty);
1379 Value *Sel1 = NullPtr;
1382 Value *PosVal = ConstantInt::get(SizeTy, Pos);
1383 Value *StrPos = ConstantInt::get(Int8Ty, Str[Pos]);
1384 Value *CEqSPos =
B.CreateICmpEQ(CharVal, StrPos);
1386 Value *
And =
B.CreateAnd(CEqSPos, NGtPos);
1387 Value *SrcPlus =
B.CreateInBoundsGEP(
B.getInt8Ty(), SrcStr, PosVal);
1388 Sel1 =
B.CreateSelect(
And, SrcPlus, NullPtr,
"memchr.sel1");
1391 Value *Str0 = ConstantInt::get(Int8Ty, Str[0]);
1392 Value *CEqS0 =
B.CreateICmpEQ(Str0, CharVal);
1393 Value *NNeZ =
B.CreateICmpNE(
Size, ConstantInt::get(SizeTy, 0));
1395 return B.CreateSelect(
And, SrcStr, Sel1,
"memchr.sel2");
1427 *std::max_element(
reinterpret_cast<const unsigned char *
>(Str.begin()),
1428 reinterpret_cast<const unsigned char *
>(Str.end()));
1441 std::string SortedStr = Str.str();
1444 unsigned NonContRanges = 1;
1445 for (
size_t i = 1; i < SortedStr.size(); ++i) {
1446 if (SortedStr[i] > SortedStr[i - 1] + 1) {
1453 if (NonContRanges > 2)
1457 for (
unsigned char C : SortedStr)
1459 B.CreateICmpEQ(CharVal, ConstantInt::get(CharVal->
getType(),
C)));
1461 return B.CreateIntToPtr(
B.CreateOr(CharCompares), CI->
getType());
1466 unsigned char Width =
NextPowerOf2(std::max((
unsigned char)7, Max));
1476 C =
B.CreateAnd(
C,
B.getIntN(Width, 0xFF));
1483 Value *Shl =
B.CreateShl(
B.getIntN(Width, 1ULL),
C);
1484 Value *
Bits =
B.CreateIsNotNull(
B.CreateAnd(Shl, BitfieldC),
"memchr.bits");
1488 return B.CreateIntToPtr(
B.CreateLogicalAnd(Bounds, Bits,
"memchr"),
1513 if (Pos == MinSize ||
1514 (StrNCmp && (LStr[Pos] ==
'\0' && RStr[Pos] ==
'\0'))) {
1522 if (LStr[Pos] != RStr[Pos])
1527 typedef unsigned char UChar;
1528 int IRes = UChar(LStr[Pos]) < UChar(RStr[Pos]) ? -1 : 1;
1529 Value *MaxSize = ConstantInt::get(
Size->getType(), Pos);
1532 return B.CreateSelect(Cmp, Zero, Res);
1544 Value *LHSV =
B.CreateZExt(
B.CreateLoad(
B.getInt8Ty(),
LHS,
"lhsc"),
1546 Value *RHSV =
B.CreateZExt(
B.CreateLoad(
B.getInt8Ty(),
RHS,
"rhsc"),
1548 return B.CreateSub(LHSV, RHSV,
"chardiff");
1556 Align PrefAlignment =
DL.getPrefTypeAlign(IntType);
1559 Value *LHSV =
nullptr;
1560 if (
auto *LHSC = dyn_cast<Constant>(
LHS))
1563 Value *RHSV =
nullptr;
1564 if (
auto *RHSC = dyn_cast<Constant>(
RHS))
1572 LHSV =
B.CreateLoad(IntType,
LHS,
"lhsv");
1574 RHSV =
B.CreateLoad(IntType,
RHS,
"rhsv");
1575 return B.CreateZExt(
B.CreateICmpNE(LHSV, RHSV), CI->
getType(),
"memcmp");
1583Value *LibCallSimplifier::optimizeMemCmpBCmpCommon(
CallInst *CI,
1603 if (
Value *V = optimizeMemCmpBCmpCommon(CI,
B))
1621 return optimizeMemCmpBCmpCommon(CI,
B);
1627 if (isa<IntrinsicInst>(CI))
1647 if (
N->isNullValue())
1660 if (
N->getZExtValue() <= SrcStr.
size()) {
1669 ConstantInt::get(
N->getType(), std::min(
uint64_t(Pos + 1),
N->getZExtValue()));
1672 return Pos + 1 <=
N->getZExtValue()
1673 ?
B.CreateInBoundsGEP(
B.getInt8Ty(), Dst, NewN)
1687 return B.CreateInBoundsGEP(
B.getInt8Ty(), Dst,
N);
1693 if (isa<IntrinsicInst>(CI))
1706 if (isa<IntrinsicInst>(CI))
1751 case LibFunc_Znwm12__hot_cold_t:
1754 LibFunc_Znwm12__hot_cold_t, HotCold);
1759 LibFunc_Znwm12__hot_cold_t, HotCold);
1761 case LibFunc_Znam12__hot_cold_t:
1764 LibFunc_Znam12__hot_cold_t, HotCold);
1769 LibFunc_Znam12__hot_cold_t, HotCold);
1771 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
1775 LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);
1777 case LibFunc_ZnwmRKSt9nothrow_t:
1781 LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);
1783 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
1787 LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);
1789 case LibFunc_ZnamRKSt9nothrow_t:
1793 LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);
1795 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
1799 LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);
1801 case LibFunc_ZnwmSt11align_val_t:
1805 LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);
1807 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
1811 LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);
1813 case LibFunc_ZnamSt11align_val_t:
1817 LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);
1819 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
1823 TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
1826 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
1830 TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
1833 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
1837 TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
1840 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
1844 TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,
1871 if (
FPExtInst *Cast = dyn_cast<FPExtInst>(Val)) {
1872 Value *
Op = Cast->getOperand(0);
1873 if (
Op->getType()->isFloatTy())
1876 if (
ConstantFP *Const = dyn_cast<ConstantFP>(Val)) {
1882 return ConstantFP::get(Const->getContext(),
F);
1890 bool isPrecise =
false) {
1921 if (!CallerName.
empty() && CallerName.
back() ==
'f' &&
1922 CallerName.
size() == (CalleeName.
size() + 1) &&
1937 R =
isBinary ?
B.CreateCall(Fn, V) :
B.CreateCall(Fn, V[0]);
1944 return B.CreateFPExt(R,
B.getDoubleTy());
1950 bool isPrecise =
false) {
1957 bool isPrecise =
false) {
1971 assert(
Op->getType()->isArrayTy() &&
"Unexpected signature for cabs!");
1973 Real =
B.CreateExtractValue(
Op, 0,
"real");
1974 Imag =
B.CreateExtractValue(
Op, 1,
"imag");
1984 Value *AbsOp =
nullptr;
1985 if (
ConstantFP *ConstReal = dyn_cast<ConstantFP>(Real)) {
1986 if (ConstReal->isZero())
1989 }
else if (
ConstantFP *ConstImag = dyn_cast<ConstantFP>(Imag)) {
1990 if (ConstImag->isZero())
1999 *CI,
B.CreateUnaryIntrinsic(Intrinsic::fabs, AbsOp,
nullptr,
"cabs"));
2010 Value *RealReal =
B.CreateFMul(Real, Real);
2011 Value *ImagImag =
B.CreateFMul(Imag, Imag);
2013 return copyFlags(*CI,
B.CreateUnaryIntrinsic(Intrinsic::sqrt,
2014 B.CreateFAdd(RealReal, ImagImag),
2021 if (isa<SIToFPInst>(I2F) || isa<UIToFPInst>(I2F)) {
2022 Value *
Op = cast<Instruction>(I2F)->getOperand(0);
2025 unsigned BitWidth =
Op->getType()->getScalarSizeInBits();
2026 if (
BitWidth < DstWidth || (
BitWidth == DstWidth && isa<SIToFPInst>(I2F))) {
2027 Type *IntTy =
Op->getType()->getWithNewBitWidth(DstWidth);
2028 return isa<SIToFPInst>(I2F) ?
B.CreateSExt(
Op, IntTy)
2029 :
B.CreateZExt(
Op, IntTy);
2070 LibFunc LibFnFloat, LibFnDouble, LibFnLongDouble;
2078 ExpName = TLI->
getName(LibFunc_exp);
2079 ID = Intrinsic::exp;
2080 LibFnFloat = LibFunc_expf;
2081 LibFnDouble = LibFunc_exp;
2082 LibFnLongDouble = LibFunc_expl;
2087 ExpName = TLI->
getName(LibFunc_exp2);
2088 ID = Intrinsic::exp2;
2089 LibFnFloat = LibFunc_exp2f;
2090 LibFnDouble = LibFunc_exp2;
2091 LibFnLongDouble = LibFunc_exp2l;
2098 ?
B.CreateUnaryIntrinsic(
ID,
FMul,
nullptr, ExpName)
2107 substituteInParent(BaseFn, ExpFn);
2124 (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo)) &&
2126 hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl))) {
2131 Constant *One = ConstantFP::get(Ty, 1.0);
2134 return copyFlags(*Pow,
B.CreateIntrinsic(Intrinsic::ldexp,
2135 {Ty, ExpoI->getType()},
2136 {One, ExpoI}, Pow,
"exp2"));
2140 One, ExpoI, TLI, LibFunc_ldexp, LibFunc_ldexpf,
2141 LibFunc_ldexpl,
B, NoAttrs));
2146 if (
hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) {
2149 BaseR = BaseR / *BaseF;
2151 const APFloat *NF = IsReciprocal ? &BaseR : BaseF;
2153 if ((IsInteger || IsReciprocal) &&
2156 NI > 1 && NI.isPowerOf2()) {
2157 double N = NI.logBase2() * (IsReciprocal ? -1.0 : 1.0);
2158 Value *
FMul =
B.CreateFMul(Expo, ConstantFP::get(Ty,
N),
"mul");
2160 return copyFlags(*Pow,
B.CreateUnaryIntrinsic(Intrinsic::exp2,
FMul,
2165 LibFunc_exp2l,
B, NoAttrs));
2171 hasFloatFn(M, TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) {
2175 B.CreateIntrinsic(Intrinsic::exp10, {Ty}, {Expo}, Pow,
"exp10");
2180 LibFunc_exp10f, LibFunc_exp10l,
2190 "pow(1.0, y) should have been simplified earlier!");
2192 Value *Log =
nullptr;
2199 Value *
FMul =
B.CreateFMul(Log, Expo,
"mul");
2201 return copyFlags(*Pow,
B.CreateUnaryIntrinsic(Intrinsic::exp2,
FMul,
2203 else if (
hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f,
2207 LibFunc_exp2l,
B, NoAttrs));
2219 return B.CreateUnaryIntrinsic(Intrinsic::sqrt, V,
nullptr,
"sqrt");
2222 if (
hasFloatFn(M, TLI, V->getType(), LibFunc_sqrt, LibFunc_sqrtf,
2228 LibFunc_sqrtl,
B, Attrs);
2265 Sqrt =
B.CreateUnaryIntrinsic(Intrinsic::fabs, Sqrt,
nullptr,
"abs");
2274 Value *FCmp =
B.CreateFCmpOEQ(
Base, NegInf,
"isinf");
2275 Sqrt =
B.CreateSelect(FCmp, PosInf, Sqrt);
2280 Sqrt =
B.CreateFDiv(ConstantFP::get(Ty, 1.0), Sqrt,
"reciprocal");
2289 return B.CreateIntrinsic(Intrinsic::powi, Types, Args);
2311 if (
Value *Exp = replacePowWithExp(Pow,
B))
2318 return B.CreateFDiv(ConstantFP::get(Ty, 1.0),
Base,
"reciprocal");
2322 return ConstantFP::get(Ty, 1.0);
2330 return B.CreateFMul(
Base,
Base,
"square");
2332 if (
Value *Sqrt = replacePowWithSqrt(Pow,
B))
2343 Value *Sqrt =
nullptr;
2344 if (!ExpoA.isInteger()) {
2358 if (!ExpoI.isInteger())
2381 return B.CreateFMul(PowI, Sqrt);
2388 if (AllowApprox && (isa<SIToFPInst>(Expo) || isa<UIToFPInst>(Expo))) {
2395 if (UnsafeFPShrink &&
Name == TLI->
getName(LibFunc_pow) &&
2396 hasFloatVersion(M,
Name)) {
2409 if (UnsafeFPShrink &&
Name == TLI->
getName(LibFunc_exp2) &&
2410 hasFloatVersion(M,
Name))
2419 const bool UseIntrinsic =
Callee->isIntrinsic();
2428 if ((isa<SIToFPInst>(
Op) || isa<UIToFPInst>(
Op)) &&
2430 hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl))) {
2432 Constant *One = ConstantFP::get(Ty, 1.0);
2435 return copyFlags(*CI,
B.CreateIntrinsic(Intrinsic::ldexp,
2436 {Ty, Exp->getType()},
2443 One, Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf,
2458 if ((
Name ==
"fmin" ||
Name ==
"fmax") && hasFloatVersion(M,
Name))
2472 B.setFastMathFlags(FMF);
2475 : Intrinsic::maxnum;
2488 if (UnsafeFPShrink && hasFloatVersion(
Mod, LogNm))
2496 LibFunc LogLb, ExpLb, Exp2Lb, Exp10Lb, PowLb;
2502 LogID = Intrinsic::log;
2503 ExpLb = LibFunc_expf;
2504 Exp2Lb = LibFunc_exp2f;
2505 Exp10Lb = LibFunc_exp10f;
2506 PowLb = LibFunc_powf;
2509 LogID = Intrinsic::log;
2510 ExpLb = LibFunc_exp;
2511 Exp2Lb = LibFunc_exp2;
2512 Exp10Lb = LibFunc_exp10;
2513 PowLb = LibFunc_pow;
2516 LogID = Intrinsic::log;
2517 ExpLb = LibFunc_expl;
2518 Exp2Lb = LibFunc_exp2l;
2519 Exp10Lb = LibFunc_exp10l;
2520 PowLb = LibFunc_powl;
2523 LogID = Intrinsic::log2;
2524 ExpLb = LibFunc_expf;
2525 Exp2Lb = LibFunc_exp2f;
2526 Exp10Lb = LibFunc_exp10f;
2527 PowLb = LibFunc_powf;
2530 LogID = Intrinsic::log2;
2531 ExpLb = LibFunc_exp;
2532 Exp2Lb = LibFunc_exp2;
2533 Exp10Lb = LibFunc_exp10;
2534 PowLb = LibFunc_pow;
2537 LogID = Intrinsic::log2;
2538 ExpLb = LibFunc_expl;
2539 Exp2Lb = LibFunc_exp2l;
2540 Exp10Lb = LibFunc_exp10l;
2541 PowLb = LibFunc_powl;
2543 case LibFunc_log10f:
2544 LogID = Intrinsic::log10;
2545 ExpLb = LibFunc_expf;
2546 Exp2Lb = LibFunc_exp2f;
2547 Exp10Lb = LibFunc_exp10f;
2548 PowLb = LibFunc_powf;
2551 LogID = Intrinsic::log10;
2552 ExpLb = LibFunc_exp;
2553 Exp2Lb = LibFunc_exp2;
2554 Exp10Lb = LibFunc_exp10;
2555 PowLb = LibFunc_pow;
2557 case LibFunc_log10l:
2558 LogID = Intrinsic::log10;
2559 ExpLb = LibFunc_expl;
2560 Exp2Lb = LibFunc_exp2l;
2561 Exp10Lb = LibFunc_exp10l;
2562 PowLb = LibFunc_powl;
2567 else if (LogID == Intrinsic::log || LogID == Intrinsic::log2 ||
2568 LogID == Intrinsic::log10) {
2570 ExpLb = LibFunc_expf;
2571 Exp2Lb = LibFunc_exp2f;
2572 Exp10Lb = LibFunc_exp10f;
2573 PowLb = LibFunc_powf;
2575 ExpLb = LibFunc_exp;
2576 Exp2Lb = LibFunc_exp2;
2577 Exp10Lb = LibFunc_exp10;
2578 PowLb = LibFunc_pow;
2593 if (ArgLb == PowLb || ArgID == Intrinsic::pow || ArgID == Intrinsic::powi) {
2596 ?
B.CreateUnaryIntrinsic(LogID, Arg->
getOperand(0),
nullptr,
"log")
2600 if (ArgID == Intrinsic::powi)
2601 Y =
B.CreateSIToFP(
Y, Ty,
"cast");
2602 Value *MulY =
B.CreateFMul(
Y, LogX,
"mul");
2605 substituteInParent(Arg, MulY);
2611 if (ArgLb == ExpLb || ArgLb == Exp2Lb || ArgLb == Exp10Lb ||
2612 ArgID == Intrinsic::exp || ArgID == Intrinsic::exp2) {
2614 if (ArgLb == ExpLb || ArgID == Intrinsic::exp)
2617 else if (ArgLb == Exp2Lb || ArgID == Intrinsic::exp2)
2618 Eul = ConstantFP::get(Log->
getType(), 2.0);
2620 Eul = ConstantFP::get(Log->
getType(), 10.0);
2622 ?
B.CreateUnaryIntrinsic(LogID, Eul,
nullptr,
"log")
2627 substituteInParent(Arg, MulY);
2647 LibFunc SqrtLb, ExpLb, Exp2Lb, Exp10Lb;
2652 ExpLb = LibFunc_expf;
2653 Exp2Lb = LibFunc_exp2f;
2654 Exp10Lb = LibFunc_exp10f;
2657 ExpLb = LibFunc_exp;
2658 Exp2Lb = LibFunc_exp2;
2659 Exp10Lb = LibFunc_exp10;
2662 ExpLb = LibFunc_expl;
2663 Exp2Lb = LibFunc_exp2l;
2664 Exp10Lb = LibFunc_exp10l;
2671 ExpLb = LibFunc_expf;
2672 Exp2Lb = LibFunc_exp2f;
2673 Exp10Lb = LibFunc_exp10f;
2675 ExpLb = LibFunc_exp;
2676 Exp2Lb = LibFunc_exp2;
2677 Exp10Lb = LibFunc_exp10;
2683 if (ArgLb != ExpLb && ArgLb != Exp2Lb && ArgLb != Exp10Lb &&
2684 ArgID != Intrinsic::exp && ArgID != Intrinsic::exp2)
2688 B.SetInsertPoint(Arg);
2691 B.CreateFMulFMF(ExpOperand, ConstantFP::get(ExpOperand->getType(), 0.5),
2706 (
Callee->getName() ==
"sqrt" ||
2707 Callee->getIntrinsicID() == Intrinsic::sqrt))
2710 if (
Value *Opt = mergeSqrtToExp(CI,
B))
2717 if (!
I ||
I->getOpcode() != Instruction::FMul || !
I->isFast())
2723 Value *Op0 =
I->getOperand(0);
2724 Value *Op1 =
I->getOperand(1);
2725 Value *RepeatOp =
nullptr;
2726 Value *OtherOp =
nullptr;
2736 Value *OtherMul0, *OtherMul1;
2739 if (OtherMul0 == OtherMul1 && cast<Instruction>(Op0)->isFast()) {
2741 RepeatOp = OtherMul0;
2752 B.setFastMathFlags(
I->getFastMathFlags());
2757 B.CreateUnaryIntrinsic(Intrinsic::fabs, RepeatOp,
nullptr,
"fabs");
2763 B.CreateUnaryIntrinsic(Intrinsic::sqrt, OtherOp,
nullptr,
"sqrt");
2764 return copyFlags(*CI,
B.CreateFMul(FabsCall, SqrtCall));
2769Value *LibCallSimplifier::optimizeTrigInversionPairs(
CallInst *CI,
2775 if (UnsafeFPShrink &&
2778 hasFloatVersion(M,
Name))
2782 auto *OpC = dyn_cast<CallInst>(Op1);
2787 if (!CI->
isFast() || !OpC->isFast())
2800 .
Case(
"tan", LibFunc_atan)
2801 .
Case(
"atanh", LibFunc_tanh)
2802 .
Case(
"sinh", LibFunc_asinh)
2803 .
Case(
"cosh", LibFunc_acosh)
2804 .
Case(
"tanf", LibFunc_atanf)
2805 .
Case(
"atanhf", LibFunc_tanhf)
2806 .
Case(
"sinhf", LibFunc_asinhf)
2807 .
Case(
"coshf", LibFunc_acoshf)
2808 .
Case(
"tanl", LibFunc_atanl)
2809 .
Case(
"atanhl", LibFunc_tanhl)
2810 .
Case(
"sinhl", LibFunc_asinhl)
2811 .
Case(
"coshl", LibFunc_acoshl)
2812 .
Case(
"asinh", LibFunc_sinh)
2813 .
Case(
"asinhf", LibFunc_sinhf)
2814 .
Case(
"asinhl", LibFunc_sinhl)
2816 if (Func == inverseFunc)
2817 Ret = OpC->getArgOperand(0);
2839 Name =
"__sincospif_stret";
2848 Name =
"__sincospi_stret";
2857 M, *TLI, TheLibFunc, OrigCallee->
getAttributes(), ResTy, ArgTy);
2859 if (
Instruction *ArgInst = dyn_cast<Instruction>(Arg)) {
2862 B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());
2866 BasicBlock &EntryBB =
B.GetInsertBlock()->getParent()->getEntryBlock();
2867 B.SetInsertPoint(&EntryBB, EntryBB.
begin());
2870 SinCos =
B.CreateCall(Callee, Arg,
"sincospi");
2873 Sin =
B.CreateExtractValue(SinCos, 0,
"sinpi");
2874 Cos =
B.CreateExtractValue(SinCos, 1,
"cospi");
2876 Sin =
B.CreateExtractElement(SinCos, ConstantInt::get(
B.getInt32Ty(), 0),
2878 Cos =
B.CreateExtractElement(SinCos, ConstantInt::get(
B.getInt32Ty(), 1),
2960 classifyArgUse(U,
F, IsFloat, SinCalls, CosCalls, SinCosCalls);
2966 Value *Sin, *Cos, *SinCos;
2974 replaceAllUsesWith(
C, Res);
2977 replaceTrigInsts(SinCalls, Sin);
2978 replaceTrigInsts(CosCalls, Cos);
2979 replaceTrigInsts(SinCosCalls, SinCos);
2981 return IsSin ? Sin : Cos;
2984void LibCallSimplifier::classifyArgUse(
2989 auto *CI = dyn_cast<CallInst>(Val);
3000 if (!Callee || !TLI->
getLibFunc(*Callee, Func) ||
3006 if (Func == LibFunc_sinpif)
3008 else if (Func == LibFunc_cospif)
3010 else if (Func == LibFunc_sincospif_stret)
3013 if (Func == LibFunc_sinpi)
3015 else if (Func == LibFunc_cospi)
3017 else if (Func == LibFunc_sincospi_stret)
3040 APSInt QuotInt(IntBW,
false);
3047 B.CreateAlignedStore(
3048 ConstantInt::get(
B.getIntNTy(IntBW), QuotInt.getExtValue()),
3050 return ConstantFP::get(CI->
getType(), Rem);
3062 Type *ArgType =
Op->getType();
3063 Value *
V =
B.CreateIntrinsic(Intrinsic::cttz, {ArgType}, {
Op,
B.getTrue()},
3065 V =
B.CreateAdd(V, ConstantInt::get(
V->getType(), 1));
3066 V =
B.CreateIntCast(V, RetType,
false);
3069 return B.CreateSelect(
Cond, V, ConstantInt::get(RetType, 0));
3076 Type *ArgType =
Op->getType();
3077 Value *
V =
B.CreateIntrinsic(Intrinsic::ctlz, {ArgType}, {
Op,
B.getFalse()},
3081 return B.CreateIntCast(V, CI->
getType(),
false);
3088 Value *IsNeg =
B.CreateIsNeg(
X);
3089 Value *NegX =
B.CreateNSWNeg(
X,
"neg");
3090 return B.CreateSelect(IsNeg, NegX,
X);
3096 Type *ArgType =
Op->getType();
3097 Op =
B.CreateSub(
Op, ConstantInt::get(ArgType,
'0'),
"isdigittmp");
3098 Op =
B.CreateICmpULT(
Op, ConstantInt::get(ArgType, 10),
"isdigit");
3105 Type *ArgType =
Op->getType();
3106 Op =
B.CreateICmpULT(
Op, ConstantInt::get(ArgType, 128),
"isascii");
3113 ConstantInt::get(CI->
getType(), 0x7F));
3131 if (isa<ConstantPointerNull>(EndPtr)) {
3144 return convertStrToInt(CI, Str, EndPtr, CInt->getSExtValue(), AsSigned,
B);
3176 if (!Callee || !Callee->isDeclaration())
3185 if (StreamArg >= (
int)CI->
arg_size())
3193 return GV->
getName() ==
"stderr";
3203 if (FormatStr.
empty())
3214 if (FormatStr.
size() == 1 || FormatStr ==
"%%") {
3218 Value *IntChar = ConstantInt::get(IntTy, (
unsigned char)FormatStr[0]);
3223 if (FormatStr ==
"%s" && CI->
arg_size() > 1) {
3228 if (OperandStr.
empty())
3231 if (OperandStr.
size() == 1) {
3235 Value *IntChar = ConstantInt::get(IntTy, (
unsigned char)OperandStr[0]);
3239 if (OperandStr.
back() ==
'\n') {
3241 Value *GV =
B.CreateGlobalString(OperandStr,
"str");
3248 if (FormatStr.
back() ==
'\n' &&
3253 Value *GV =
B.CreateGlobalString(FormatStr,
"str");
3259 if (FormatStr ==
"%c" && CI->
arg_size() > 1 &&
3268 if (FormatStr ==
"%s\n" && CI->
arg_size() > 1 &&
3279 if (
Value *V = optimizePrintFString(CI,
B)) {
3290 Callee->getAttributes());
3292 New->setCalledFunction(IPrintFFn);
3302 Callee->getAttributes());
3304 New->setCalledFunction(SmallPrintFFn);
3312Value *LibCallSimplifier::optimizeSPrintFString(
CallInst *CI,
3331 FormatStr.
size() + 1));
3332 return ConstantInt::get(CI->
getType(), FormatStr.
size());
3337 if (FormatStr.
size() != 2 || FormatStr[0] !=
'%' || CI->
arg_size() < 3)
3341 if (FormatStr[1] ==
'c') {
3347 B.CreateStore(V,
Ptr);
3348 Ptr =
B.CreateInBoundsGEP(
B.getInt8Ty(),
Ptr,
B.getInt32(1),
"nul");
3349 B.CreateStore(
B.getInt8(0),
Ptr);
3351 return ConstantInt::get(CI->
getType(), 1);
3354 if (FormatStr[1] ==
's') {
3370 return ConstantInt::get(CI->
getType(), SrcLen - 1);
3373 Value *PtrDiff =
B.CreatePtrDiff(
B.getInt8Ty(), V, Dest);
3374 return B.CreateIntCast(PtrDiff, CI->
getType(),
false);
3387 B.CreateAdd(Len, ConstantInt::get(
Len->getType(), 1),
"leninc");
3391 return B.CreateIntCast(Len, CI->
getType(),
false);
3400 if (
Value *V = optimizeSPrintFString(CI,
B)) {
3411 FT,
Callee->getAttributes());
3413 New->setCalledFunction(SIPrintFFn);
3423 Callee->getAttributes());
3425 New->setCalledFunction(SmallSPrintFFn);
3441 assert(StrArg || (
N < 2 && Str.size() == 1));
3445 if (Str.size() > IntMax)
3451 Value *StrLen = ConstantInt::get(CI->
getType(), Str.size());
3461 NCopy = Str.size() + 1;
3466 if (NCopy && StrArg)
3480 Type *Int8Ty =
B.getInt8Ty();
3481 Value *NulOff =
B.getIntN(IntBits, NCopy);
3482 Value *DstEnd =
B.CreateInBoundsGEP(Int8Ty, DstArg, NulOff,
"endptr");
3483 B.CreateStore(ConstantInt::get(Int8Ty, 0), DstEnd);
3487Value *LibCallSimplifier::optimizeSnPrintFString(
CallInst *CI,
3516 return emitSnPrintfMemCpy(CI, FmtArg, FormatStr,
N,
B);
3521 if (FormatStr.
size() != 2 || FormatStr[0] !=
'%' || CI->
arg_size() != 4)
3525 if (FormatStr[1] ==
'c') {
3531 return emitSnPrintfMemCpy(CI,
nullptr, CharStr,
N,
B);
3539 B.CreateStore(V,
Ptr);
3540 Ptr =
B.CreateInBoundsGEP(
B.getInt8Ty(),
Ptr,
B.getInt32(1),
"nul");
3541 B.CreateStore(
B.getInt8(0),
Ptr);
3542 return ConstantInt::get(CI->
getType(), 1);
3545 if (FormatStr[1] !=
's')
3554 return emitSnPrintfMemCpy(CI, StrArg, Str,
N,
B);
3558 if (
Value *V = optimizeSnPrintFString(CI,
B)) {
3567Value *LibCallSimplifier::optimizeFPrintFString(
CallInst *CI,
3569 optimizeErrorReporting(CI,
B, 0);
3592 ConstantInt::get(SizeTTy, FormatStr.
size()),
3598 if (FormatStr.
size() != 2 || FormatStr[0] !=
'%' || CI->
arg_size() < 3)
3602 if (FormatStr[1] ==
'c') {
3612 if (FormatStr[1] ==
's') {
3626 if (
Value *V = optimizeFPrintFString(CI,
B)) {
3635 FT,
Callee->getAttributes());
3637 New->setCalledFunction(FIPrintFFn);
3646 auto SmallFPrintFFn =
3648 Callee->getAttributes());
3650 New->setCalledFunction(SmallFPrintFFn);
3659 optimizeErrorReporting(CI,
B, 3);
3664 if (SizeC && CountC) {
3669 return ConstantInt::get(CI->
getType(), 0);
3676 Value *Cast =
B.CreateIntCast(Char, IntTy,
true,
"chari");
3678 return NewCI ? ConstantInt::get(CI->
getType(), 1) : nullptr;
3686 optimizeErrorReporting(CI,
B, 1);
3711 ConstantInt::get(SizeTTy, Len - 1),
3751bool LibCallSimplifier::hasFloatVersion(
const Module *M,
StringRef FuncName) {
3753 FloatFuncName +=
'f';
3757Value *LibCallSimplifier::optimizeStringMemoryLibCall(
CallInst *CI,
3768 "Optimizing string/memory libcall would change the calling convention");
3770 case LibFunc_strcat:
3771 return optimizeStrCat(CI, Builder);
3772 case LibFunc_strncat:
3773 return optimizeStrNCat(CI, Builder);
3774 case LibFunc_strchr:
3775 return optimizeStrChr(CI, Builder);
3776 case LibFunc_strrchr:
3777 return optimizeStrRChr(CI, Builder);
3778 case LibFunc_strcmp:
3779 return optimizeStrCmp(CI, Builder);
3780 case LibFunc_strncmp:
3781 return optimizeStrNCmp(CI, Builder);
3782 case LibFunc_strcpy:
3783 return optimizeStrCpy(CI, Builder);
3784 case LibFunc_stpcpy:
3785 return optimizeStpCpy(CI, Builder);
3786 case LibFunc_strlcpy:
3787 return optimizeStrLCpy(CI, Builder);
3788 case LibFunc_stpncpy:
3789 return optimizeStringNCpy(CI,
true, Builder);
3790 case LibFunc_strncpy:
3791 return optimizeStringNCpy(CI,
false, Builder);
3792 case LibFunc_strlen:
3793 return optimizeStrLen(CI, Builder);
3794 case LibFunc_strnlen:
3795 return optimizeStrNLen(CI, Builder);
3796 case LibFunc_strpbrk:
3797 return optimizeStrPBrk(CI, Builder);
3798 case LibFunc_strndup:
3799 return optimizeStrNDup(CI, Builder);
3800 case LibFunc_strtol:
3801 case LibFunc_strtod:
3802 case LibFunc_strtof:
3803 case LibFunc_strtoul:
3804 case LibFunc_strtoll:
3805 case LibFunc_strtold:
3806 case LibFunc_strtoull:
3807 return optimizeStrTo(CI, Builder);
3808 case LibFunc_strspn:
3809 return optimizeStrSpn(CI, Builder);
3810 case LibFunc_strcspn:
3811 return optimizeStrCSpn(CI, Builder);
3812 case LibFunc_strstr:
3813 return optimizeStrStr(CI, Builder);
3814 case LibFunc_memchr:
3815 return optimizeMemChr(CI, Builder);
3816 case LibFunc_memrchr:
3817 return optimizeMemRChr(CI, Builder);
3819 return optimizeBCmp(CI, Builder);
3820 case LibFunc_memcmp:
3821 return optimizeMemCmp(CI, Builder);
3822 case LibFunc_memcpy:
3823 return optimizeMemCpy(CI, Builder);
3824 case LibFunc_memccpy:
3825 return optimizeMemCCpy(CI, Builder);
3826 case LibFunc_mempcpy:
3827 return optimizeMemPCpy(CI, Builder);
3828 case LibFunc_memmove:
3829 return optimizeMemMove(CI, Builder);
3830 case LibFunc_memset:
3831 return optimizeMemSet(CI, Builder);
3832 case LibFunc_realloc:
3833 return optimizeRealloc(CI, Builder);
3834 case LibFunc_wcslen:
3835 return optimizeWcslen(CI, Builder);
3837 return optimizeBCopy(CI, Builder);
3839 case LibFunc_ZnwmRKSt9nothrow_t:
3840 case LibFunc_ZnwmSt11align_val_t:
3841 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
3843 case LibFunc_ZnamRKSt9nothrow_t:
3844 case LibFunc_ZnamSt11align_val_t:
3845 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
3846 case LibFunc_Znwm12__hot_cold_t:
3847 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
3848 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
3849 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
3850 case LibFunc_Znam12__hot_cold_t:
3851 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
3852 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
3853 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
3854 return optimizeNew(CI, Builder, Func);
3870 if (CharSeq.
empty())
3871 Fill =
APInt(32, 0);
3878Value *LibCallSimplifier::optimizeFloatingPointLibCall(
CallInst *CI,
3887 if (
Value *V = optimizeSymmetric(CI, Func, Builder))
3891 case LibFunc_sinpif:
3893 return optimizeSinCosPi(CI,
true, Builder);
3894 case LibFunc_cospif:
3896 return optimizeSinCosPi(CI,
false, Builder);
3900 return optimizePow(CI, Builder);
3904 return optimizeExp2(CI, Builder);
3912 return optimizeSqrt(CI, Builder);
3916 case LibFunc_log10f:
3918 case LibFunc_log10l:
3919 case LibFunc_log1pf:
3921 case LibFunc_log1pl:
3928 return optimizeLog(CI, Builder);
3936 case LibFunc_asinhf:
3937 case LibFunc_asinhl:
3942 case LibFunc_atanhf:
3943 case LibFunc_atanhl:
3944 return optimizeTrigInversionPairs(CI, Builder);
3951 case LibFunc_roundeven:
3953 case LibFunc_nearbyint:
3973 case LibFunc_copysign:
3983 return optimizeFMinFMax(CI, Builder);
3987 return optimizeCAbs(CI, Builder);
3988 case LibFunc_remquo:
3989 case LibFunc_remquof:
3990 case LibFunc_remquol:
3991 return optimizeRemquo(CI, Builder);
4026 else if (isa<FPMathOperator>(CI) && CI->
isFast())
4027 UnsafeFPShrink =
true;
4031 if (!IsCallingConvC)
4035 switch (
II->getIntrinsicID()) {
4036 case Intrinsic::pow:
4037 return optimizePow(CI, Builder);
4038 case Intrinsic::exp2:
4039 return optimizeExp2(CI, Builder);
4040 case Intrinsic::log:
4041 case Intrinsic::log2:
4042 case Intrinsic::log10:
4043 return optimizeLog(CI, Builder);
4044 case Intrinsic::sqrt:
4045 return optimizeSqrt(CI, Builder);
4046 case Intrinsic::memset:
4047 return optimizeMemSet(CI, Builder);
4048 case Intrinsic::memcpy:
4049 return optimizeMemCpy(CI, Builder);
4050 case Intrinsic::memmove:
4051 return optimizeMemMove(CI, Builder);
4058 if (
Value *SimplifiedFortifiedCI =
4060 return SimplifiedFortifiedCI;
4067 if (
Value *V = optimizeStringMemoryLibCall(CI, Builder))
4069 if (
Value *V = optimizeFloatingPointLibCall(CI, Func, Builder))
4075 return optimizeFFS(CI, Builder);
4079 return optimizeFls(CI, Builder);
4083 return optimizeAbs(CI, Builder);
4084 case LibFunc_isdigit:
4085 return optimizeIsDigit(CI, Builder);
4086 case LibFunc_isascii:
4087 return optimizeIsAscii(CI, Builder);
4088 case LibFunc_toascii:
4089 return optimizeToAscii(CI, Builder);
4093 return optimizeAtoi(CI, Builder);
4094 case LibFunc_strtol:
4095 case LibFunc_strtoll:
4096 return optimizeStrToInt(CI, Builder,
true);
4097 case LibFunc_strtoul:
4098 case LibFunc_strtoull:
4099 return optimizeStrToInt(CI, Builder,
false);
4100 case LibFunc_printf:
4101 return optimizePrintF(CI, Builder);
4102 case LibFunc_sprintf:
4103 return optimizeSPrintF(CI, Builder);
4104 case LibFunc_snprintf:
4105 return optimizeSnPrintF(CI, Builder);
4106 case LibFunc_fprintf:
4107 return optimizeFPrintF(CI, Builder);
4108 case LibFunc_fwrite:
4109 return optimizeFWrite(CI, Builder);
4111 return optimizeFPuts(CI, Builder);
4113 return optimizePuts(CI, Builder);
4114 case LibFunc_perror:
4115 return optimizeErrorReporting(CI, Builder);
4116 case LibFunc_vfprintf:
4117 case LibFunc_fiprintf:
4118 return optimizeErrorReporting(CI, Builder, 0);
4121 return optimizeExit(CI);
4135 : FortifiedSimplifier(TLI),
DL(
DL), TLI(TLI), AC(AC), ORE(ORE), BFI(BFI),
4136 PSI(PSI), Replacer(Replacer), Eraser(Eraser) {}
4143void LibCallSimplifier::eraseFromParent(
Instruction *
I) {
4182bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(
4183 CallInst *CI,
unsigned ObjSizeOp, std::optional<unsigned> SizeOp,
4184 std::optional<unsigned> StrOp, std::optional<unsigned> FlagOp) {
4189 if (!Flag || !
Flag->isZero())
4198 if (ObjSizeCI->isMinusOne())
4201 if (OnlyLowerUnknownSize)
4211 return ObjSizeCI->getZExtValue() >=
Len;
4217 return ObjSizeCI->getZExtValue() >= SizeCI->getZExtValue();
4223Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(
CallInst *CI,
4225 if (isFortifiedCallFoldable(CI, 3, 2)) {
4235Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(
CallInst *CI,
4237 if (isFortifiedCallFoldable(CI, 3, 2)) {
4247Value *FortifiedLibCallSimplifier::optimizeMemSetChk(
CallInst *CI,
4249 if (isFortifiedCallFoldable(CI, 3, 2)) {
4259Value *FortifiedLibCallSimplifier::optimizeMemPCpyChk(
CallInst *CI,
4262 if (isFortifiedCallFoldable(CI, 3, 2))
4270Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(
CallInst *CI,
4278 if (Func == LibFunc_stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) {
4280 return StrLen ?
B.CreateInBoundsGEP(
B.getInt8Ty(), Dst, StrLen) :
nullptr;
4288 if (isFortifiedCallFoldable(CI, 2, std::nullopt, 1)) {
4289 if (Func == LibFunc_strcpy_chk)
4295 if (OnlyLowerUnknownSize)
4307 Value *LenV = ConstantInt::get(SizeTTy, Len);
4311 if (Ret && Func == LibFunc_stpcpy_chk)
4312 return B.CreateInBoundsGEP(
B.getInt8Ty(), Dst,
4313 ConstantInt::get(SizeTTy, Len - 1));
4314 return copyFlags(*CI, cast<CallInst>(Ret));
4317Value *FortifiedLibCallSimplifier::optimizeStrLenChk(
CallInst *CI,
4319 if (isFortifiedCallFoldable(CI, 1, std::nullopt, 0))
4325Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(
CallInst *CI,
4328 if (isFortifiedCallFoldable(CI, 3, 2)) {
4329 if (Func == LibFunc_strncpy_chk)
4342Value *FortifiedLibCallSimplifier::optimizeMemCCpyChk(
CallInst *CI,
4344 if (isFortifiedCallFoldable(CI, 4, 3))
4352Value *FortifiedLibCallSimplifier::optimizeSNPrintfChk(
CallInst *CI,
4354 if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2)) {
4364Value *FortifiedLibCallSimplifier::optimizeSPrintfChk(
CallInst *CI,
4366 if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1)) {
4370 VariadicArgs,
B, TLI));
4376Value *FortifiedLibCallSimplifier::optimizeStrCatChk(
CallInst *CI,
4378 if (isFortifiedCallFoldable(CI, 2))
4385Value *FortifiedLibCallSimplifier::optimizeStrLCat(
CallInst *CI,
4387 if (isFortifiedCallFoldable(CI, 3))
4395Value *FortifiedLibCallSimplifier::optimizeStrNCatChk(
CallInst *CI,
4397 if (isFortifiedCallFoldable(CI, 3))
4405Value *FortifiedLibCallSimplifier::optimizeStrLCpyChk(
CallInst *CI,
4407 if (isFortifiedCallFoldable(CI, 3))
4415Value *FortifiedLibCallSimplifier::optimizeVSNPrintfChk(
CallInst *CI,
4417 if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2))
4425Value *FortifiedLibCallSimplifier::optimizeVSPrintfChk(
CallInst *CI,
4427 if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1))
4470 case LibFunc_memcpy_chk:
4471 return optimizeMemCpyChk(CI, Builder);
4472 case LibFunc_mempcpy_chk:
4473 return optimizeMemPCpyChk(CI, Builder);
4474 case LibFunc_memmove_chk:
4475 return optimizeMemMoveChk(CI, Builder);
4476 case LibFunc_memset_chk:
4477 return optimizeMemSetChk(CI, Builder);
4478 case LibFunc_stpcpy_chk:
4479 case LibFunc_strcpy_chk:
4480 return optimizeStrpCpyChk(CI, Builder, Func);
4481 case LibFunc_strlen_chk:
4482 return optimizeStrLenChk(CI, Builder);
4483 case LibFunc_stpncpy_chk:
4484 case LibFunc_strncpy_chk:
4485 return optimizeStrpNCpyChk(CI, Builder, Func);
4486 case LibFunc_memccpy_chk:
4487 return optimizeMemCCpyChk(CI, Builder);
4488 case LibFunc_snprintf_chk:
4489 return optimizeSNPrintfChk(CI, Builder);
4490 case LibFunc_sprintf_chk:
4491 return optimizeSPrintfChk(CI, Builder);
4492 case LibFunc_strcat_chk:
4493 return optimizeStrCatChk(CI, Builder);
4494 case LibFunc_strlcat_chk:
4495 return optimizeStrLCat(CI, Builder);
4496 case LibFunc_strncat_chk:
4497 return optimizeStrNCatChk(CI, Builder);
4498 case LibFunc_strlcpy_chk:
4499 return optimizeStrLCpyChk(CI, Builder);
4500 case LibFunc_vsnprintf_chk:
4501 return optimizeVSNPrintfChk(CI, Builder);
4502 case LibFunc_vsprintf_chk:
4503 return optimizeVSPrintfChk(CI, Builder);
4512 : TLI(TLI), OnlyLowerUnknownSize(OnlyLowerUnknownSize) {}
This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static bool isBinary(MachineInstr &MI)
const SmallVectorImpl< MachineOperand > & Cond
static bool isDigit(const char C)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool isOnlyUsedInEqualityComparison(Value *V, Value *With)
Return true if it is only used in equality comparisons with With.
static void annotateNonNullAndDereferenceable(CallInst *CI, ArrayRef< unsigned > ArgNos, Value *Size, const DataLayout &DL)
static cl::opt< unsigned, false, HotColdHintParser > ColdNewHintValue("cold-new-hint-value", cl::Hidden, cl::init(1), cl::desc("Value to pass to hot/cold operator new for cold allocation"))
static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value *Arg, bool UseFloat, Value *&Sin, Value *&Cos, Value *&SinCos, const TargetLibraryInfo *TLI)
static bool canTransformToMemCmp(CallInst *CI, Value *Str, uint64_t Len, const DataLayout &DL)
static Value * mergeAttributesAndFlags(CallInst *NewCI, const CallInst &Old)
static cl::opt< bool > OptimizeHotColdNew("optimize-hot-cold-new", cl::Hidden, cl::init(false), cl::desc("Enable hot/cold operator new library calls"))
static Value * optimizeBinaryDoubleFP(CallInst *CI, IRBuilderBase &B, const TargetLibraryInfo *TLI, bool isPrecise=false)
Shrink double -> float for binary functions.
static bool ignoreCallingConv(LibFunc Func)
static cl::opt< bool > OptimizeExistingHotColdNew("optimize-existing-hot-cold-new", cl::Hidden, cl::init(false), cl::desc("Enable optimization of existing hot/cold operator new library calls"))
static void annotateDereferenceableBytes(CallInst *CI, ArrayRef< unsigned > ArgNos, uint64_t DereferenceableBytes)
static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg)
static Value * optimizeDoubleFP(CallInst *CI, IRBuilderBase &B, bool isBinary, const TargetLibraryInfo *TLI, bool isPrecise=false)
Shrink double -> float functions.
static Value * optimizeSymmetricCall(CallInst *CI, bool IsEven, IRBuilderBase &B)
static Value * getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno, Module *M, IRBuilderBase &B, const TargetLibraryInfo *TLI)
static Value * valueHasFloatPrecision(Value *Val)
Return a variant of Val with float type.
static Value * optimizeMemCmpConstantSize(CallInst *CI, Value *LHS, Value *RHS, uint64_t Len, IRBuilderBase &B, const DataLayout &DL)
static Value * createPowWithIntegerExponent(Value *Base, Value *Expo, Module *M, IRBuilderBase &B)
static Value * convertStrToInt(CallInst *CI, StringRef &Str, Value *EndPtr, uint64_t Base, bool AsSigned, IRBuilderBase &B)
static Value * memChrToCharCompare(CallInst *CI, Value *NBytes, IRBuilderBase &B, const DataLayout &DL)
static Value * copyFlags(const CallInst &Old, Value *New)
static StringRef substr(StringRef Str, uint64_t Len)
static cl::opt< unsigned, false, HotColdHintParser > HotNewHintValue("hot-new-hint-value", cl::Hidden, cl::init(254), cl::desc("Value to pass to hot/cold operator new for hot allocation"))
static bool isTrigLibCall(CallInst *CI)
static Value * optimizeNaN(CallInst *CI)
Constant folding nan/nanf/nanl.
static bool isOnlyUsedInComparisonWithZero(Value *V)
static Value * replaceUnaryCall(CallInst *CI, IRBuilderBase &B, Intrinsic::ID IID)
static bool callHasFloatingPointArgument(const CallInst *CI)
static Value * optimizeUnaryDoubleFP(CallInst *CI, IRBuilderBase &B, const TargetLibraryInfo *TLI, bool isPrecise=false)
Shrink double -> float for unary functions.
static bool callHasFP128Argument(const CallInst *CI)
static void annotateNonNullNoUndefBasedOnAccess(CallInst *CI, ArrayRef< unsigned > ArgNos)
static Value * optimizeMemCmpVarSize(CallInst *CI, Value *LHS, Value *RHS, Value *Size, bool StrNCmp, IRBuilderBase &B, const DataLayout &DL)
static Value * getIntToFPVal(Value *I2F, IRBuilderBase &B, unsigned DstWidth)
static cl::opt< bool > EnableUnsafeFPShrink("enable-double-float-shrink", cl::Hidden, cl::init(false), cl::desc("Enable unsafe double to float " "shrinking for math lib calls"))
static cl::opt< unsigned, false, HotColdHintParser > NotColdNewHintValue("notcold-new-hint-value", cl::Hidden, cl::init(128), cl::desc("Value to pass to hot/cold operator new for " "notcold (warm) allocation"))
This file defines the SmallString class.
opStatus divide(const APFloat &RHS, roundingMode RM)
bool isFiniteNonZero() const
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
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 ...
opStatus add(const APFloat &RHS, roundingMode RM)
const fltSemantics & getSemantics() const
float convertToFloat() const
Converts this APFloat to host float value.
opStatus remainder(const APFloat &RHS)
opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const
Class for arbitrary precision integers.
bool ule(const APInt &RHS) const
Unsigned less or equal comparison.
An arbitrary precision integer that knows its signedness.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
A cache of @llvm.assume calls within a function.
static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)
Create an AttributeList with the specified parameters in it.
Attribute getFnAttr(Attribute::AttrKind Kind) const
Return the attribute object that exists for the function.
AttributeSet getParamAttrs(unsigned ArgNo) const
The attributes for the argument or parameter at the given index are returned.
AttributeList addParamAttributes(LLVMContext &C, unsigned ArgNo, const AttrBuilder &B) const
Add an argument attribute to the list.
MaybeAlign getAlignment() const
static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)
StringRef getValueAsString() const
Return the attribute's value as a string.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
void addFnAttr(Attribute::AttrKind Kind)
Adds the attribute to the function.
void getOperandBundlesAsDefs(SmallVectorImpl< OperandBundleDef > &Defs) const
Return the list of operand bundles attached to this instruction as a vector of OperandBundleDefs.
bool isNoBuiltin() const
Return true if the call should not be treated as a call to a builtin.
void removeParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Removes the attribute from the given argument.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool doesNotAccessMemory(unsigned OpNo) const
void removeRetAttrs(const AttributeMask &AttrsToRemove)
Removes the attributes from the return value.
bool hasFnAttr(Attribute::AttrKind Kind) const
Determine whether this call has the given attribute.
bool isStrictFP() const
Determine if the call requires strict floating point semantics.
uint64_t getParamDereferenceableBytes(unsigned i) const
Extract the number of dereferenceable bytes for a call or parameter (0=unknown).
bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
MaybeAlign getParamAlign(unsigned ArgNo) const
Extract the alignment for a call or parameter (0=unknown).
void setAttributes(AttributeList A)
Set the parameter attributes for this call.
bool doesNotThrow() const
Determine if the call cannot unwind.
Value * getArgOperand(unsigned i) const
uint64_t getParamDereferenceableOrNullBytes(unsigned i) const
Extract the number of dereferenceable_or_null bytes for a parameter (0=unknown).
Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
iterator_range< User::op_iterator > args()
Iteration adapter for range-for loops.
unsigned arg_size() const
AttributeList getAttributes() const
Return the parameter attributes for this call.
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
Adds the attribute to the indicated argument.
Function * getCaller()
Helper to get the caller (the parent function).
This class represents a function call, abstracting a target machine's calling convention.