LLVM: lib/Transforms/Utils/SimplifyLibCalls.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

42

43#include

44

45using namespace llvm;

47

51 cl::desc("Enable unsafe double to float "

52 "shrinking for math lib calls"));

53

54

55

56

59 cl::desc("Enable hot/cold operator new library calls"));

63 "Enable optimization of existing hot/cold operator new library calls"));

66 cl::desc("Enable transformation of nobuiltin operator new library calls"));

67

68namespace {

69

70

71

72

73struct HotColdHintParser : public cl::parser {

75

76 bool parse(cl::Option &O, StringRef ArgName, StringRef Arg, unsigned &Value) {

78 return O.error("'" + Arg + "' value invalid for uint argument!");

79

81 return O.error("'" + Arg + "' value must be in the range [0, 255]!");

82

83 return false;

84 }

85};

86

87}

88

89

90

91

92

95 cl::desc("Value to pass to hot/cold operator new for cold allocation"));

98 cl::desc("Value to pass to hot/cold operator new for "

99 "notcold (warm) allocation"));

102 cl::desc("Value to pass to hot/cold operator new for hot allocation"));

106 "Value to pass to hot/cold operator new for ambiguous allocation"));

107

108

109

110

111

113 return Func == LibFunc_abs || Func == LibFunc_labs ||

114 Func == LibFunc_llabs || Func == LibFunc_strlen;

115}

116

117

121 if (IC->isEquality() && IC->getOperand(1) == With)

122 continue;

123

124 return false;

125 }

126 return true;

127}

128

131 return OI->getType()->isFloatingPointTy();

132 });

133}

134

137 return OI->getType()->isFP128Ty();

138 });

139}

140

141

142

143

144

145

146

147

151 if (Base != 0)

152

153 return nullptr;

154

155

157

160 Str = Str.substr(Offset);

161 break;

162 }

163

164 if (Str.empty())

165

166

167 return nullptr;

168

169

170 bool Negate = Str[0] == '-';

171 if (Str[0] == '-' || Str[0] == '+') {

172 Str = Str.drop_front();

173 if (Str.empty())

174

175 return nullptr;

177 }

178

179

180

183 uint64_t Max = AsSigned && Negate ? 1 : 0;

185

186

187 if (Str.size() > 1) {

188 if (Str[0] == '0') {

189 if (toUpper((unsigned char)Str[1]) == 'X') {

190 if (Str.size() == 2 || (Base && Base != 16))

191

192

193 return nullptr;

194

195 Str = Str.drop_front(2);

198 }

199 else if (Base == 0)

201 } else if (Base == 0)

203 }

204 else if (Base == 0)

206

207

208

209

211 for (unsigned i = 0; i != Str.size(); ++i) {

212 unsigned char DigVal = Str[i];

214 DigVal = DigVal - '0';

215 else {

216 DigVal = toUpper(DigVal);

218 DigVal = DigVal - 'A' + 10;

219 else

220 return nullptr;

221 }

222

223 if (DigVal >= Base)

224

225 return nullptr;

226

227

228

229 bool VFlow;

231 if (VFlow || Result > Max)

232 return nullptr;

233 }

234

235 if (EndPtr) {

236

237 Value *Off = B.getInt64(Offset + Str.size());

239 Value *StrEnd = B.CreateInBoundsGEP(B.getInt8Ty(), StrBeg, Off, "endptr");

240 B.CreateStore(StrEnd, EndPtr);

241 }

242

243 if (Negate)

244

245 Result = -Result;

246

247 return ConstantInt::get(RetTy, Result);

248}

249

254 if (C->isNullValue())

255 continue;

256

257 return false;

258 }

259 return true;

260}

261

265 return false;

266

268 return false;

269

271 return false;

272

273 return true;

274}

275

278 uint64_t DereferenceableBytes) {

280 if (F)

281 return;

282 for (unsigned ArgNo : ArgNos) {

283 uint64_t DerefBytes = DereferenceableBytes;

288 DereferenceableBytes);

289

294 CI->removeParamAttr(ArgNo, Attribute::DereferenceableOrNull);

297 }

298 }

299}

300

304 if (F)

305 return;

306

307 for (unsigned ArgNo : ArgNos) {

308 if (!CI->paramHasAttr(ArgNo, Attribute::NoUndef))

310

311 if (!CI->paramHasAttr(ArgNo, Attribute::NonNull)) {

312 unsigned AS =

315 continue;

317 }

318

320 }

321}

322

333 DerefMin = std::min(X, Y);

335 }

336 }

337}

338

339

340

341

342

343

351

354 NewCI->getContext(), {NewCI->getAttributes(), Old.getAttributes()}));

355 NewCI->removeRetAttrs(AttributeFuncs::typeIncompatible(

357 for (unsigned I = 0; I < NewCI->arg_size(); ++I)

361

363}

364

365

367 return Len >= Str.size() ? Str : Str.substr(0, Len);

368}

369

370

371

372

373

375

379

380

382 if (Len)

384 else

385 return nullptr;

386 --Len;

387

388

389 if (Len == 0)

390 return Dst;

391

392 return copyFlags(*CI, emitStrLenMemCpy(Src, Dst, Len, B));

393}

394

395Value *LibCallSimplifier::emitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len,

397

398

400 if (!DstLen)

401 return nullptr;

402

403

404

405

406 Value *CpyDst = B.CreateInBoundsGEP(B.getInt8Ty(), Dst, DstLen, "endptr");

407

408

409

410 B.CreateMemCpy(CpyDst, Align(1), Src, Align(1),

411 TLI->getAsSizeT(Len + 1, *B.GetInsertBlock()->getModule()));

412 return Dst;

413}

414

416

420 uint64_t Len;

424

425

427 if (LengthArg) {

429

430 if (!Len)

431 return Dst;

432 } else {

433 return nullptr;

434 }

435

436

438 if (SrcLen) {

440 --SrcLen;

441 } else {

442 return nullptr;

443 }

444

445

446 if (SrcLen == 0)

447 return Dst;

448

449

450 if (Len < SrcLen)

451 return nullptr;

452

453

454

455 return copyFlags(*CI, emitStrLenMemCpy(Src, Dst, SrcLen, B));

456}

457

458

459

460

463{

466

467

468 Type *CharTy = B.getInt8Ty();

469 Value *Char0 = B.CreateLoad(CharTy, Src);

470 CharVal = B.CreateTrunc(CharVal, CharTy);

471 Value *Cmp = B.CreateICmpEQ(Char0, CharVal, "char0cmp");

472

473 if (NBytes) {

474 Value *Zero = ConstantInt::get(NBytes->getType(), 0);

475 Value *And = B.CreateICmpNE(NBytes, Zero);

476 Cmp = B.CreateLogicalAnd(And, Cmp);

477 }

478

480 return B.CreateSelect(Cmp, Src, NullPtr);

481}

482

487

490

491

492

494 if (!CharC) {

496 if (Len)

498 else

499 return nullptr;

500

502 FunctionType *FT = Callee->getFunctionType();

503 unsigned IntBits = TLI->getIntSize();

504 if (!FT->getParamType(1)->isIntegerTy(IntBits))

505 return nullptr;

506

507 unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());

510 emitMemChr(SrcStr, CharVal,

511 ConstantInt::get(SizeTTy, Len), B,

512 DL, TLI));

513 }

514

515 if (CharC->isZero()) {

518

519

520 return B.CreateIntToPtr(B.getTrue(), CI->getType());

521 }

522

523

524

525 StringRef Str;

527 if (CharC->isZero())

529 return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, StrLen, "strchr");

530 return nullptr;

531 }

532

533

534

536 ? Str.size()

538 if (I == StringRef::npos)

540

541

542 return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(I), "strchr");

543}

544

550

551 StringRef Str;

553

554 if (CharC && CharC->isZero())

556 return nullptr;

557 }

558

559 unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());

561

562

563

564 uint64_t NBytes = Str.size() + 1;

565 Value *Size = ConstantInt::get(SizeTTy, NBytes);

567}

568

571 if (Str1P == Str2P)

572 return ConstantInt::get(CI->getType(), 0);

573

574 StringRef Str1, Str2;

577

578

579 if (HasStr1 && HasStr2)

581 std::clamp(Str1.compare(Str2), -1, 1));

582

583 if (HasStr1 && Str1.empty())

584 return B.CreateNeg(B.CreateZExt(

585 B.CreateLoad(B.getInt8Ty(), Str2P, "strcmpload"), CI->getType()));

586

587 if (HasStr2 && Str2.empty())

588 return B.CreateZExt(B.CreateLoad(B.getInt8Ty(), Str1P, "strcmpload"),

590

591

593 if (Len1)

596 if (Len2)

598

599 if (Len1 && Len2) {

602 TLI->getAsSizeT(std::min(Len1, Len2), *CI->getModule()),

603 B, DL, TLI));

604 }

605

606

607 if (!HasStr1 && HasStr2) {

610 TLI->getAsSizeT(Len2, *CI->getModule()),

611 B, DL, TLI));

612 } else if (HasStr1 && !HasStr2) {

615 TLI->getAsSizeT(Len1, *CI->getModule()),

616 B, DL, TLI));

617 }

618

620 return nullptr;

621}

622

623

624

628

633 if (Str1P == Str2P)

634 return ConstantInt::get(CI->getType(), 0);

635

638

642 else

644

645 if (Length == 0)

646 return ConstantInt::get(CI->getType(), 0);

647

648 if (Length == 1)

650

651 StringRef Str1, Str2;

654

655

656 if (HasStr1 && HasStr2) {

657

661 std::clamp(SubStr1.compare(SubStr2), -1, 1));

662 }

663

664 if (HasStr1 && Str1.empty())

665 return B.CreateNeg(B.CreateZExt(

666 B.CreateLoad(B.getInt8Ty(), Str2P, "strcmpload"), CI->getType()));

667

668 if (HasStr2 && Str2.empty())

669 return B.CreateZExt(B.CreateLoad(B.getInt8Ty(), Str1P, "strcmpload"),

671

673 if (Len1)

676 if (Len2)

678

679

680 if (!HasStr1 && HasStr2) {

681 Len2 = std::min(Len2, Length);

684 TLI->getAsSizeT(Len2, *CI->getModule()),

685 B, DL, TLI));

686 } else if (HasStr1 && !HasStr2) {

687 Len1 = std::min(Len1, Length);

690 TLI->getAsSizeT(Len1, *CI->getModule()),

691 B, DL, TLI));

692 }

693

694 return nullptr;

695}

696

701 if (SrcLen && Size) {

703 if (SrcLen <= Size->getZExtValue() + 1)

705 }

706

707 return nullptr;

708}

709

712 if (Dst == Src)

713 return Src;

714

716

718 if (Len)

720 else

721 return nullptr;

722

723

724

725 CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1),

726 TLI->getAsSizeT(Len, *CI->getModule()));

728 return Dst;

729}

730

733

734

737

738 if (Dst == Src) {

740 return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr;

741 }

742

743

745 if (Len)

747 else

748 return nullptr;

749

750 Value *LenV = TLI->getAsSizeT(Len, *CI->getModule());

751 Value *DstEnd = B.CreateInBoundsGEP(

752 B.getInt8Ty(), Dst, TLI->getAsSizeT(Len - 1, *CI->getModule()));

753

754

755

756 CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1), LenV);

758 return DstEnd;

759}

760

761

762

766

767

769

770

772

773 uint64_t NBytes;

775 NBytes = SizeC->getZExtValue();

776 else

777 return nullptr;

778

781 if (NBytes <= 1) {

782 if (NBytes == 1)

783

784 B.CreateStore(B.getInt8(0), Dst);

785

786

788 }

789

790

791

792

793 StringRef Str;

795 return nullptr;

796

797 uint64_t SrcLen = Str.find('\0');

798

799

800 bool NulTerm = SrcLen < NBytes;

801

802 if (NulTerm)

803

804

805 NBytes = SrcLen + 1;

806 else {

807

808

809 SrcLen = std::min(SrcLen, uint64_t(Str.size()));

810 NBytes = std::min(NBytes - 1, SrcLen);

811 }

812

813 if (SrcLen == 0) {

814

815 B.CreateStore(B.getInt8(0), Dst);

816 return ConstantInt::get(CI->getType(), 0);

817 }

818

819

820

821

822 CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1),

823 TLI->getAsSizeT(NBytes, *CI->getModule()));

825

826 if (!NulTerm) {

827 Value *EndOff = ConstantInt::get(CI->getType(), NBytes);

828 Value *EndPtr = B.CreateInBoundsGEP(B.getInt8Ty(), Dst, EndOff);

829 B.CreateStore(B.getInt8(0), EndPtr);

830 }

831

832

833

834

835 return ConstantInt::get(CI->getType(), SrcLen);

836}

837

838

839

840Value *LibCallSimplifier::optimizeStringNCpy(CallInst *CI, bool RetEnd,

845

847

848

851 }

852

853

854

857 N = SizeC->getZExtValue();

858

859 if (N == 0)

860

861 return Dst;

862

863 if (N == 1) {

864 Type *CharTy = B.getInt8Ty();

865 Value *CharVal = B.CreateLoad(CharTy, Src, "stxncpy.char0");

866 B.CreateStore(CharVal, Dst);

867 if (!RetEnd)

868

869 return Dst;

870

871

872 Value *ZeroChar = ConstantInt::get(CharTy, 0);

873 Value *Cmp = B.CreateICmpEQ(CharVal, ZeroChar, "stpncpy.char0cmp");

874

875 Value *Off1 = B.getInt32(1);

876 Value *EndPtr = B.CreateInBoundsGEP(CharTy, Dst, Off1, "stpncpy.end");

877 return B.CreateSelect(Cmp, Dst, EndPtr, "stpncpy.sel");

878 }

879

880

882 if (SrcLen)

884 else

885 return nullptr;

886

887 --SrcLen;

888

889 if (SrcLen == 0) {

890

891 Align MemSetAlign =

892 CI->getAttributes().getParamAttrs(0).getAlignment().valueOrOne();

893 CallInst *NewCI = B.CreateMemSet(Dst, B.getInt8('\0'), Size, MemSetAlign);

898 return Dst;

899 }

900

901 if (N > SrcLen + 1) {

902 if (N > 128)

903

904 return nullptr;

905

906

907 StringRef Str;

909 return nullptr;

910 std::string SrcStr = Str.str();

911

912

913 SrcStr.resize(N, '\0');

914 Src = B.CreateGlobalString(SrcStr, "str", 0,

915 nullptr, false);

916 }

917

918

919

920 CallInst *NewCI = B.CreateMemCpy(Dst, Align(1), Src, Align(1),

921 TLI->getAsSizeT(N, *CI->getModule()));

923 if (!RetEnd)

924 return Dst;

925

926

927

928 Value *Off = B.getInt64(std::min(SrcLen, N));

929 return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, Off, "endptr");

930}

931

933 unsigned CharSize,

937

940

941

942

943

944

945

946 return B.CreateZExt(B.CreateLoad(CharTy, Src, "char0"),

948 }

949

950 if (Bound) {

952 if (BoundCst->isZero())

953

954 return ConstantInt::get(CI->getType(), 0);

955

956 if (BoundCst->isOne()) {

957

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());

962 }

963 }

964 }

965

967 Value *LenC = ConstantInt::get(CI->getType(), Len - 1);

968

969

970 if (Bound)

971 return B.CreateBinaryIntrinsic(Intrinsic::umin, LenC, Bound);

972 return LenC;

973 }

974

975 if (Bound)

976

977 return nullptr;

978

979

980

981

982

983

984

985

986

988 unsigned BW = DL.getIndexTypeSizeInBits(GEP->getType());

989 SmallMapVector<Value *, APInt, 4> VarOffsets;

990 APInt ConstOffset(BW, 0);

991 assert(CharSize % 8 == 0 && "Expected a multiple of 8 sized CharSize");

992

993 if (GEP->collectOffset(DL, BW, VarOffsets, ConstOffset) ||

994 VarOffsets.size() != 1 || ConstOffset != 0 ||

995 VarOffsets.begin()->second != CharSize / 8)

996 return nullptr;

997

998 ConstantDataArraySlice Slice;

1000 uint64_t NullTermIdx;

1001 if (Slice.Array == nullptr) {

1002 NullTermIdx = 0;

1003 } else {

1004 NullTermIdx = ~((uint64_t)0);

1005 for (uint64_t I = 0, E = Slice.Length; I < E; ++I) {

1007 NullTermIdx = I;

1008 break;

1009 }

1010 }

1011

1012

1013 if (NullTermIdx == ~((uint64_t)0))

1014 return nullptr;

1015 }

1016

1019

1020

1021

1022

1023

1026 NullTermIdx == Slice.Length - 1)) {

1028 return B.CreateSub(ConstantInt::get(CI->getType(), NullTermIdx),

1030 }

1031 }

1032 }

1033

1034

1036 uint64_t LenTrue = GetStringLength(SI->getTrueValue(), CharSize);

1037 uint64_t LenFalse = GetStringLength(SI->getFalseValue(), CharSize);

1038 if (LenTrue && LenFalse) {

1039 ORE.emit([&]() {

1040 return OptimizationRemark("instcombine", "simplify-libcalls", CI)

1041 << "folded strlen(select) to select of constants";

1042 });

1043 return B.CreateSelect(SI->getCondition(),

1044 ConstantInt::get(CI->getType(), LenTrue - 1),

1045 ConstantInt::get(CI->getType(), LenFalse - 1));

1046 }

1047 }

1048

1049 return nullptr;

1050}

1051

1053 if (Value *V = optimizeStringLength(CI, B, 8))

1054 return V;

1056 return nullptr;

1057}

1058

1061 if (Value *V = optimizeStringLength(CI, B, 8, Bound))

1062 return V;

1063

1066 return nullptr;

1067}

1068

1071 unsigned WCharSize = TLI->getWCharSize(M) * 8;

1072

1073 if (WCharSize == 0)

1074 return nullptr;

1075

1076 return optimizeStringLength(CI, B, WCharSize);

1077}

1078

1080 StringRef S1, S2;

1083

1084

1085

1086 if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))

1088

1089

1090 if (HasS1 && HasS2) {

1091 size_t I = S1.find_first_of(S2);

1094

1095 return B.CreateInBoundsGEP(B.getInt8Ty(), CI->getArgOperand(0),

1096 B.getInt64(I), "strpbrk");

1097 }

1098

1099

1100 if (HasS2 && S2.size() == 1)

1102

1103 return nullptr;

1104}

1105

1109

1110

1113 }

1114

1115 return nullptr;

1116}

1117

1119 StringRef S1, S2;

1122

1123

1124

1125 if ((HasS1 && S1.empty()) || (HasS2 && S2.empty()))

1127

1128

1129 if (HasS1 && HasS2) {

1130 size_t Pos = S1.find_first_not_of(S2);

1132 Pos = S1.size();

1133 return ConstantInt::get(CI->getType(), Pos);

1134 }

1135

1136 return nullptr;

1137}

1138

1140 StringRef S1, S2;

1143

1144

1145 if (HasS1 && S1.empty())

1147

1148

1149 if (HasS1 && HasS2) {

1150 size_t Pos = S1.find_first_of(S2);

1152 Pos = S1.size();

1153 return ConstantInt::get(CI->getType(), Pos);

1154 }

1155

1156

1157 if (HasS2 && S2.empty())

1159

1160 return nullptr;

1161}

1162

1164

1167

1168

1171 if (!StrLen)

1172 return nullptr;

1174 StrLen, B, DL, TLI);

1175 if (!StrNCmp)

1176 return nullptr;

1182 replaceAllUsesWith(Old, Cmp);

1183 }

1184 return CI;

1185 }

1186

1187

1188 StringRef SearchStr, ToFindStr;

1191

1192

1193 if (HasStr2 && ToFindStr.empty())

1195

1196

1197 if (HasStr1 && HasStr2) {

1198 size_t Offset = SearchStr.find(ToFindStr);

1199

1202

1203

1204 return B.CreateConstInBoundsGEP1_64(B.getInt8Ty(), CI->getArgOperand(0),

1206 }

1207

1208

1209 if (HasStr2 && ToFindStr.size() == 1) {

1211 }

1212

1214 return nullptr;

1215}

1216

1224

1225 if (LenC) {

1227

1228 return NullPtr;

1229

1230 if (LenC->isOne()) {

1231

1232

1233 Value *Val = B.CreateLoad(B.getInt8Ty(), SrcStr, "memrchr.char0");

1234

1235 CharVal = B.CreateTrunc(CharVal, B.getInt8Ty());

1236 Value *Cmp = B.CreateICmpEQ(Val, CharVal, "memrchr.char0cmp");

1237 return B.CreateSelect(Cmp, SrcStr, NullPtr, "memrchr.sel");

1238 }

1239 }

1240

1241 StringRef Str;

1243 return nullptr;

1244

1245 if (Str.size() == 0)

1246

1247

1248

1249 return NullPtr;

1250

1252 if (LenC) {

1254 if (Str.size() < EndOff)

1255

1256 return nullptr;

1257 }

1258

1260

1261 size_t Pos = Str.rfind(CharC->getZExtValue(), EndOff);

1263

1264

1265 return NullPtr;

1266

1267 if (LenC)

1268

1269 return B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(Pos));

1270

1271 if (Str.find(Str[Pos]) == Pos) {

1272

1273

1274

1275

1276 Value *Cmp = B.CreateICmpULE(Size, ConstantInt::get(Size->getType(), Pos),

1277 "memrchr.cmp");

1278 Value *SrcPlus = B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr,

1279 B.getInt64(Pos), "memrchr.ptr_plus");

1280 return B.CreateSelect(Cmp, NullPtr, SrcPlus, "memrchr.sel");

1281 }

1282 }

1283

1284

1285 Str = Str.substr(0, EndOff);

1287 return nullptr;

1288

1289

1290

1291

1292 Type *SizeTy = Size->getType();

1293 Type *Int8Ty = B.getInt8Ty();

1294 Value *NNeZ = B.CreateICmpNE(Size, ConstantInt::get(SizeTy, 0));

1295

1296 CharVal = B.CreateTrunc(CharVal, Int8Ty);

1297 Value *CEqS0 = B.CreateICmpEQ(ConstantInt::get(Int8Ty, Str[0]), CharVal);

1298 Value *And = B.CreateLogicalAnd(NNeZ, CEqS0);

1299 Value *SizeM1 = B.CreateSub(Size, ConstantInt::get(SizeTy, 1));

1300 Value *SrcPlus =

1301 B.CreateInBoundsGEP(Int8Ty, SrcStr, SizeM1, "memrchr.ptr_plus");

1302 return B.CreateSelect(And, SrcPlus, NullPtr, "memrchr.sel");

1303}

1304

1308

1313 }

1314

1319

1320

1321 if (LenC) {

1323 return NullPtr;

1324

1325 if (LenC->isOne()) {

1326

1327

1328 Value *Val = B.CreateLoad(B.getInt8Ty(), SrcStr, "memchr.char0");

1329

1330 CharVal = B.CreateTrunc(CharVal, B.getInt8Ty());

1331 Value *Cmp = B.CreateICmpEQ(Val, CharVal, "memchr.char0cmp");

1332 return B.CreateSelect(Cmp, SrcStr, NullPtr, "memchr.sel");

1333 }

1334 }

1335

1336 StringRef Str;

1338 return nullptr;

1339

1340 if (CharC) {

1341 size_t Pos = Str.find(CharC->getZExtValue());

1343

1344

1345 return NullPtr;

1346

1347

1348

1349

1350 Value *Cmp = B.CreateICmpULE(Size, ConstantInt::get(Size->getType(), Pos),

1351 "memchr.cmp");

1352 Value *SrcPlus = B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, B.getInt64(Pos),

1353 "memchr.ptr");

1354 return B.CreateSelect(Cmp, NullPtr, SrcPlus);

1355 }

1356

1357 if (Str.size() == 0)

1358

1359

1360

1361 return NullPtr;

1362

1363 if (LenC)

1365

1366 size_t Pos = Str.find_first_not_of(Str[0]);

1368 || Str.find_first_not_of(Str[Pos], Pos) == StringRef::npos) {

1369

1370

1371

1372

1373

1374

1375

1376

1377

1378 Type *SizeTy = Size->getType();

1380

1381

1382 CharVal = B.CreateTrunc(CharVal, Int8Ty);

1383

1384 Value *Sel1 = NullPtr;

1386

1387 Value *PosVal = ConstantInt::get(SizeTy, Pos);

1388 Value *StrPos = ConstantInt::get(Int8Ty, Str[Pos]);

1389 Value *CEqSPos = B.CreateICmpEQ(CharVal, StrPos);

1391 Value *And = B.CreateAnd(CEqSPos, NGtPos);

1392 Value *SrcPlus = B.CreateInBoundsGEP(B.getInt8Ty(), SrcStr, PosVal);

1393 Sel1 = B.CreateSelect(And, SrcPlus, NullPtr, "memchr.sel1");

1394 }

1395

1396 Value *Str0 = ConstantInt::get(Int8Ty, Str[0]);

1397 Value *CEqS0 = B.CreateICmpEQ(Str0, CharVal);

1398 Value *NNeZ = B.CreateICmpNE(Size, ConstantInt::get(SizeTy, 0));

1399 Value *And = B.CreateAnd(NNeZ, CEqS0);

1400 return B.CreateSelect(And, SrcStr, Sel1, "memchr.sel2");

1401 }

1402

1403 if (!LenC) {

1405

1406

1407

1409

1410

1411 return nullptr;

1412 }

1413

1416

1417

1418

1419

1420

1421

1422

1423

1424

1425

1426

1428 return nullptr;

1429

1430 unsigned char Max =

1431 *std::max_element(reinterpret_cast<const unsigned char *>(Str.begin()),

1432 reinterpret_cast<const unsigned char *>(Str.end()));

1433

1434

1435

1436

1437

1438

1439 if (!DL.fitsInLegalInteger(Max + 1)) {

1440

1441

1442

1443

1444

1445 std::string SortedStr = Str.str();

1447

1448 unsigned NonContRanges = 1;

1449 for (size_t i = 1; i < SortedStr.size(); ++i) {

1450 if (SortedStr[i] > SortedStr[i - 1] + 1) {

1451 NonContRanges++;

1452 }

1453 }

1454

1455

1456

1457 if (NonContRanges > 2)

1458 return nullptr;

1459

1460

1461 CharVal = B.CreateTrunc(CharVal, B.getInt8Ty());

1462

1464 for (unsigned char C : SortedStr)

1465 CharCompares.push_back(B.CreateICmpEQ(CharVal, B.getInt8(C)));

1466

1467 return B.CreateIntToPtr(B.CreateOr(CharCompares), CI->getType());

1468 }

1469

1470

1471

1472 unsigned char Width = NextPowerOf2(std::max((unsigned char)7, Max));

1473

1474

1476 for (char C : Str)

1477 Bitfield.setBit((unsigned char)C);

1478 Value *BitfieldC = B.getInt(Bitfield);

1479

1480

1481 Value *C = B.CreateZExtOrTrunc(CharVal, BitfieldC->getType());

1482 C = B.CreateAnd(C, B.getIntN(Width, 0xFF));

1483

1484

1486 "memchr.bounds");

1487

1488

1489 Value *Shl = B.CreateShl(B.getIntN(Width, 1ULL), C);

1490 Value *Bits = B.CreateIsNotNull(B.CreateAnd(Shl, BitfieldC), "memchr.bits");

1491

1492

1493

1494 return B.CreateIntToPtr(B.CreateLogicalAnd(Bounds, Bits, "memchr"),

1496}

1497

1498

1499

1503 if (LHS == RHS)

1505

1509 return nullptr;

1510

1511

1512

1513

1514

1515

1517 Value *Zero = ConstantInt::get(CI->getType(), 0);

1518 for (uint64_t MinSize = std::min(LStr.size(), RStr.size()); ; ++Pos) {

1519 if (Pos == MinSize ||

1520 (StrNCmp && (LStr[Pos] == '\0' && RStr[Pos] == '\0'))) {

1521

1522

1523

1524

1525 return Zero;

1526 }

1527

1528 if (LStr[Pos] != RStr[Pos])

1529 break;

1530 }

1531

1532

1533 typedef unsigned char UChar;

1534 int IRes = UChar(LStr[Pos]) < UChar(RStr[Pos]) ? -1 : 1;

1535 Value *MaxSize = ConstantInt::get(Size->getType(), Pos);

1538 return B.CreateSelect(Cmp, Zero, Res);

1539}

1540

1541

1545 if (Len == 0)

1547

1548

1549 if (Len == 1) {

1550 Value *LHSV = B.CreateZExt(B.CreateLoad(B.getInt8Ty(), LHS, "lhsc"),

1552 Value *RHSV = B.CreateZExt(B.CreateLoad(B.getInt8Ty(), RHS, "rhsc"),

1554 return B.CreateSub(LHSV, RHSV, "chardiff");

1555 }

1556

1557

1558

1559

1562 Align PrefAlignment = DL.getPrefTypeAlign(IntType);

1563

1564

1565 Value *LHSV = nullptr;

1568

1569 Value *RHSV = nullptr;

1572

1573

1574

1577 if (!LHSV)

1578 LHSV = B.CreateLoad(IntType, LHS, "lhsv");

1579 if (!RHSV)

1580 RHSV = B.CreateLoad(IntType, RHS, "rhsv");

1581 return B.CreateZExt(B.CreateICmpNE(LHSV, RHSV), CI->getType(), "memcmp");

1582 }

1583 }

1584

1585 return nullptr;

1586}

1587

1588

1589Value *LibCallSimplifier::optimizeMemCmpBCmpCommon(CallInst *CI,

1593

1595

1597 return Res;

1598

1599

1601 if (!LenC)

1602 return nullptr;

1603

1605}

1606

1609 if (Value *V = optimizeMemCmpBCmpCommon(CI, B))

1610 return V;

1611

1612

1613

1614

1621 }

1622

1623 return nullptr;

1624}

1625

1627 return optimizeMemCmpBCmpCommon(CI, B);

1628}

1629

1634 return nullptr;

1635

1636

1641}

1642

1648 StringRef SrcStr;

1649 if (CI->use_empty() && Dst == Src)

1650 return Dst;

1651

1652 if (N) {

1653 if (N->isNullValue())

1656

1657 !StopChar)

1658 return nullptr;

1659 } else {

1660 return nullptr;

1661 }

1662

1663

1666 if (N->getZExtValue() <= SrcStr.size()) {

1670 }

1671 return nullptr;

1672 }

1673

1675 ConstantInt::get(N->getType(), std::min(uint64_t(Pos + 1), N->getZExtValue()));

1676

1678 return Pos + 1 <= N->getZExtValue()

1679 ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, NewN)

1681}

1682

1686

1687 CallInst *NewCI =

1689

1690

1691

1693 return B.CreateInBoundsGEP(B.getInt8Ty(), Dst, N);

1694}

1695

1700 return nullptr;

1701

1702

1707}

1708

1713 return nullptr;

1714

1715

1720}

1721

1725

1726 return nullptr;

1727}

1728

1729

1730

1731Value *LibCallSimplifier::maybeOptimizeNoBuiltinOperatorNew(CallInst *CI,

1734 return nullptr;

1736 if (!Callee)

1737 return nullptr;

1738 LibFunc Func;

1739 if (!TLI->getLibFunc(*Callee, Func))

1740 return nullptr;

1741 switch (Func) {

1742 case LibFunc_Znwm:

1743 case LibFunc_ZnwmRKSt9nothrow_t:

1744 case LibFunc_ZnwmSt11align_val_t:

1745 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:

1746 case LibFunc_Znam:

1747 case LibFunc_ZnamRKSt9nothrow_t:

1748 case LibFunc_ZnamSt11align_val_t:

1749 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:

1750 case LibFunc_size_returning_new:

1751 case LibFunc_size_returning_new_aligned:

1752

1753

1754

1756 return nullptr;

1757 break;

1758 case LibFunc_Znwm12__hot_cold_t:

1759 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:

1760 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:

1761 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

1762 case LibFunc_Znam12__hot_cold_t:

1763 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:

1764 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:

1765 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

1766 case LibFunc_size_returning_new_hot_cold:

1767 case LibFunc_size_returning_new_aligned_hot_cold:

1768

1769

1771 return nullptr;

1772 break;

1773 default:

1774 return nullptr;

1775 }

1776 return optimizeNew(CI, B, Func);

1777}

1778

1779

1780

1781

1782

1784 LibFunc &Func) {

1786 return nullptr;

1787

1788 uint8_t HotCold;

1789 if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "cold")

1791 else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() ==

1792 "notcold")

1794 else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() == "hot")

1796 else if (CI->getAttributes().getFnAttr("memprof").getValueAsString() ==

1797 "ambiguous")

1799 else

1800 return nullptr;

1801

1802

1803

1804

1805

1806

1807

1808

1809 Value *NewCall = nullptr;

1810 switch (Func) {

1811 case LibFunc_Znwm12__hot_cold_t:

1814 LibFunc_Znwm12__hot_cold_t, HotCold);

1815 break;

1816 case LibFunc_Znwm:

1818 LibFunc_Znwm12__hot_cold_t, HotCold);

1819 break;

1820 case LibFunc_Znam12__hot_cold_t:

1823 LibFunc_Znam12__hot_cold_t, HotCold);

1824 break;

1825 case LibFunc_Znam:

1827 LibFunc_Znam12__hot_cold_t, HotCold);

1828 break;

1829 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:

1833 LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);

1834 break;

1835 case LibFunc_ZnwmRKSt9nothrow_t:

1838 LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);

1839 break;

1840 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:

1844 LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);

1845 break;

1846 case LibFunc_ZnamRKSt9nothrow_t:

1849 LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);

1850 break;

1851 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:

1855 LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);

1856 break;

1857 case LibFunc_ZnwmSt11align_val_t:

1860 LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);

1861 break;

1862 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:

1866 LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);

1867 break;

1868 case LibFunc_ZnamSt11align_val_t:

1871 LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);

1872 break;

1873 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

1877 TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,

1878 HotCold);

1879 break;

1880 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:

1883 TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold);

1884 break;

1885 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

1889 TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,

1890 HotCold);

1891 break;

1892 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:

1895 TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t, HotCold);

1896 break;

1897 case LibFunc_size_returning_new:

1899 LibFunc_size_returning_new_hot_cold,

1900 HotCold);

1901 break;

1902 case LibFunc_size_returning_new_hot_cold:

1905 LibFunc_size_returning_new_hot_cold,

1906 HotCold);

1907 break;

1908 case LibFunc_size_returning_new_aligned:

1911 LibFunc_size_returning_new_aligned_hot_cold, HotCold);

1912 break;

1913 case LibFunc_size_returning_new_aligned_hot_cold:

1917 LibFunc_size_returning_new_aligned_hot_cold, HotCold);

1918 break;

1919 default:

1920 return nullptr;

1921 }

1922

1925

1926 return NewCall;

1927}

1928

1929

1930

1931

1932

1933

1940

1941

1942

1943

1944

1945

1948 Value *Op = Cast->getOperand(0);

1949 if (Op->getType()->isFloatTy())

1950 return Op;

1951 }

1953 APFloat F = Const->getValueAPF();

1954 bool losesInfo;

1956 &losesInfo);

1957 if (!losesInfo)

1958 return ConstantFP::get(Const->getContext(), F);

1959 }

1960 return nullptr;

1961}

1962

1963

1966 bool isPrecise = false) {

1969 return nullptr;

1970

1971

1972

1973

1974 if (isPrecise)

1978 return nullptr;

1979 }

1980

1981

1985 if (!V[0] || (isBinary && !V[1]))

1986 return nullptr;

1987

1988

1989

1990

1991

1992

1994 bool IsIntrinsic = CalleeFn->isIntrinsic();

1995 if (!IsIntrinsic) {

1997 if (CallerName.ends_with('f') &&

1998 CallerName.size() == (CalleeName.size() + 1) &&

2000 return nullptr;

2001 }

2002

2003

2006

2007

2009 if (IsIntrinsic) {

2011 R = isBinary ? B.CreateIntrinsic(IID, B.getFloatTy(), V)

2012 : B.CreateIntrinsic(IID, B.getFloatTy(), V[0]);

2013 } else {

2014 AttributeList CalleeAttrs = CalleeFn->getAttributes();

2016 CalleeAttrs)

2018 }

2019 return B.CreateFPExt(R, B.getDoubleTy());

2020}

2021

2022

2025 bool isPrecise = false) {

2027}

2028

2029

2032 bool isPrecise = false) {

2034}

2035

2036

2038 Value *Real, *Imag;

2039

2041

2043 return nullptr;

2044

2046 assert(Op->getType()->isArrayTy() && "Unexpected signature for cabs!");

2047

2048 Real = B.CreateExtractValue(Op, 0, "real");

2049 Imag = B.CreateExtractValue(Op, 1, "imag");

2050

2051 } else {

2052 assert(CI->arg_size() == 2 && "Unexpected signature for cabs!");

2053

2056

2057

2058

2059 Value *AbsOp = nullptr;

2061 if (ConstReal->isZero())

2062 AbsOp = Imag;

2063

2065 if (ConstImag->isZero())

2066 AbsOp = Real;

2067 }

2068

2069 if (AbsOp)

2071 *CI, B.CreateUnaryIntrinsic(Intrinsic::fabs, AbsOp, CI, "cabs"));

2072

2074 return nullptr;

2075 }

2076

2077

2078 Value *RealReal = B.CreateFMulFMF(Real, Real, CI);

2079 Value *ImagImag = B.CreateFMulFMF(Imag, Imag, CI);

2081 *CI, B.CreateUnaryIntrinsic(Intrinsic::sqrt,

2082 B.CreateFAddFMF(RealReal, ImagImag, CI), CI,

2083 "cabs"));

2084}

2085

2086

2087

2091

2092

2093 unsigned BitWidth = Op->getType()->getScalarSizeInBits();

2095 Type *IntTy = Op->getType()->getWithNewBitWidth(DstWidth);

2097 : B.CreateZExt(Op, IntTy);

2098 }

2099 }

2100

2101 return nullptr;

2102}

2103

2104

2105

2106

2111 bool Ignored;

2112

2113

2114

2115

2116

2117

2118

2119

2120

2121

2122

2123

2124

2125

2126

2127

2130 LibFunc LibFn;

2131

2133 if (CalleeFn && TLI->getLibFunc(CalleeFn->getName(), LibFn) &&

2135 StringRef ExpName;

2138 LibFunc LibFnFloat, LibFnDouble, LibFnLongDouble;

2139

2140 switch (LibFn) {

2141 default:

2142 return nullptr;

2143 case LibFunc_expf:

2144 case LibFunc_exp:

2145 case LibFunc_expl:

2146 ExpName = TLI->getName(LibFunc_exp);

2147 ID = Intrinsic::exp;

2148 LibFnFloat = LibFunc_expf;

2149 LibFnDouble = LibFunc_exp;

2150 LibFnLongDouble = LibFunc_expl;

2151 break;

2152 case LibFunc_exp2f:

2153 case LibFunc_exp2:

2154 case LibFunc_exp2l:

2155 ExpName = TLI->getName(LibFunc_exp2);

2156 ID = Intrinsic::exp2;

2157 LibFnFloat = LibFunc_exp2f;

2158 LibFnDouble = LibFunc_exp2;

2159 LibFnLongDouble = LibFunc_exp2l;

2160 break;

2161 }

2162

2163

2166 ? B.CreateUnaryIntrinsic(ID, FMul, nullptr, ExpName)

2168 LibFnLongDouble, B,

2170

2171

2172

2173

2174

2175 substituteInParent(BaseFn, ExpFn);

2176 return ExpFn;

2177 }

2178 }

2179

2180

2181

2184 return nullptr;

2185

2186 AttributeList NoAttrs;

2187

2189

2190

2193 (UseIntrinsic ||

2194 hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl))) {

2195

2196

2197

2199 Constant *One = ConstantFP::get(Ty, 1.0);

2200

2201 if (UseIntrinsic) {

2202 return copyFlags(*Pow, B.CreateIntrinsic(Intrinsic::ldexp,

2203 {Ty, ExpoI->getType()},

2204 {One, ExpoI}, Pow, "exp2"));

2205 }

2206

2208 One, ExpoI, TLI, LibFunc_ldexp, LibFunc_ldexpf,

2209 LibFunc_ldexpl, B, NoAttrs));

2210 }

2211 }

2212

2213

2214 if (hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f, LibFunc_exp2l)) {

2217 BaseR = BaseR / *BaseF;

2218 bool IsInteger = BaseF->isInteger(), IsReciprocal = BaseR.isInteger();

2219 const APFloat *NF = IsReciprocal ? &BaseR : BaseF;

2220 APSInt NI(64, false);

2221 if ((IsInteger || IsReciprocal) &&

2224 NI > 1 && NI.isPowerOf2()) {

2225 double N = NI.logBase2() * (IsReciprocal ? -1.0 : 1.0);

2226 Value *FMul = B.CreateFMul(Expo, ConstantFP::get(Ty, N), "mul");

2228 return copyFlags(*Pow, B.CreateUnaryIntrinsic(Intrinsic::exp2, FMul,

2229 nullptr, "exp2"));

2230 else

2232 LibFunc_exp2f,

2233 LibFunc_exp2l, B, NoAttrs));

2234 }

2235 }

2236

2237

2239 hasFloatFn(M, TLI, Ty, LibFunc_exp10, LibFunc_exp10f, LibFunc_exp10l)) {

2240

2242 CallInst *NewExp10 =

2243 B.CreateIntrinsic(Intrinsic::exp10, {Ty}, {Expo}, Pow, "exp10");

2244 return copyFlags(*Pow, NewExp10);

2245 }

2246

2248 LibFunc_exp10f, LibFunc_exp10l,

2249 B, NoAttrs));

2250 }

2251

2252

2255

2256

2258 "pow(1.0, y) should have been simplified earlier!");

2259

2265

2266 if (Log) {

2267 Value *FMul = B.CreateFMul(Log, Expo, "mul");

2269 return copyFlags(*Pow, B.CreateUnaryIntrinsic(Intrinsic::exp2, FMul,

2270 nullptr, "exp2"));

2271 else if (hasFloatFn(M, TLI, Ty, LibFunc_exp2, LibFunc_exp2f,

2272 LibFunc_exp2l))

2274 LibFunc_exp2f,

2275 LibFunc_exp2l, B, NoAttrs));

2276 }

2277 }

2278

2279 return nullptr;

2280}

2281

2285

2286 if (NoErrno)

2287 return B.CreateUnaryIntrinsic(Intrinsic::sqrt, V, nullptr, "sqrt");

2288

2289

2290 if (hasFloatFn(M, TLI, V->getType(), LibFunc_sqrt, LibFunc_sqrtf,

2291 LibFunc_sqrtl))

2292

2293

2294

2296 LibFunc_sqrtl, B, Attrs);

2297

2298 return nullptr;

2299}

2300

2301

2306

2310 return nullptr;

2311

2312

2313

2315 return nullptr;

2316

2317

2318

2319

2320

2323 Base, SimplifyQuery(DL, TLI, DT, AC, Pow, true, true, DC)))

2324 return nullptr;

2325

2327 TLI);

2328 if (!Sqrt)

2329 return nullptr;

2330

2331

2333 Sqrt = B.CreateUnaryIntrinsic(Intrinsic::fabs, Sqrt, nullptr, "abs");

2334

2336

2337

2338

2342 Value *FCmp = B.CreateFCmpOEQ(Base, NegInf, "isinf");

2343 Sqrt = B.CreateSelect(FCmp, PosInf, Sqrt);

2344 }

2345

2346

2348 Sqrt = B.CreateFDiv(ConstantFP::get(Ty, 1.0), Sqrt, "reciprocal");

2349

2350 return Sqrt;

2351}

2352

2357 return B.CreateIntrinsic(Intrinsic::powi, Types, Args);

2358}

2359

2368 bool Ignored;

2369

2370

2371 IRBuilderBase::FastMathFlagGuard Guard(B);

2373

2374

2375

2377 return Base;

2378

2379 if (Value *Exp = replacePowWithExp(Pow, B))

2380 return Exp;

2381

2382

2383

2384

2386 return B.CreateFDiv(ConstantFP::get(Ty, 1.0), Base, "reciprocal");

2387

2388

2390 return ConstantFP::get(Ty, 1.0);

2391

2392

2394 return Base;

2395

2396

2398 return B.CreateFMul(Base, Base, "square");

2399

2400 if (Value *Sqrt = replacePowWithSqrt(Pow, B))

2401 return Sqrt;

2402

2403

2404

2405

2411 Value *Sqrt = nullptr;

2412 if (!ExpoA.isInteger()) {

2414

2415

2416

2418 return nullptr;

2419

2421 return nullptr;

2422

2425 return nullptr;

2426 if (!ExpoI.isInteger())

2427 return nullptr;

2428 ExpoF = &ExpoI;

2429

2431 B, TLI);

2432 if (!Sqrt)

2433 return nullptr;

2434 }

2435

2436

2437

2438 APSInt IntExpo(TLI->getIntSize(), false);

2443 *Pow,

2445 Base, ConstantInt::get(B.getIntNTy(TLI->getIntSize()), IntExpo),

2446 M, B));

2447

2448 if (PowI && Sqrt)

2449 return B.CreateFMul(PowI, Sqrt);

2450

2451 return PowI;

2452 }

2453 }

2454

2455

2459 }

2460

2461

2462

2463 if (UnsafeFPShrink && Name == TLI->getName(LibFunc_pow) &&

2464 hasFloatVersion(M, Name)) {

2466 return Shrunk;

2467 }

2468

2469 return nullptr;

2470}

2471

2476 Value *Ret = nullptr;

2477 if (UnsafeFPShrink && Name == TLI->getName(LibFunc_exp2) &&

2478 hasFloatVersion(M, Name))

2480

2481

2482

2483

2484

2485

2486

2487 const bool UseIntrinsic = Callee->isIntrinsic();

2488

2490 if (!UseIntrinsic && Ty->isVectorTy())

2491 return Ret;

2492

2493

2494

2497 (UseIntrinsic ||

2498 hasFloatFn(M, TLI, Ty, LibFunc_ldexp, LibFunc_ldexpf, LibFunc_ldexpl))) {

2500 Constant *One = ConstantFP::get(Ty, 1.0);

2501

2502 if (UseIntrinsic) {

2503 return copyFlags(*CI, B.CreateIntrinsic(Intrinsic::ldexp,

2504 {Ty, Exp->getType()},

2505 {One, Exp}, CI));

2506 }

2507

2508 IRBuilderBase::FastMathFlagGuard Guard(B);

2511 One, Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf,

2512 LibFunc_ldexpl, B, AttributeList()));

2513 }

2514 }

2515

2516 return Ret;

2517}

2518

2521

2522

2523

2526 if ((Name == "fmin" || Name == "fmax") && hasFloatVersion(M, Name))

2528 return Ret;

2529

2530

2531

2532

2533

2534

2535

2536

2539

2540 Intrinsic::ID IID = Callee->getName().starts_with("fmin") ? Intrinsic::minnum

2541 : Intrinsic::maxnum;

2544}

2545

2546Value *LibCallSimplifier::optimizeFMinimumnumFMaximumnum(CallInst *CI,

2549

2550

2551

2554 if ((Name == "fminimum_num" || Name == "fmaximum_num") &&

2555 hasFloatVersion(M, Name))

2557 return Ret;

2558

2559

2560

2561

2562

2564 ? Intrinsic::minimumnum

2565 : Intrinsic::maximumnum;

2568}

2569

2571 Function *LogFn = Log->getCalledFunction();

2572 StringRef LogNm = LogFn->getName();

2575 Type *Ty = Log->getType();

2576

2577 if (UnsafeFPShrink && hasFloatVersion(Mod, LogNm))

2579 return Ret;

2580

2581 LibFunc LogLb, ExpLb, Exp2Lb, Exp10Lb, PowLb;

2582

2583

2584 if (TLI->getLibFunc(LogNm, LogLb)) {

2585 switch (LogLb) {

2586 case LibFunc_logf:

2587 LogID = Intrinsic::log;

2588 ExpLb = LibFunc_expf;

2589 Exp2Lb = LibFunc_exp2f;

2590 Exp10Lb = LibFunc_exp10f;

2591 PowLb = LibFunc_powf;

2592 break;

2593 case LibFunc_log:

2594 LogID = Intrinsic::log;

2595 ExpLb = LibFunc_exp;

2596 Exp2Lb = LibFunc_exp2;

2597 Exp10Lb = LibFunc_exp10;

2598 PowLb = LibFunc_pow;

2599 break;

2600 case LibFunc_logl:

2601 LogID = Intrinsic::log;

2602 ExpLb = LibFunc_expl;

2603 Exp2Lb = LibFunc_exp2l;

2604 Exp10Lb = LibFunc_exp10l;

2605 PowLb = LibFunc_powl;

2606 break;

2607 case LibFunc_log2f:

2608 LogID = Intrinsic::log2;

2609 ExpLb = LibFunc_expf;

2610 Exp2Lb = LibFunc_exp2f;

2611 Exp10Lb = LibFunc_exp10f;

2612 PowLb = LibFunc_powf;

2613 break;

2614 case LibFunc_log2:

2615 LogID = Intrinsic::log2;

2616 ExpLb = LibFunc_exp;

2617 Exp2Lb = LibFunc_exp2;

2618 Exp10Lb = LibFunc_exp10;

2619 PowLb = LibFunc_pow;

2620 break;

2621 case LibFunc_log2l:

2622 LogID = Intrinsic::log2;

2623 ExpLb = LibFunc_expl;

2624 Exp2Lb = LibFunc_exp2l;

2625 Exp10Lb = LibFunc_exp10l;

2626 PowLb = LibFunc_powl;

2627 break;

2628 case LibFunc_log10f:

2629 LogID = Intrinsic::log10;

2630 ExpLb = LibFunc_expf;

2631 Exp2Lb = LibFunc_exp2f;

2632 Exp10Lb = LibFunc_exp10f;

2633 PowLb = LibFunc_powf;

2634 break;

2635 case LibFunc_log10:

2636 LogID = Intrinsic::log10;

2637 ExpLb = LibFunc_exp;

2638 Exp2Lb = LibFunc_exp2;

2639 Exp10Lb = LibFunc_exp10;

2640 PowLb = LibFunc_pow;

2641 break;

2642 case LibFunc_log10l:

2643 LogID = Intrinsic::log10;

2644 ExpLb = LibFunc_expl;

2645 Exp2Lb = LibFunc_exp2l;

2646 Exp10Lb = LibFunc_exp10l;

2647 PowLb = LibFunc_powl;

2648 break;

2649 default:

2650 return nullptr;

2651 }

2652

2653

2654 bool IsKnownNoErrno = Log->hasNoNaNs() && Log->hasNoInfs();

2655 if (!IsKnownNoErrno) {

2656 SimplifyQuery SQ(DL, TLI, DT, AC, Log, true, true, DC);

2658 Log->getOperand(0),

2660 Function *F = Log->getParent()->getParent();

2662 IsKnownNoErrno =

2665 }

2666 if (IsKnownNoErrno) {

2667 auto *NewLog = B.CreateUnaryIntrinsic(LogID, Log->getArgOperand(0), Log);

2668 NewLog->copyMetadata(*Log);

2670 }

2671 } else if (LogID == Intrinsic::log || LogID == Intrinsic::log2 ||

2672 LogID == Intrinsic::log10) {

2674 ExpLb = LibFunc_expf;

2675 Exp2Lb = LibFunc_exp2f;

2676 Exp10Lb = LibFunc_exp10f;

2677 PowLb = LibFunc_powf;

2679 ExpLb = LibFunc_exp;

2680 Exp2Lb = LibFunc_exp2;

2681 Exp10Lb = LibFunc_exp10;

2682 PowLb = LibFunc_pow;

2683 } else

2684 return nullptr;

2685 } else

2686 return nullptr;

2687

2688

2691 return nullptr;

2692

2693 IRBuilderBase::FastMathFlagGuard Guard(B);

2695

2697 LibFunc ArgLb = NotLibFunc;

2698 TLI->getLibFunc(*Arg, ArgLb);

2699

2700

2701 AttributeList NoAttrs;

2702 if (ArgLb == PowLb || ArgID == Intrinsic::pow || ArgID == Intrinsic::powi) {

2704 Log->doesNotAccessMemory()

2705 ? B.CreateUnaryIntrinsic(LogID, Arg->getOperand(0), nullptr, "log")

2708

2709 if (ArgID == Intrinsic::powi)

2710 Y = B.CreateSIToFP(Y, Ty, "cast");

2711 Value *MulY = B.CreateFMul(Y, LogX, "mul");

2712

2713

2714 substituteInParent(Arg, MulY);

2715 return MulY;

2716 }

2717

2718

2719

2720 if (ArgLb == ExpLb || ArgLb == Exp2Lb || ArgLb == Exp10Lb ||

2721 ArgID == Intrinsic::exp || ArgID == Intrinsic::exp2) {

2723 if (ArgLb == ExpLb || ArgID == Intrinsic::exp)

2724

2725 Eul = ConstantFP::get(Log->getType(), numbers::e);

2726 else if (ArgLb == Exp2Lb || ArgID == Intrinsic::exp2)

2727 Eul = ConstantFP::get(Log->getType(), 2.0);

2728 else

2729 Eul = ConstantFP::get(Log->getType(), 10.0);

2730 Value *LogE = Log->doesNotAccessMemory()

2731 ? B.CreateUnaryIntrinsic(LogID, Eul, nullptr, "log")

2734

2735

2736 substituteInParent(Arg, MulY);

2737 return MulY;

2738 }

2739

2740 return nullptr;

2741}

2742

2743

2746 return nullptr;

2747

2751 return nullptr;

2753 LibFunc ArgLb = NotLibFunc;

2754 TLI->getLibFunc(*Arg, ArgLb);

2755

2756 LibFunc SqrtLb, ExpLb, Exp2Lb, Exp10Lb;

2757

2758 if (TLI->getLibFunc(SqrtFn->getName(), SqrtLb))

2759 switch (SqrtLb) {

2760 case LibFunc_sqrtf:

2761 ExpLb = LibFunc_expf;

2762 Exp2Lb = LibFunc_exp2f;

2763 Exp10Lb = LibFunc_exp10f;

2764 break;

2765 case LibFunc_sqrt:

2766 ExpLb = LibFunc_exp;

2767 Exp2Lb = LibFunc_exp2;

2768 Exp10Lb = LibFunc_exp10;

2769 break;

2770 case LibFunc_sqrtl:

2771 ExpLb = LibFunc_expl;

2772 Exp2Lb = LibFunc_exp2l;

2773 Exp10Lb = LibFunc_exp10l;

2774 break;

2775 default:

2776 return nullptr;

2777 }

2778 else if (SqrtFn->getIntrinsicID() == Intrinsic::sqrt) {

2780 ExpLb = LibFunc_expf;

2781 Exp2Lb = LibFunc_exp2f;

2782 Exp10Lb = LibFunc_exp10f;

2784 ExpLb = LibFunc_exp;

2785 Exp2Lb = LibFunc_exp2;

2786 Exp10Lb = LibFunc_exp10;

2787 } else

2788 return nullptr;

2789 } else

2790 return nullptr;

2791

2792 if (ArgLb != ExpLb && ArgLb != Exp2Lb && ArgLb != Exp10Lb &&

2793 ArgID != Intrinsic::exp && ArgID != Intrinsic::exp2)

2794 return nullptr;

2795

2796 IRBuilderBase::InsertPointGuard Guard(B);

2797 B.SetInsertPoint(Arg);

2798 auto *ExpOperand = Arg->getOperand(0);

2799 auto *FMul =

2800 B.CreateFMulFMF(ExpOperand, ConstantFP::get(ExpOperand->getType(), 0.5),

2801 CI, "merged.sqrt");

2802

2804 return Arg;

2805}

2806

2810 Value *Ret = nullptr;

2811

2812

2813

2815 (Callee->getName() == "sqrt" ||

2816 Callee->getIntrinsicID() == Intrinsic::sqrt))

2818

2819 if (Value *Opt = mergeSqrtToExp(CI, B))

2820 return Opt;

2821

2823 return Ret;

2824

2826 if (I || I->getOpcode() != Instruction::FMul || I->isFast())

2827 return Ret;

2828

2829

2830

2831

2832 Value *Op0 = I->getOperand(0);

2833 Value *Op1 = I->getOperand(1);

2834 Value *RepeatOp = nullptr;

2835 Value *OtherOp = nullptr;

2836 if (Op0 == Op1) {

2837

2838 RepeatOp = Op0;

2839 } else {

2840

2841

2842

2843

2844

2848

2849 RepeatOp = MulOp;

2850 OtherOp = Op1;

2853

2854 RepeatOp = MulOp;

2855 OtherOp = Op0;

2856 }

2857 }

2858 if (!RepeatOp)

2859 return Ret;

2860

2861

2862

2863

2864

2865

2866 Value *FabsCall =

2867 B.CreateUnaryIntrinsic(Intrinsic::fabs, RepeatOp, I, "fabs");

2868 if (OtherOp) {

2869

2870

2871

2872 Value *SqrtCall =

2873 B.CreateUnaryIntrinsic(Intrinsic::sqrt, OtherOp, I, "sqrt");

2874 return copyFlags(*CI, B.CreateFMulFMF(FabsCall, SqrtCall, I));

2875 }

2876 return copyFlags(*CI, FabsCall);

2877}

2878

2880

2881

2882

2883

2885 if (!IsNoNan) {

2886 SimplifyQuery SQ(DL, TLI, DT, AC, CI, true, true, DC);

2889 KnownFPClass Known1 =

2892 const fltSemantics &FltSem =

2895 }

2896 }

2897

2898 if (IsNoNan) {

2901 FRemI->setHasNoNaNs(true);

2902 return FRem;

2903 }

2904 return nullptr;

2905}

2906

2907Value *LibCallSimplifier::optimizeTrigInversionPairs(CallInst *CI,

2911 Value *Ret = nullptr;

2913 if (UnsafeFPShrink &&

2914 (Name == "tan" || Name == "atanh" || Name == "sinh" || Name == "cosh" ||

2915 Name == "asinh") &&

2916 hasFloatVersion(M, Name))

2918

2921 if (!OpC)

2922 return Ret;

2923

2924

2925 if (!CI->isFast() || !OpC->isFast())

2926 return Ret;

2927

2928

2929

2930

2931

2932

2933 LibFunc Func;

2934 Function *F = OpC->getCalledFunction();

2935 if (F && TLI->getLibFunc(F->getName(), Func) &&

2937 LibFunc inverseFunc = llvm::StringSwitch(Callee->getName())

2938 .Case("tan", LibFunc_atan)

2939 .Case("atanh", LibFunc_tanh)

2940 .Case("sinh", LibFunc_asinh)

2941 .Case("cosh", LibFunc_acosh)

2942 .Case("tanf", LibFunc_atanf)

2943 .Case("atanhf", LibFunc_tanhf)

2944 .Case("sinhf", LibFunc_asinhf)

2945 .Case("coshf", LibFunc_acoshf)

2946 .Case("tanl", LibFunc_atanl)

2947 .Case("atanhl", LibFunc_tanhl)

2948 .Case("sinhl", LibFunc_asinhl)

2949 .Case("coshl", LibFunc_acoshl)

2950 .Case("asinh", LibFunc_sinh)

2951 .Case("asinhf", LibFunc_sinhf)

2952 .Case("asinhl", LibFunc_sinhl)

2953 .Default(NotLibFunc);

2954 if (Func == inverseFunc)

2955 Ret = OpC->getArgOperand(0);

2956 }

2957 return Ret;

2958}

2959

2966

2968 bool UseFloat, Value *&Sin, Value *&Cos,

2972 Type *ResTy;

2974

2976 if (UseFloat) {

2977 Name = "__sincospif_stret";

2978

2979 assert(T.getArch() != Triple::x86 && "x86 messy and unsupported for now");

2980

2981

2985 } else {

2986 Name = "__sincospi_stret";

2988 }

2989

2991 return false;

2992 LibFunc TheLibFunc;

2995 M, *TLI, TheLibFunc, OrigCallee->getAttributes(), ResTy, ArgTy);

2996

2998

2999

3000 B.SetInsertPoint(ArgInst->getParent(), ++ArgInst->getIterator());

3001 } else {

3002

3003

3004 BasicBlock &EntryBB = B.GetInsertBlock()->getParent()->getEntryBlock();

3005 B.SetInsertPoint(&EntryBB, EntryBB.begin());

3006 }

3007

3008 SinCos = B.CreateCall(Callee, Arg, "sincospi");

3009

3011 Sin = B.CreateExtractValue(SinCos, 0, "sinpi");

3012 Cos = B.CreateExtractValue(SinCos, 1, "cospi");

3013 } else {

3014 Sin = B.CreateExtractElement(SinCos, ConstantInt::get(B.getInt32Ty(), 0),

3015 "sinpi");

3016 Cos = B.CreateExtractElement(SinCos, ConstantInt::get(B.getInt32Ty(), 1),

3017 "cospi");

3018 }

3019

3020 return true;

3021}

3022

3027

3030 Call->copyFastMathFlags(CI);

3032 if (IsEven) {

3033

3035 }

3036

3037 return B.CreateFNegFMF(CallInst, CI);

3038 }

3039

3040

3044 Call->copyFastMathFlags(CI);

3046 }

3047

3048 return nullptr;

3049}

3050

3051Value *LibCallSimplifier::optimizeSymmetric(CallInst *CI, LibFunc Func,

3053 switch (Func) {

3054 case LibFunc_cos:

3055 case LibFunc_cosf:

3056 case LibFunc_cosl:

3058

3059 case LibFunc_sin:

3060 case LibFunc_sinf:

3061 case LibFunc_sinl:

3062

3063 case LibFunc_tan:

3064 case LibFunc_tanf:

3065 case LibFunc_tanl:

3066

3067 case LibFunc_erf:

3068 case LibFunc_erff:

3069 case LibFunc_erfl:

3071

3072 default:

3073 return nullptr;

3074 }

3075}

3076

3078

3079

3081 return nullptr;

3082

3085 return nullptr;

3086

3090

3092

3093

3094

3095

3097 for (User *U : Arg->users())

3098 classifyArgUse(U, F, IsFloat, SinCalls, CosCalls, SinCosCalls);

3099

3100

3101 if (SinCalls.empty() || CosCalls.empty())

3102 return nullptr;

3103

3104 Value *Sin, *Cos, *SinCos;

3106 SinCos, TLI))

3107 return nullptr;

3108

3109 auto replaceTrigInsts = [this](SmallVectorImpl<CallInst *> &Calls,

3111 for (CallInst *C : Calls)

3112 replaceAllUsesWith(C, Res);

3113 };

3114

3115 replaceTrigInsts(SinCalls, Sin);

3116 replaceTrigInsts(CosCalls, Cos);

3117 replaceTrigInsts(SinCosCalls, SinCos);

3118

3119 return IsSin ? Sin : Cos;

3120}

3121

3122void LibCallSimplifier::classifyArgUse(

3129 return;

3130

3131

3133 return;

3134

3137 LibFunc Func;

3138 if (!Callee || !TLI->getLibFunc(*Callee, Func) ||

3141 return;

3142

3143 if (IsFloat) {

3144 if (Func == LibFunc_sinpif)

3146 else if (Func == LibFunc_cospif)

3148 else if (Func == LibFunc_sincospif_stret)

3150 } else {

3151 if (Func == LibFunc_sinpi)

3153 else if (Func == LibFunc_cospi)

3155 else if (Func == LibFunc_sincospi_stret)

3157 }

3158}

3159

3160

3165 return nullptr;

3166

3171 return nullptr;

3174 return nullptr;

3175

3176

3177 unsigned IntBW = TLI->getIntSize();

3178 APSInt QuotInt(IntBW, false);

3179 bool IsExact;

3180 Status =

3183 return nullptr;

3184

3185 B.CreateAlignedStore(

3188 return ConstantFP::get(CI->getType(), Rem);

3189}

3190

3191

3193

3195 return nullptr;

3196

3197

3198

3203

3205

3208 return nullptr;

3209

3212

3215 return ConstantFP::get(CI->getType(), MaxVal);

3216}

3217

3218

3219

3220

3221

3223

3224

3227 Type *ArgType = Op->getType();

3228 Value *V = B.CreateIntrinsic(Intrinsic::cttz, {ArgType}, {Op, B.getTrue()},

3229 nullptr, "cttz");

3230 V = B.CreateAdd(V, ConstantInt::get(V->getType(), 1));

3231 V = B.CreateIntCast(V, RetType, false);

3232

3234 return B.CreateSelect(Cond, V, ConstantInt::get(RetType, 0));

3235}

3236

3238

3239

3241 Type *ArgType = Op->getType();

3242 Value *V = B.CreateIntrinsic(Intrinsic::ctlz, {ArgType}, {Op, B.getFalse()},

3243 nullptr, "ctlz");

3245 V);

3246 return B.CreateIntCast(V, CI->getType(), false);

3247}

3248

3250

3251

3253 Value *IsNeg = B.CreateIsNeg(X);

3254 Value *NegX = B.CreateNSWNeg(X, "neg");

3255 return B.CreateSelect(IsNeg, NegX, X);

3256}

3257

3259

3261 Type *ArgType = Op->getType();

3262 Op = B.CreateSub(Op, ConstantInt::get(ArgType, '0'), "isdigittmp");

3263 Op = B.CreateICmpULT(Op, ConstantInt::get(ArgType, 10), "isdigit");

3264 return B.CreateZExt(Op, CI->getType());

3265}

3266

3268

3270 Type *ArgType = Op->getType();

3271 Op = B.CreateICmpULT(Op, ConstantInt::get(ArgType, 128), "isascii");

3272 return B.CreateZExt(Op, CI->getType());

3273}

3274

3276

3278 ConstantInt::get(CI->getType(), 0x7F));

3279}

3280

3281

3283 StringRef Str;

3285 return nullptr;

3286

3287 return convertStrToInt(CI, Str, nullptr, 10, true, B);

3288}

3289

3290

3292 bool AsSigned) {

3295

3296

3299 EndPtr = nullptr;

3301 return nullptr;

3302

3303 StringRef Str;

3305 return nullptr;

3306

3308 return convertStrToInt(CI, Str, EndPtr, CInt->getSExtValue(), AsSigned, B);

3309 }

3310

3311 return nullptr;

3312}

3313

3314

3315

3316

3317

3319

3321 int StreamArg) {

3323

3324

3325

3326

3327

3328

3329

3330

3331 if (!CI->hasFnAttr(Attribute::Cold) &&

3334 }

3335

3336 return nullptr;

3337}

3338

3340 if (!Callee || !Callee->isDeclaration())

3341 return false;

3342

3343 if (StreamArg < 0)

3344 return true;

3345

3346

3347

3348

3349 if (StreamArg >= (int)CI->arg_size())

3350 return false;

3352 if (!LI)

3353 return false;

3356 return false;

3357 return GV->getName() == "stderr";

3358}

3359

3361

3362 StringRef FormatStr;

3364 return nullptr;

3365

3366

3367 if (FormatStr.empty())

3369

3370

3371

3372

3374 return nullptr;

3375

3377

3378 if (FormatStr.size() == 1 || FormatStr == "%%") {

3379

3380

3381

3382 Value *IntChar = ConstantInt::get(IntTy, (unsigned char)FormatStr[0]);

3383 return copyFlags(*CI, emitPutChar(IntChar, B, TLI));

3384 }

3385

3386

3387 if (FormatStr == "%s" && CI->arg_size() > 1) {

3388 StringRef OperandStr;

3389 if (!getConstantStringInfo(CI->getOperand(1), OperandStr))

3390 return nullptr;

3391

3392 if (OperandStr.empty())

3393 return (Value *)CI;

3394

3395 if (OperandStr.size() == 1) {

3396

3397

3398

3399 Value *IntChar = ConstantInt::get(IntTy, (unsigned char)OperandStr[0]);

3400 return copyFlags(*CI, emitPutChar(IntChar, B, TLI));

3401 }

3402

3403 if (OperandStr.back() == '\n') {

3404 OperandStr = OperandStr.drop_back();

3405 Value *GV = B.CreateGlobalString(OperandStr, "str");

3406 return copyFlags(*CI, emitPutS(GV, B, TLI));

3407 }

3408 return nullptr;

3409 }

3410

3411

3412 if (FormatStr.back() == '\n' &&

3413 !FormatStr.contains('%')) {

3414

3415

3416 FormatStr = FormatStr.drop_back();

3417 Value *GV = B.CreateGlobalString(FormatStr, "str");

3418 return copyFlags(*CI, emitPutS(GV, B, TLI));

3419 }

3420

3421

3422

3423 if (FormatStr == "%c" && CI->arg_size() > 1 &&

3425

3426

3427 Value *IntChar = B.CreateIntCast(CI->getArgOperand(1), IntTy, false);

3428 return copyFlags(*CI, emitPutChar(IntChar, B, TLI));

3429 }

3430

3431

3432 if (FormatStr == "%s\n" && CI->arg_size() > 1 &&

3435 return nullptr;

3436}

3437

3439

3442 FunctionType *FT = Callee->getFunctionType();

3443 if (Value *V = optimizePrintFString(CI, B)) {

3444 return V;

3445 }

3446

3448

3449

3450

3453 FunctionCallee IPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_iprintf, FT,

3454 Callee->getAttributes());

3456 New->setCalledFunction(IPrintFFn);

3457 B.Insert(New);

3458 return New;

3459 }

3460

3461

3462

3465 auto SmallPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_small_printf, FT,

3466 Callee->getAttributes());

3468 New->setCalledFunction(SmallPrintFFn);

3469 B.Insert(New);

3470 return New;

3471 }

3472

3473 return nullptr;

3474}

3475

3476Value *LibCallSimplifier::optimizeSPrintFString(CallInst *CI,

3478

3479 StringRef FormatStr;

3481 return nullptr;

3482

3483

3486

3487

3488 if (FormatStr.contains('%'))

3489 return nullptr;

3490

3491

3493

3494 TLI->getAsSizeT(FormatStr.size() + 1, *CI->getModule()));

3495 return ConstantInt::get(CI->getType(), FormatStr.size());

3496 }

3497

3498

3499

3500 if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->arg_size() < 3)

3501 return nullptr;

3502

3503

3504 if (FormatStr[1] == 'c') {

3505

3507 return nullptr;

3509 Value *Ptr = Dest;

3510 B.CreateStore(V, Ptr);

3511 Ptr = B.CreateInBoundsGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul");

3512 B.CreateStore(B.getInt8(0), Ptr);

3513

3514 return ConstantInt::get(CI->getType(), 1);

3515 }

3516

3517 if (FormatStr[1] == 's') {

3518

3519

3521 return nullptr;

3522

3524

3526

3528 if (SrcLen) {

3530 TLI->getAsSizeT(SrcLen, *CI->getModule()));

3531

3532 return ConstantInt::get(CI->getType(), SrcLen - 1);

3534

3535 Value *PtrDiff = B.CreatePtrDiff(B.getInt8Ty(), V, Dest);

3536 return B.CreateIntCast(PtrDiff, CI->getType(), false);

3537 }

3538

3541 return nullptr;

3542

3544 if (!Len)

3545 return nullptr;

3547 B.CreateAdd(Len, ConstantInt::get(Len->getType(), 1), "leninc");

3549

3550

3551 return B.CreateIntCast(Len, CI->getType(), false);

3552 }

3553 return nullptr;

3554}

3555

3559 FunctionType *FT = Callee->getFunctionType();

3560 if (Value *V = optimizeSPrintFString(CI, B)) {

3561 return V;

3562 }

3563

3565

3566

3567

3570 FunctionCallee SIPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_siprintf,

3571 FT, Callee->getAttributes());

3573 New->setCalledFunction(SIPrintFFn);

3574 B.Insert(New);

3575 return New;

3576 }

3577

3578

3579

3582 auto SmallSPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_small_sprintf, FT,

3583 Callee->getAttributes());

3585 New->setCalledFunction(SmallSPrintFFn);

3586 B.Insert(New);

3587 return New;

3588 }

3589

3590 return nullptr;

3591}

3592

3593

3594

3595

3596

3597

3598Value *LibCallSimplifier::emitSnPrintfMemCpy(CallInst *CI, Value *StrArg,

3601 assert(StrArg || (N < 2 && Str.size() == 1));

3602

3603 unsigned IntBits = TLI->getIntSize();

3604 uint64_t IntMax = maxIntN(IntBits);

3605 if (Str.size() > IntMax)

3606

3607

3608

3609 return nullptr;

3610

3611 Value *StrLen = ConstantInt::get(CI->getType(), Str.size());

3612 if (N == 0)

3613 return StrLen;

3614

3615

3616

3617 uint64_t NCopy;

3618 if (N > Str.size())

3619

3620

3621 NCopy = Str.size() + 1;

3622 else

3623 NCopy = N - 1;

3624

3626 if (NCopy && StrArg)

3627

3629 TLI->getAsSizeT(NCopy, *CI->getModule())));

3630

3631 if (N > Str.size())

3632

3633

3634 return StrLen;

3635

3636

3638 Value *NulOff = B.getIntN(IntBits, NCopy);

3639 Value *DstEnd = B.CreateInBoundsGEP(Int8Ty, DstArg, NulOff, "endptr");

3640 B.CreateStore(ConstantInt::get(Int8Ty, 0), DstEnd);

3641 return StrLen;

3642}

3643

3644Value *LibCallSimplifier::optimizeSnPrintFString(CallInst *CI,

3646

3649 return nullptr;

3650

3651 uint64_t N = Size->getZExtValue();

3652 uint64_t IntMax = maxIntN(TLI->getIntSize());

3653 if (N > IntMax)

3654

3655

3656 return nullptr;

3657

3660

3661

3662 StringRef FormatStr;

3664 return nullptr;

3665

3666

3668 if (FormatStr.contains('%'))

3669

3670

3671 return nullptr;

3672

3673 return emitSnPrintfMemCpy(CI, FmtArg, FormatStr, N, B);

3674 }

3675

3676

3677

3678 if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->arg_size() != 4)

3679 return nullptr;

3680

3681

3682 if (FormatStr[1] == 'c') {

3683 if (N <= 1) {

3684

3685

3686

3687 StringRef CharStr("*");

3688 return emitSnPrintfMemCpy(CI, nullptr, CharStr, N, B);

3689 }

3690

3691

3693 return nullptr;

3695 Value *Ptr = DstArg;

3696 B.CreateStore(V, Ptr);

3697 Ptr = B.CreateInBoundsGEP(B.getInt8Ty(), Ptr, B.getInt32(1), "nul");

3698 B.CreateStore(B.getInt8(0), Ptr);

3699 return ConstantInt::get(CI->getType(), 1);

3700 }

3701

3702 if (FormatStr[1] != 's')

3703 return nullptr;

3704

3706

3707 StringRef Str;

3709 return nullptr;

3710

3711 return emitSnPrintfMemCpy(CI, StrArg, Str, N, B);

3712}

3713

3715 if (Value *V = optimizeSnPrintFString(CI, B)) {

3716 return V;

3717 }

3718

3721 return nullptr;

3722}

3723

3724Value *LibCallSimplifier::optimizeFPrintFString(CallInst *CI,

3726 optimizeErrorReporting(CI, B, 0);

3727

3728

3729 StringRef FormatStr;

3731 return nullptr;

3732

3733

3734

3735

3737 return nullptr;

3738

3739

3741

3742 if (FormatStr.contains('%'))

3743 return nullptr;

3744

3747 TLI->getAsSizeT(FormatStr.size(), *CI->getModule()),

3749 }

3750

3751

3752

3753 if (FormatStr.size() != 2 || FormatStr[0] != '%' || CI->arg_size() < 3)

3754 return nullptr;

3755

3756

3757 if (FormatStr[1] == 'c') {

3758

3760 return nullptr;

3761 Type *IntTy = B.getIntNTy(TLI->getIntSize());

3763 "chari");

3765 }

3766

3767 if (FormatStr[1] == 's') {

3768

3770 return nullptr;

3773 }

3774 return nullptr;

3775}

3776

3780 FunctionType *FT = Callee->getFunctionType();

3781 if (Value *V = optimizeFPrintFString(CI, B)) {

3782 return V;

3783 }

3784

3785

3786

3789 FunctionCallee FIPrintFFn = getOrInsertLibFunc(M, *TLI, LibFunc_fiprintf,

3790 FT, Callee->getAttributes());

3792 New->setCalledFunction(FIPrintFFn);

3793 B.Insert(New);

3794 return New;

3795 }

3796

3797

3798

3801 auto SmallFPrintFFn =

3803 Callee->getAttributes());

3805 New->setCalledFunction(SmallFPrintFFn);

3806 B.Insert(New);

3807 return New;

3808 }

3809

3810 return nullptr;

3811}

3812

3814 optimizeErrorReporting(CI, B, 3);

3815

3816

3819 if (SizeC && CountC) {

3821

3822

3823 if (Bytes == 0)

3824 return ConstantInt::get(CI->getType(), 0);

3825

3826

3827

3828 if (Bytes == 1 && CI->use_empty()) {

3831 Value *Cast = B.CreateIntCast(Char, IntTy, true, "chari");

3833 return NewCI ? ConstantInt::get(CI->getType(), 1) : nullptr;

3834 }

3835 }

3836

3837 return nullptr;

3838}

3839

3841 optimizeErrorReporting(CI, B, 1);

3842

3843

3844

3847 return nullptr;

3848

3849

3851 return nullptr;

3852

3853

3855 if (!Len)

3856 return nullptr;

3857

3858

3859 unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());

3862 *CI,

3864 ConstantInt::get(SizeTTy, Len - 1),

3866}

3867

3871 return nullptr;

3872

3873

3874

3875 StringRef Str;

3877

3878

3881 }

3882

3883 return nullptr;

3884}

3885

3886Value *LibCallSimplifier::optimizeExit(CallInst *CI) {

3887

3888

3889 const APInt *C;

3890 if (!CI->hasFnAttr(Attribute::Cold) &&

3893 }

3894 return nullptr;

3895}

3896

3898

3902}

3903

3904bool LibCallSimplifier::hasFloatVersion(const Module *M, StringRef FuncName) {

3905 SmallString<20> FloatFuncName = FuncName;

3906 FloatFuncName += 'f';

3908}

3909

3910Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI,

3913 LibFunc Func;

3915

3916

3917 if (TLI->getLibFunc(*Callee, Func) && isLibFuncEmittable(M, TLI, Func)) {

3918

3922 "Optimizing string/memory libcall would change the calling convention");

3923 switch (Func) {

3924 case LibFunc_strcat:

3925 return optimizeStrCat(CI, Builder);

3926 case LibFunc_strncat:

3927 return optimizeStrNCat(CI, Builder);

3928 case LibFunc_strchr:

3929 return optimizeStrChr(CI, Builder);

3930 case LibFunc_strrchr:

3931 return optimizeStrRChr(CI, Builder);

3932 case LibFunc_strcmp:

3933 return optimizeStrCmp(CI, Builder);

3934 case LibFunc_strncmp:

3935 return optimizeStrNCmp(CI, Builder);

3936 case LibFunc_strcpy:

3937 return optimizeStrCpy(CI, Builder);

3938 case LibFunc_stpcpy:

3939 return optimizeStpCpy(CI, Builder);

3940 case LibFunc_strlcpy:

3941 return optimizeStrLCpy(CI, Builder);

3942 case LibFunc_stpncpy:

3943 return optimizeStringNCpy(CI, true, Builder);

3944 case LibFunc_strncpy:

3945 return optimizeStringNCpy(CI, false, Builder);

3946 case LibFunc_strlen:

3947 return optimizeStrLen(CI, Builder);

3948 case LibFunc_strnlen:

3949 return optimizeStrNLen(CI, Builder);

3950 case LibFunc_strpbrk:

3951 return optimizeStrPBrk(CI, Builder);

3952 case LibFunc_strndup:

3953 return optimizeStrNDup(CI, Builder);

3954 case LibFunc_strtol:

3955 case LibFunc_strtod:

3956 case LibFunc_strtof:

3957 case LibFunc_strtoul:

3958 case LibFunc_strtoll:

3959 case LibFunc_strtold:

3960 case LibFunc_strtoull:

3961 return optimizeStrTo(CI, Builder);

3962 case LibFunc_strspn:

3963 return optimizeStrSpn(CI, Builder);

3964 case LibFunc_strcspn:

3965 return optimizeStrCSpn(CI, Builder);

3966 case LibFunc_strstr:

3967 return optimizeStrStr(CI, Builder);

3968 case LibFunc_memchr:

3969 return optimizeMemChr(CI, Builder);

3970 case LibFunc_memrchr:

3971 return optimizeMemRChr(CI, Builder);

3972 case LibFunc_bcmp:

3973 return optimizeBCmp(CI, Builder);

3974 case LibFunc_memcmp:

3975 return optimizeMemCmp(CI, Builder);

3976 case LibFunc_memcpy:

3977 return optimizeMemCpy(CI, Builder);

3978 case LibFunc_memccpy:

3979 return optimizeMemCCpy(CI, Builder);

3980 case LibFunc_mempcpy:

3981 return optimizeMemPCpy(CI, Builder);

3982 case LibFunc_memmove:

3983 return optimizeMemMove(CI, Builder);

3984 case LibFunc_memset:

3985 return optimizeMemSet(CI, Builder);

3986 case LibFunc_realloc:

3987 return optimizeRealloc(CI, Builder);

3988 case LibFunc_wcslen:

3989 return optimizeWcslen(CI, Builder);

3990 case LibFunc_bcopy:

3991 return optimizeBCopy(CI, Builder);

3992 case LibFunc_Znwm:

3993 case LibFunc_ZnwmRKSt9nothrow_t:

3994 case LibFunc_ZnwmSt11align_val_t:

3995 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:

3996 case LibFunc_Znam:

3997 case LibFunc_ZnamRKSt9nothrow_t:

3998 case LibFunc_ZnamSt11align_val_t:

3999 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:

4000 case LibFunc_Znwm12__hot_cold_t:

4001 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:

4002 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:

4003 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

4004 case LibFunc_Znam12__hot_cold_t:

4005 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:

4006 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:

4007 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

4008 case LibFunc_size_returning_new:

4009 case LibFunc_size_returning_new_hot_cold:

4010 case LibFunc_size_returning_new_aligned:

4011 case LibFunc_size_returning_new_aligned_hot_cold:

4012 return optimizeNew(CI, Builder, Func);

4013 default:

4014 break;

4015 }

4016 }

4017 return nullptr;

4018}

4019

4020

4024 return nullptr;

4025

4027

4028 if (CharSeq.empty())

4029 Fill = APInt(32, 0);

4031 return nullptr;

4032

4034}

4035

4036Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,

4037 LibFunc Func,

4040

4041

4043 return nullptr;

4044

4045 if (Value *V = optimizeSymmetric(CI, Func, Builder))

4046 return V;

4047

4048 switch (Func) {

4049 case LibFunc_sinpif:

4050 case LibFunc_sinpi:

4051 return optimizeSinCosPi(CI, true, Builder);

4052 case LibFunc_cospif:

4053 case LibFunc_cospi:

4054 return optimizeSinCosPi(CI, false, Builder);

4055 case LibFunc_powf:

4056 case LibFunc_pow:

4057 case LibFunc_powl:

4058 return optimizePow(CI, Builder);

4059 case LibFunc_exp2l:

4060 case LibFunc_exp2:

4061 case LibFunc_exp2f:

4062 return optimizeExp2(CI, Builder);

4063 case LibFunc_fabsf:

4064 case LibFunc_fabs:

4065 case LibFunc_fabsl:

4067 case LibFunc_sqrtf:

4068 case LibFunc_sqrt:

4069 case LibFunc_sqrtl:

4070 return optimizeSqrt(CI, Builder);

4071 case LibFunc_fmod:

4072 case LibFunc_fmodf:

4073 case LibFunc_fmodl:

4074 return optimizeFMod(CI, Builder);

4075 case LibFunc_logf:

4076 case LibFunc_log:

4077 case LibFunc_logl:

4078 case LibFunc_log10f:

4079 case LibFunc_log10:

4080 case LibFunc_log10l:

4081 case LibFunc_log1pf:

4082 case LibFunc_log1p:

4083 case LibFunc_log1pl:

4084 case LibFunc_log2f:

4085 case LibFunc_log2:

4086 case LibFunc_log2l:

4087 case LibFunc_logbf:

4088 case LibFunc_logb:

4089 case LibFunc_logbl:

4090 return optimizeLog(CI, Builder);

4091 case LibFunc_tan:

4092 case LibFunc_tanf:

4093 case LibFunc_tanl:

4094 case LibFunc_sinh:

4095 case LibFunc_sinhf:

4096 case LibFunc_sinhl:

4097 case LibFunc_asinh:

4098 case LibFunc_asinhf:

4099 case LibFunc_asinhl:

4100 case LibFunc_cosh:

4101 case LibFunc_coshf:

4102 case LibFunc_coshl:

4103 case LibFunc_atanh:

4104 case LibFunc_atanhf:

4105 case LibFunc_atanhl:

4106 return optimizeTrigInversionPairs(CI, Builder);

4107 case LibFunc_ceil:

4109 case LibFunc_floor:

4111 case LibFunc_round:

4113 case LibFunc_roundeven:

4115 case LibFunc_nearbyint:

4117 case LibFunc_rint:

4119 case LibFunc_trunc:

4121 case LibFunc_acos:

4122 case LibFunc_acosh:

4123 case LibFunc_asin:

4124 case LibFunc_atan:

4125 case LibFunc_cbrt:

4126 case LibFunc_exp:

4127 case LibFunc_exp10:

4128 case LibFunc_expm1:

4129 case LibFunc_cos:

4130 case LibFunc_sin:

4131 case LibFunc_tanh:

4134 return nullptr;

4135 case LibFunc_copysign:

4138 return nullptr;

4139 case LibFunc_fdim:

4140 case LibFunc_fdimf:

4141 case LibFunc_fdiml:

4142 return optimizeFdim(CI, Builder);

4143 case LibFunc_fminf:

4144 case LibFunc_fmin:

4145 case LibFunc_fminl:

4146 case LibFunc_fmaxf:

4147 case LibFunc_fmax:

4148 case LibFunc_fmaxl:

4149 return optimizeFMinFMax(CI, Builder);

4150 case LibFunc_fminimum_numf:

4151 case LibFunc_fminimum_num:

4152 case LibFunc_fminimum_numl:

4153 case LibFunc_fmaximum_numf:

4154 case LibFunc_fmaximum_num:

4155 case LibFunc_fmaximum_numl:

4156 return optimizeFMinimumnumFMaximumnum(CI, Builder);

4157 case LibFunc_cabs:

4158 case LibFunc_cabsf:

4159 case LibFunc_cabsl:

4160 return optimizeCAbs(CI, Builder);

4161 case LibFunc_remquo:

4162 case LibFunc_remquof:

4163 case LibFunc_remquol:

4164 return optimizeRemquo(CI, Builder);

4165 case LibFunc_nan:

4166 case LibFunc_nanf:

4167 case LibFunc_nanl:

4169 default:

4170 return nullptr;

4171 }

4172}

4173

4177

4178

4179

4180

4182

4183 return maybeOptimizeNoBuiltinOperatorNew(CI, Builder);

4184 }

4185

4186 LibFunc Func;

4189

4192

4194 Builder.setDefaultOperandBundles(OpBundles);

4195

4196

4197

4198

4202 UnsafeFPShrink = true;

4203

4204

4206 if (!IsCallingConvC)

4207 return nullptr;

4208

4209

4210 switch (II->getIntrinsicID()) {

4211 case Intrinsic::pow:

4212 return optimizePow(CI, Builder);

4213 case Intrinsic::exp2:

4214 return optimizeExp2(CI, Builder);

4215 case Intrinsic:🪵

4216 case Intrinsic::log2:

4217 case Intrinsic::log10:

4218 return optimizeLog(CI, Builder);

4219 case Intrinsic::sqrt:

4220 return optimizeSqrt(CI, Builder);

4221 case Intrinsic::memset:

4222 return optimizeMemSet(CI, Builder);

4223 case Intrinsic::memcpy:

4224 return optimizeMemCpy(CI, Builder);

4225 case Intrinsic::memmove:

4226 return optimizeMemMove(CI, Builder);

4227 case Intrinsic::sin:

4228 case Intrinsic::cos:

4229 if (UnsafeFPShrink)

4231 return nullptr;

4232 default:

4233 return nullptr;

4234 }

4235 }

4236

4237

4238 if (Value *SimplifiedFortifiedCI =

4239 FortifiedSimplifier.optimizeCall(CI, Builder))

4240 return SimplifiedFortifiedCI;

4241

4242

4243 if (TLI->getLibFunc(*Callee, Func) && isLibFuncEmittable(M, TLI, Func)) {

4244

4246 return nullptr;

4247 if (Value *V = optimizeStringMemoryLibCall(CI, Builder))

4248 return V;

4249 if (Value *V = optimizeFloatingPointLibCall(CI, Func, Builder))

4250 return V;

4251 switch (Func) {

4252 case LibFunc_ffs:

4253 case LibFunc_ffsl:

4254 case LibFunc_ffsll:

4255 return optimizeFFS(CI, Builder);

4256 case LibFunc_fls:

4257 case LibFunc_flsl:

4258 case LibFunc_flsll:

4259 return optimizeFls(CI, Builder);

4260 case LibFunc_abs:

4261 case LibFunc_labs:

4262 case LibFunc_llabs:

4263 return optimizeAbs(CI, Builder);

4264 case LibFunc_isdigit:

4265 return optimizeIsDigit(CI, Builder);

4266 case LibFunc_isascii:

4267 return optimizeIsAscii(CI, Builder);

4268 case LibFunc_toascii:

4269 return optimizeToAscii(CI, Builder);

4270 case LibFunc_atoi:

4271 case LibFunc_atol:

4272 case LibFunc_atoll:

4273 return optimizeAtoi(CI, Builder);

4274 case LibFunc_strtol:

4275 case LibFunc_strtoll:

4276 return optimizeStrToInt(CI, Builder, true);

4277 case LibFunc_strtoul:

4278 case LibFunc_strtoull:

4279 return optimizeStrToInt(CI, Builder, false);

4280 case LibFunc_printf:

4281 return optimizePrintF(CI, Builder);

4282 case LibFunc_sprintf:

4283 return optimizeSPrintF(CI, Builder);

4284 case LibFunc_snprintf:

4285 return optimizeSnPrintF(CI, Builder);

4286 case LibFunc_fprintf:

4287 return optimizeFPrintF(CI, Builder);

4288 case LibFunc_fwrite:

4289 return optimizeFWrite(CI, Builder);

4290 case LibFunc_fputs:

4291 return optimizeFPuts(CI, Builder);

4292 case LibFunc_puts:

4293 return optimizePuts(CI, Builder);

4294 case LibFunc_perror:

4295 return optimizeErrorReporting(CI, Builder);

4296 case LibFunc_vfprintf:

4297 case LibFunc_fiprintf:

4298 return optimizeErrorReporting(CI, Builder, 0);

4299 case LibFunc_exit:

4300 case LibFunc_Exit:

4301 return optimizeExit(CI);

4302 default:

4303 return nullptr;

4304 }

4305 }

4306 return nullptr;

4307}

4308

4315 : FortifiedSimplifier(TLI), DL(DL), TLI(TLI), DT(DT), DC(DC), AC(AC),

4316 ORE(ORE), BFI(BFI), PSI(PSI), Replacer(Replacer), Eraser(Eraser) {}

4317

4318void LibCallSimplifier::replaceAllUsesWith(Instruction *I, Value *With) {

4319

4320 Replacer(I, With);

4321}

4322

4323void LibCallSimplifier::eraseFromParent(Instruction *I) {

4324 Eraser(I);

4325}

4326

4327

4328

4329

4330

4331

4332

4333

4334

4335

4336

4337

4338

4339

4340

4341

4342

4343

4344

4345

4346

4347

4348

4349

4350

4351

4352

4353

4354

4355

4356

4357

4358

4359

4360

4361

4362bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(

4363 CallInst *CI, unsigned ObjSizeOp, std::optional SizeOp,

4364 std::optional StrOp, std::optional FlagOp) {

4365

4366

4367 if (FlagOp) {

4369 if (!Flag || Flag->isZero())

4370 return false;

4371 }

4372

4374 return true;

4375

4376 if (ConstantInt *ObjSizeCI =

4378 if (ObjSizeCI->isMinusOne())

4379 return true;

4380

4381 if (OnlyLowerUnknownSize)

4382 return false;

4383 if (StrOp) {

4385

4386

4387 if (Len)

4389 else

4390 return false;

4391 return ObjSizeCI->getZExtValue() >= Len;

4392 }

4393

4394 if (SizeOp) {

4395 if (ConstantInt *SizeCI =

4397 return ObjSizeCI->getZExtValue() >= SizeCI->getZExtValue();

4398 }

4399 }

4400 return false;

4401}

4402

4403Value *FortifiedLibCallSimplifier::optimizeMemCpyChk(CallInst *CI,

4405 if (isFortifiedCallFoldable(CI, 3, 2)) {

4406 CallInst *NewCI =

4411 }

4412 return nullptr;

4413}

4414

4415Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI,

4417 if (isFortifiedCallFoldable(CI, 3, 2)) {

4418 CallInst *NewCI =

4423 }

4424 return nullptr;

4425}

4426

4427Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI,

4429 if (isFortifiedCallFoldable(CI, 3, 2)) {

4431 CallInst *NewCI = B.CreateMemSet(CI->getArgOperand(0), Val,

4435 }

4436 return nullptr;

4437}

4438

4439Value *FortifiedLibCallSimplifier::optimizeMemPCpyChk(CallInst *CI,

4442 if (isFortifiedCallFoldable(CI, 3, 2))

4446 }

4447 return nullptr;

4448}

4449

4450Value *FortifiedLibCallSimplifier::optimizeStrpCpyChk(CallInst *CI,

4452 LibFunc Func) {

4456

4457

4458 if (Func == LibFunc_stpcpy_chk && !OnlyLowerUnknownSize && Dst == Src) {

4460 return StrLen ? B.CreateInBoundsGEP(B.getInt8Ty(), Dst, StrLen) : nullptr;

4461 }

4462

4463

4464

4465

4466

4467

4468 if (isFortifiedCallFoldable(CI, 2, std::nullopt, 1)) {

4469 if (Func == LibFunc_strcpy_chk)

4471 else

4473 }

4474

4475 if (OnlyLowerUnknownSize)

4476 return nullptr;

4477

4478

4480 if (Len)

4482 else

4483 return nullptr;

4484

4485 unsigned SizeTBits = TLI->getSizeTSize(*CI->getModule());

4487 Value *LenV = ConstantInt::get(SizeTTy, Len);

4489

4490

4491 if (Ret && Func == LibFunc_stpcpy_chk)

4492 return B.CreateInBoundsGEP(B.getInt8Ty(), Dst,

4493 ConstantInt::get(SizeTTy, Len - 1));

4495}

4496

4497Value *FortifiedLibCallSimplifier::optimizeStrLenChk(CallInst *CI,

4499 if (isFortifiedCallFoldable(CI, 1, std::nullopt, 0))

4502 return nullptr;

4503}

4504

4505Value *FortifiedLibCallSimplifier::optimizeStrpNCpyChk(CallInst *CI,

4507 LibFunc Func) {

4508 if (isFortifiedCallFoldable(CI, 3, 2)) {

4509 if (Func == LibFunc_strncpy_chk)

4513 else

4517 }

4518

4519 return nullptr;

4520}

4521

4522Value *FortifiedLibCallSimplifier::optimizeMemCCpyChk(CallInst *CI,

4524 if (isFortifiedCallFoldable(CI, 4, 3))

4528

4529 return nullptr;

4530}

4531

4532Value *FortifiedLibCallSimplifier::optimizeSNPrintfChk(CallInst *CI,

4534 if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2)) {

4535 SmallVector<Value *, 8> VariadicArgs(drop_begin(CI->args(), 5));

4539 }

4540

4541 return nullptr;

4542}

4543

4544Value *FortifiedLibCallSimplifier::optimizeSPrintfChk(CallInst *CI,

4546 if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1)) {

4547 SmallVector<Value *, 8> VariadicArgs(drop_begin(CI->args(), 4));

4550 VariadicArgs, B, TLI));

4551 }

4552

4553 return nullptr;

4554}

4555

4556Value *FortifiedLibCallSimplifier::optimizeStrCatChk(CallInst *CI,

4558 if (isFortifiedCallFoldable(CI, 2))

4561

4562 return nullptr;

4563}

4564

4565Value *FortifiedLibCallSimplifier::optimizeStrLCat(CallInst *CI,

4567 if (isFortifiedCallFoldable(CI, 3))

4571

4572 return nullptr;

4573}

4574

4575Value *FortifiedLibCallSimplifier::optimizeStrNCatChk(CallInst *CI,

4577 if (isFortifiedCallFoldable(CI, 3))

4581

4582 return nullptr;

4583}

4584

4585Value *FortifiedLibCallSimplifier::optimizeStrLCpyChk(CallInst *CI,

4587 if (isFortifiedCallFoldable(CI, 3))

4591

4592 return nullptr;

4593}

4594

4595Value *FortifiedLibCallSimplifier::optimizeVSNPrintfChk(CallInst *CI,

4597 if (isFortifiedCallFoldable(CI, 3, 1, std::nullopt, 2))

4601

4602 return nullptr;

4603}

4604

4605Value *FortifiedLibCallSimplifier::optimizeVSPrintfChk(CallInst *CI,

4607 if (isFortifiedCallFoldable(CI, 2, std::nullopt, std::nullopt, 1))

4611

4612 return nullptr;

4613}

4614

4617

4618

4619

4620

4621

4622

4623

4624

4625

4626

4627

4628

4629

4630 LibFunc Func;

4633

4636

4638 Builder.setDefaultOperandBundles(OpBundles);

4639

4640

4641

4642 if (!TLI->getLibFunc(*Callee, Func))

4643 return nullptr;

4644

4645

4647 return nullptr;

4648

4649 switch (Func) {

4650 case LibFunc_memcpy_chk:

4651 return optimizeMemCpyChk(CI, Builder);

4652 case LibFunc_mempcpy_chk:

4653 return optimizeMemPCpyChk(CI, Builder);

4654 case LibFunc_memmove_chk:

4655 return optimizeMemMoveChk(CI, Builder);

4656 case LibFunc_memset_chk:

4657 return optimizeMemSetChk(CI, Builder);

4658 case LibFunc_stpcpy_chk:

4659 case LibFunc_strcpy_chk:

4660 return optimizeStrpCpyChk(CI, Builder, Func);

4661 case LibFunc_strlen_chk:

4662 return optimizeStrLenChk(CI, Builder);

4663 case LibFunc_stpncpy_chk:

4664 case LibFunc_strncpy_chk:

4665 return optimizeStrpNCpyChk(CI, Builder, Func);

4666 case LibFunc_memccpy_chk:

4667 return optimizeMemCCpyChk(CI, Builder);

4668 case LibFunc_snprintf_chk:

4669 return optimizeSNPrintfChk(CI, Builder);

4670 case LibFunc_sprintf_chk:

4671 return optimizeSPrintfChk(CI, Builder);

4672 case LibFunc_strcat_chk:

4673 return optimizeStrCatChk(CI, Builder);

4674 case LibFunc_strlcat_chk:

4675 return optimizeStrLCat(CI, Builder);

4676 case LibFunc_strncat_chk:

4677 return optimizeStrNCatChk(CI, Builder);

4678 case LibFunc_strlcpy_chk:

4679 return optimizeStrLCpyChk(CI, Builder);

4680 case LibFunc_vsnprintf_chk:

4681 return optimizeVSNPrintfChk(CI, Builder);

4682 case LibFunc_vsprintf_chk:

4683 return optimizeVSPrintfChk(CI, Builder);

4684 default:

4685 break;

4686 }

4687 return nullptr;

4688}

4689

4692 : TLI(TLI), OnlyLowerUnknownSize(OnlyLowerUnknownSize) {}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file declares a class to represent arbitrary precision floating point values and provide a varie...

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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

Module.h This file contains the declarations for the Module class.

static llvm::Error parse(DataExtractor &Data, uint64_t BaseAddr, LineEntryCallback const &Callback)

Machine Check Debug Module

uint64_t IntrinsicInst * II

static bool isBinary(MachineInstr &MI)

const SmallVectorImpl< MachineOperand > & Cond

static bool isOnlyUsedInEqualityComparison(Value *V, Value *With)

Return true if it is only used in equality comparisons with With.

Definition SimplifyLibCalls.cpp:118

static void annotateNonNullAndDereferenceable(CallInst *CI, ArrayRef< unsigned > ArgNos, Value *Size, const DataLayout &DL)

Definition SimplifyLibCalls.cpp:323

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)

Definition SimplifyLibCalls.cpp:2967

static bool canTransformToMemCmp(CallInst *CI, Value *Str, uint64_t Len, const DataLayout &DL)

Definition SimplifyLibCalls.cpp:262

static Value * mergeAttributesAndFlags(CallInst *NewCI, const CallInst &Old)

Definition SimplifyLibCalls.cpp:352

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.

Definition SimplifyLibCalls.cpp:2030

static bool ignoreCallingConv(LibFunc Func)

Definition SimplifyLibCalls.cpp:112

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)

Definition SimplifyLibCalls.cpp:276

static bool isReportingError(Function *Callee, CallInst *CI, int StreamArg)

Definition SimplifyLibCalls.cpp:3339

static Value * optimizeDoubleFP(CallInst *CI, IRBuilderBase &B, bool isBinary, const TargetLibraryInfo *TLI, bool isPrecise=false)

Shrink double -> float functions.

Definition SimplifyLibCalls.cpp:1964

static Value * optimizeSymmetricCall(CallInst *CI, bool IsEven, IRBuilderBase &B)

Definition SimplifyLibCalls.cpp:3023

static Value * getSqrtCall(Value *V, AttributeList Attrs, bool NoErrno, Module *M, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Definition SimplifyLibCalls.cpp:2282

static Value * valueHasFloatPrecision(Value *Val)

Return a variant of Val with float type.

Definition SimplifyLibCalls.cpp:1946

static Value * optimizeMemCmpConstantSize(CallInst *CI, Value *LHS, Value *RHS, uint64_t Len, IRBuilderBase &B, const DataLayout &DL)

Definition SimplifyLibCalls.cpp:1542

static Value * createPowWithIntegerExponent(Value *Base, Value *Expo, Module *M, IRBuilderBase &B)

Definition SimplifyLibCalls.cpp:2353

static Value * convertStrToInt(CallInst *CI, StringRef &Str, Value *EndPtr, uint64_t Base, bool AsSigned, IRBuilderBase &B)

Definition SimplifyLibCalls.cpp:148

static Value * memChrToCharCompare(CallInst *CI, Value *NBytes, IRBuilderBase &B, const DataLayout &DL)

Definition SimplifyLibCalls.cpp:461

static Value * copyFlags(const CallInst &Old, Value *New)

Definition SimplifyLibCalls.cpp:344

static StringRef substr(StringRef Str, uint64_t Len)

Definition SimplifyLibCalls.cpp:366

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)

Definition SimplifyLibCalls.cpp:2960

static Value * optimizeNaN(CallInst *CI)

Constant folding nan/nanf/nanl.

Definition SimplifyLibCalls.cpp:4021

static bool isOnlyUsedInComparisonWithZero(Value *V)

Definition SimplifyLibCalls.cpp:250

static Value * replaceUnaryCall(CallInst *CI, IRBuilderBase &B, Intrinsic::ID IID)

Definition SimplifyLibCalls.cpp:1934

static bool callHasFloatingPointArgument(const CallInst *CI)

Definition SimplifyLibCalls.cpp:129

static Value * optimizeUnaryDoubleFP(CallInst *CI, IRBuilderBase &B, const TargetLibraryInfo *TLI, bool isPrecise=false)

Shrink double -> float for unary functions.

Definition SimplifyLibCalls.cpp:2023

static bool callHasFP128Argument(const CallInst *CI)

Definition SimplifyLibCalls.cpp:135

static cl::opt< bool > OptimizeNoBuiltinHotColdNew("optimize-nobuiltin-hot-cold-new-new", cl::Hidden, cl::init(false), cl::desc("Enable transformation of nobuiltin operator new library calls"))

static cl::opt< unsigned, false, HotColdHintParser > AmbiguousNewHintValue("ambiguous-new-hint-value", cl::Hidden, cl::init(222), cl::desc("Value to pass to hot/cold operator new for ambiguous allocation"))

static void annotateNonNullNoUndefBasedOnAccess(CallInst *CI, ArrayRef< unsigned > ArgNos)

Definition SimplifyLibCalls.cpp:301

static Value * optimizeMemCmpVarSize(CallInst *CI, Value *LHS, Value *RHS, Value *Size, bool StrNCmp, IRBuilderBase &B, const DataLayout &DL)

Definition SimplifyLibCalls.cpp:1500

static Value * getIntToFPVal(Value *I2F, IRBuilderBase &B, unsigned DstWidth)

Definition SimplifyLibCalls.cpp:2088

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.

static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")

static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")

static SymbolRef::Type getType(const Symbol *Sym)

static const fltSemantics & IEEEsingle()

static constexpr roundingMode rmTowardZero

static constexpr roundingMode rmTowardNegative

static constexpr roundingMode rmNearestTiesToEven

opStatus

IEEE-754R 7: Default exception handling.

opStatus divide(const APFloat &RHS, roundingMode RM)

bool isFiniteNonZero() const

LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)

opStatus subtract(const APFloat &RHS, roundingMode RM)

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 ...

opStatus add(const APFloat &RHS, roundingMode RM)

const fltSemantics & getSemantics() const

LLVM_ABI 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

static APFloat getZero(const fltSemantics &Sem, bool Negative=false)

Factory for Positive and Negative Zero.

Class for arbitrary precision integers.

bool ule(const APInt &RHS) const

Unsigned less or equal comparison.

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 LLVM_ABI Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)

static LLVM_ABI Attribute getWithCaptureInfo(LLVMContext &Context, CaptureInfo CI)

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 removeParamAttrs(unsigned ArgNo, const AttributeMask &AttrsToRemove)

Removes the attributes from the given argument.

LLVM_ABI 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.

AttributeSet getParamAttributes(unsigned ArgNo) const

Return the param attributes for this call.

uint64_t getParamDereferenceableBytes(unsigned i) const

Extract the number of dereferenceable bytes for a call or parameter (0=unknown).

LLVM_ABI 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).

AttributeSet getRetAttributes() const

Return the return attributes for this call.

void setAttributes(AttributeList A)

Set the 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).

LLVM_ABI 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 attributes for this call.

void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)

Adds the attribute to the indicated argument.

LLVM_ABI Function * getCaller()

Helper to get the caller (the parent function).

This class represents a function call, abstracting a target machine's calling convention.

bool isNoTailCall() const

TailCallKind getTailCallKind() const

bool isMustTailCall() const

static CaptureInfo none()

Create CaptureInfo that does not capture any components of the pointer.

@ ICMP_UGT

unsigned greater than

@ ICMP_ULT

unsigned less than

@ ICMP_ULE

unsigned less or equal

Predicate getPredicate() const

Return the predicate for this instruction.

LLVM_ABI uint64_t getElementAsInteger(uint64_t i) const

If this is a sequential container of integers (of any size), return the specified element in the low ...

ConstantFP - Floating Point Values [float, double].

static LLVM_ABI Constant * getInfinity(Type *Ty, bool Negative=false)

static LLVM_ABI Constant * getQNaN(Type *Ty, bool Negative=false, APInt *Payload=nullptr)

This is the shared class of boolean and integer constants.

bool isOne() const

This is just a convenience method to make client code smaller for a common case.

bool isZero() const

This is just a convenience method to make client code smaller for a common code.

static ConstantInt * getSigned(IntegerType *Ty, int64_t V)

Return a ConstantInt with the specified value for the specified type.

int64_t getSExtValue() const

Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...

uint64_t getZExtValue() const

Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...

This is an important base class in LLVM.

static LLVM_ABI Constant * getNullValue(Type *Ty)

Constructor to create a '0' constant of arbitrary type.

A parsed version of the target data layout string in and methods for querying it.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

This class represents an extension of floating point types.

This class represents a truncation of floating point types.

void setNoSignedZeros(bool B=true)

static FastMathFlags getFast()

static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)

FortifiedLibCallSimplifier(const TargetLibraryInfo *TLI, bool OnlyLowerUnknownSize=false)

Definition SimplifyLibCalls.cpp:4690

Value * optimizeCall(CallInst *CI, IRBuilderBase &B)

Take the given call instruction and return a more optimal value to replace the instruction with or 0 ...

Definition SimplifyLibCalls.cpp:4615

A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...

Intrinsic::ID getIntrinsicID() const LLVM_READONLY

getIntrinsicID - This method returns the ID number of the specified function, or Intrinsic::not_intri...

AttributeList getAttributes() const

Return the attribute list for this Function.

bool isIntrinsic() const

isIntrinsic - Returns true if the function's name starts with "llvm.".

bool hasFnAttribute(Attribute::AttrKind Kind) const

Return true if the function has the attribute.

LLVM_ABI bool isDeclaration() const

Return true if the primary definition of this global value is outside of the current translation unit...

Module * getParent()

Get the module that this global value is contained inside of...

This instruction compares its operands according to the predicate given to the constructor.

Common base class shared among various IRBuilders.

LLVM_ABI Instruction * clone() const

Create a copy of 'this' instruction that is identical in all ways except the following:

LLVM_ABI bool hasNoNaNs() const LLVM_READONLY

Determine whether the no-NaNs flag is set.

LLVM_ABI bool hasNoInfs() const LLVM_READONLY

Determine whether the no-infs flag is set.

LLVM_ABI bool hasNoSignedZeros() const LLVM_READONLY

Determine whether the no-signed-zeros flag is set.

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 bool isFast() const LLVM_READONLY

Determine whether all fast-math-flags are set.

LLVM_ABI const Function * getFunction() const

Return the function this instruction belongs to.

LLVM_ABI FastMathFlags getFastMathFlags() const LLVM_READONLY

Convenience function for getting all the fast-math flags, which must be an operator which supports th...

LLVM_ABI bool hasApproxFunc() const LLVM_READONLY

Determine whether the approximate-math-functions flag is set.

LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())

Copy metadata from SrcInst to this instruction.

LLVM_ABI bool hasAllowReassoc() const LLVM_READONLY

Determine whether the allow-reassociation flag is set.

LLVM_ABI const DataLayout & getDataLayout() const

Get the data layout of the module this instruction belongs to.

Class to represent integer types.

static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)

This static method is the primary way of constructing an IntegerType.

A wrapper class for inspecting calls to intrinsic functions.

LibCallSimplifier(const DataLayout &DL, const TargetLibraryInfo *TLI, DominatorTree *DT, DomConditionCache *DC, AssumptionCache *AC, OptimizationRemarkEmitter &ORE, BlockFrequencyInfo *BFI, ProfileSummaryInfo *PSI, function_ref< void(Instruction *, Value *)> Replacer=&replaceAllUsesWithDefault, function_ref< void(Instruction *)> Eraser=&eraseFromParentDefault)

Definition SimplifyLibCalls.cpp:4309

Value * optimizeCall(CallInst *CI, IRBuilderBase &B)

optimizeCall - Take the given call instruction and return a more optimal value to replace the instruc...

Definition SimplifyLibCalls.cpp:4174

An instruction for reading from memory.

Value * getPointerOperand()

A Module instance is used to store all the information related to an LLVM module.

const Triple & getTargetTriple() const

Get the target triple which is a string describing the target host.

Analysis providing profile information.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

static constexpr size_t npos

bool getAsInteger(unsigned Radix, T &Result) const

Parse the current string as an integer of the specified radix.

bool starts_with(StringRef Prefix) const

Check if this string starts with the given Prefix.

constexpr bool empty() const

empty - Check if the string is empty.

char back() const

back - Get the last character in the string.

constexpr size_t size() const

size - Get the string size.

bool contains(StringRef Other) const

Return true if the given string is a substring of *this, and false otherwise.

size_t find(char C, size_t From=0) const

Search for the first character C in the string.

bool ends_with(StringRef Suffix) const

Check if this string ends with the given Suffix.

int compare(StringRef RHS) const

compare - Compare two strings; the result is negative, zero, or positive if this string is lexicograp...

static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)

This static method is the primary way to create a literal StructType.

static LLVM_ABI bool isCallingConvCCompatible(CallBase *CI)

Returns true if call site / callee has cdecl-compatible calling conventions.

Provides information about what library functions are available for the current target.

bool getLibFunc(StringRef funcName, LibFunc &F) const

Searches for a particular function name.

Triple - Helper class for working with autoconf configuration names.

The instances of the Type class are immutable: once they are created, they are never changed.

LLVM_ABI unsigned getIntegerBitWidth() const

bool isVectorTy() const

True if this is an instance of VectorType.

bool isPointerTy() const

True if this is an instance of PointerType.

bool isFloatTy() const

Return true if this is 'float', a 32-bit IEEE fp type.

LLVM_ABI unsigned getPointerAddressSpace() const

Get the address space of this pointer or pointer vector type.

static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)

Type * getScalarType() const

If this is a vector type, return the element type, otherwise return 'this'.

bool isStructTy() const

True if this is an instance of StructType.

LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY

Return the basic size of this type if it is a primitive 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.

static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)

LLVM_ABI const fltSemantics & getFltSemantics() const

A Use represents the edge between a Value definition and its users.

void setOperand(unsigned i, Value *Val)

Value * getOperand(unsigned i) const

LLVM Value Representation.

Type * getType() const

All values are typed, get the type of this value.

bool hasOneUse() const

Return true if there is exactly one use of this 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.

An efficient, type-erasing, non-owning reference to a callable.

const ParentTy * getParent() const

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

Flag

These should be considered private to the implementation of the MCInstrDesc class.

OneUse_match< SubPat > m_OneUse(const SubPat &SP)

ap_match< APInt > m_APInt(const APInt *&Res)

Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.

BinaryOp_match< LHS, RHS, Instruction::FMul > m_FMul(const LHS &L, const RHS &R)

bool match(Val *V, const Pattern &P)

cstfp_pred_ty< is_any_zero_fp > m_AnyZeroFP()

Match a floating-point negative zero or positive zero.

ap_match< APFloat > m_APFloat(const APFloat *&Res)

Match a ConstantFP or splatted ConstantVector, binding the specified pointer to the contained APFloat...

class_match< ConstantInt > m_ConstantInt()

Match an arbitrary ConstantInt and ignore it.

ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)

Matches SelectInst.

specific_fpval m_SpecificFP(double V)

Match a specific floating point value or vector with all elements equal to the value.

deferredval_ty< Value > m_Deferred(Value *const &V)

Like m_Specific(), but works if the specific value to match is determined as part of the same match()...

specific_fpval m_FPOne()

Match a float 1.0 or vector with all elements equal to 1.0.

class_match< Value > m_Value()

Match an arbitrary value and ignore it.

FNeg_match< OpTy > m_FNeg(const OpTy &X)

Match 'fneg X' as 'fsub -0.0, X'.

m_Intrinsic_Ty< Opnd0 >::Ty m_FAbs(const Opnd0 &Op0)

m_Intrinsic_Ty< Opnd0, Opnd1 >::Ty m_CopySign(const Opnd0 &Op0, const Opnd1 &Op1)

This namespace contains all of the command line option processing machinery.

initializer< Ty > init(const Ty &Val)

NodeAddr< FuncNode * > Func

friend class Instruction

Iterator for Instructions in a `BasicBlock.

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

FunctionAddr VTableAddr Value

LLVM_ABI Value * emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI, StringRef Name, IRBuilderBase &B, const AttributeList &Attrs)

Emit a call to the unary function named 'Name' (e.g.

LLVM_ABI KnownFPClass computeKnownFPClass(const Value *V, const APInt &DemandedElts, FPClassTest InterestedClasses, const SimplifyQuery &SQ, unsigned Depth=0)

Determine which floating-point classes are valid for V, and return them in KnownFPClass bit sets.

LLVM_ABI Value * emitStrChr(Value *Ptr, char C, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strchr function to the builder, for the specified pointer and character.

constexpr uint64_t maxUIntN(uint64_t N)

Gets the maximum value for a N-bit unsigned integer.

LLVM_ABI Value * emitPutChar(Value *Char, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the putchar function. This assumes that Char is an 'int'.

LLVM_ABI Value * emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the __memcpy_chk function to the builder.

LLVM_ABI Value * emitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strncpy function to the builder, for the specified pointer arguments and length.

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 bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI)

LLVM_ABI Value * emitHotColdNewAlignedNoThrow(Value *Num, Value *Align, Value *NoThrow, IRBuilderBase &B, const TargetLibraryInfo *TLI, LibFunc NewFunc, uint8_t HotCold)

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

APFloat abs(APFloat X)

Returns the absolute value of the argument.

LLVM_ABI bool getConstantStringInfo(const Value *V, StringRef &Str, bool TrimAtNul=true)

This function computes the length of a null-terminated C string pointed to by V.

LLVM_ABI bool isDereferenceableAndAlignedPointer(const Value *V, Type *Ty, Align Alignment, const DataLayout &DL, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr)

Returns true if V is always a dereferenceable pointer with alignment greater or equal than requested.

LLVM_ABI Value * emitSPrintf(Value *Dest, Value *Fmt, ArrayRef< Value * > VariadicArgs, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the sprintf function.

LLVM_ABI bool getConstantDataArrayInfo(const Value *V, ConstantDataArraySlice &Slice, unsigned ElementSize, uint64_t Offset=0)

Returns true if the value V is a pointer into a ConstantDataArray.

LLVM_ABI Value * emitMemRChr(Value *Ptr, Value *Val, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the memrchr function, analogously to emitMemChr.

LLVM_READONLY APFloat maximum(const APFloat &A, const APFloat &B)

Implements IEEE 754-2019 maximum semantics.

LLVM_ABI Value * emitStrLCat(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strlcat function.

LLVM_ABI bool shouldOptimizeForSize(const MachineFunction *MF, ProfileSummaryInfo *PSI, const MachineBlockFrequencyInfo *BFI, PGSOQueryType QueryType=PGSOQueryType::Other)

Returns true if machine function MF is suggested to be size-optimized based on the profile.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

LLVM_ABI bool hasFloatFn(const Module *M, const TargetLibraryInfo *TLI, Type *Ty, LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn)

Check whether the overloaded floating point function corresponding to Ty is available.

LLVM_ABI Value * emitStrNCat(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strncat function.

LLVM_ABI bool isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI, LibFunc TheLibFunc)

Check whether the library function is available on target and also that it in the current Module is a...

LLVM_ABI Value * emitVSNPrintf(Value *Dest, Value *Size, Value *Fmt, Value *VAList, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the vsnprintf function.

auto dyn_cast_or_null(const Y &Val)

Align getKnownAlignment(Value *V, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)

Try to infer an alignment for the specified pointer.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI Value * emitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the strncmp function to the builder.

LLVM_ABI Value * emitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the memcmp function.

LLVM_ABI Value * emitBinaryFloatFnCall(Value *Op1, Value *Op2, const TargetLibraryInfo *TLI, StringRef Name, IRBuilderBase &B, const AttributeList &Attrs)

Emit a call to the binary function named 'Name' (e.g.

bool isAlpha(char C)

Checks if character C is a valid letter as classified by "C" locale.

LLVM_ABI Value * emitFPutS(Value *Str, Value *File, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the fputs function.

LLVM_ABI Value * emitStrDup(Value *Ptr, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strdup function to the builder, for the specified pointer.

decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI void computeKnownBits(const Value *V, KnownBits &Known, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)

Determine which bits of V are known to be either zero or one and return them in the KnownZero/KnownOn...

LLVM_ABI bool NullPointerIsDefined(const Function *F, unsigned AS=0)

Check whether null pointer dereferencing is considered undefined behavior for a given function or an ...

LLVM_ABI Value * emitBCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the bcmp function.

bool isDigit(char C)

Checks if character C is one of the 10 decimal digits.

std::enable_if_t< std::is_unsigned_v< T >, T > SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed=nullptr)

Multiply two unsigned integers, X and Y, and add the unsigned integer, A to the product.

LLVM_ABI uint64_t GetStringLength(const Value *V, unsigned CharSize=8)

If we can compute the length of the string pointed to by the specified pointer, return 'len+1'.

LLVM_ABI FunctionCallee getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI, LibFunc TheLibFunc, FunctionType *T, AttributeList AttributeList)

Calls getOrInsertFunction() and then makes sure to add mandatory argument attributes.

LLVM_ABI Value * emitStrLen(Value *Ptr, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the strlen function to the builder, for the specified pointer.

LLVM_ABI Value * emitFPutC(Value *Char, Value *File, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the fputc function.

LLVM_ABI Value * emitStpNCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the stpncpy function to the builder, for the specified pointer arguments and length.

LLVM_ABI Value * emitStrCat(Value *Dest, Value *Src, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strcat function.

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 Value * emitVSPrintf(Value *Dest, Value *Fmt, Value *VAList, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the vsprintf function.

LLVM_ABI bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)

Return true if the given value is known to be non-zero when defined.

LLVM_ABI Value * emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the fwrite function.

LLVM_ABI Value * emitSNPrintf(Value *Dest, Value *Size, Value *Fmt, ArrayRef< Value * > Args, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the snprintf function.

@ Mod

The access may modify the value stored in memory.

LLVM_ABI Value * emitStpCpy(Value *Dst, Value *Src, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the stpcpy function to the builder, for the specified pointer arguments.

@ And

Bitwise or logical AND of integers.

char toUpper(char x)

Returns the corresponding uppercase character if x is lowercase.

DWARFExpression::Operation Op

@ NearestTiesToEven

roundTiesToEven.

constexpr int64_t maxIntN(int64_t N)

Gets the maximum value for a N-bit signed integer.

constexpr unsigned BitWidth

decltype(auto) cast(const From &Val)

cast - Return the argument parameter cast to the specified type.

LLVM_ABI Value * emitHotColdNewNoThrow(Value *Num, Value *NoThrow, IRBuilderBase &B, const TargetLibraryInfo *TLI, LibFunc NewFunc, uint8_t HotCold)

LLVM_ABI Value * emitMalloc(Value *Num, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the malloc function.

LLVM_ABI Value * emitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the memchr function.

LLVM_ABI Value * emitHotColdNewAligned(Value *Num, Value *Align, IRBuilderBase &B, const TargetLibraryInfo *TLI, LibFunc NewFunc, uint8_t HotCold)

bool isSpace(char C)

Checks whether character C is whitespace in the "C" locale.

LLVM_ABI Value * emitPutS(Value *Str, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the puts function. This assumes that Str is some pointer.

LLVM_ABI Value * emitMemCCpy(Value *Ptr1, Value *Ptr2, Value *Val, Value *Len, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the memccpy function.

LLVM_ABI Value * emitHotColdSizeReturningNew(Value *Num, IRBuilderBase &B, const TargetLibraryInfo *TLI, LibFunc NewFunc, uint8_t HotCold)

LLVM_ABI Value * emitHotColdNew(Value *Num, IRBuilderBase &B, const TargetLibraryInfo *TLI, LibFunc NewFunc, uint8_t HotCold)

Emit a call to the hot/cold operator new function.

LLVM_ABI Constant * ConstantFoldLoadFromConstPtr(Constant *C, Type *Ty, APInt Offset, const DataLayout &DL)

Return the value that a load from C with offset Offset would produce if it is constant and determinab...

LLVM_ABI Value * emitStrLCpy(Value *Dest, Value *Src, Value *Size, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strlcpy function.

LLVM_ABI Value * emitHotColdSizeReturningNewAligned(Value *Num, Value *Align, IRBuilderBase &B, const TargetLibraryInfo *TLI, LibFunc NewFunc, uint8_t HotCold)

LLVM_ABI Value * emitStrCpy(Value *Dst, Value *Src, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the strcpy function to the builder, for the specified pointer arguments.

LLVM_ABI Value * emitMemPCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B, const DataLayout &DL, const TargetLibraryInfo *TLI)

Emit a call to the mempcpy function.

constexpr uint64_t NextPowerOf2(uint64_t A)

Returns the next power of two (in 64-bits) that is strictly greater than A.

This struct is a compact representation of a valid (non-zero power of two) alignment.

uint64_t Length

Length of the slice.

uint64_t Offset

Slice starts at this Offset.

const ConstantDataArray * Array

ConstantDataArray pointer.

bool isNonNegative() const

Returns true if this value is known to be non-negative.

APInt getMaxValue() const

Return the maximal unsigned value possible given these KnownBits.

bool isKnownNeverInfinity() const

Return true if it's known this can never be an infinity.

static constexpr FPClassTest OrderedLessThanZeroMask

LLVM_ABI bool isKnownNeverLogicalZero(DenormalMode Mode) const

Return true if it's know this can never be interpreted as a zero.

bool cannotBeOrderedLessThanZero() const

Return true if we can prove that the analyzed floating-point value is either NaN or never less than -...