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

1

2

3

4

5

6

7

8

9

10

11

12

13

39

40#include

41

42using namespace llvm;

43using namespace PatternMatch;

44

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

49 "shrinking for math lib calls"));

50

51

52

53

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

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

61

62namespace {

63

64

65

66

67struct HotColdHintParser : public cl::parser {

69

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

73

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

76

77 return false;

78 }

79};

80

81}

82

83

84

85

86

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

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

93 "notcold (warm) allocation"));

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

97

98

99

100

101

103 return Func == LibFunc_abs || Func == LibFunc_labs ||

104 Func == LibFunc_llabs || Func == LibFunc_strlen;

105}

106

107

109 for (User *U : V->users()) {

110 if (ICmpInst *IC = dyn_cast(U))

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

112 continue;

113

114 return false;

115 }

116 return true;

117}

118

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

122 });

123}

124

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

128 });

129}

130

131

132

133

134

135

136

137

140 if (Base < 2 || Base > 36)

141 if (Base != 0)

142

143 return nullptr;

144

145

147

149 if (!isSpace((unsigned char)Str[Offset])) {

150 Str = Str.substr(Offset);

151 break;

152 }

153

154 if (Str.empty())

155

156

157 return nullptr;

158

159

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

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

162 Str = Str.drop_front();

163 if (Str.empty())

164

165 return nullptr;

167 }

168

169

170

172 unsigned NBits = RetTy->getPrimitiveSizeInBits();

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

175

176

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

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

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

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

181

182

183 return nullptr;

184

185 Str = Str.drop_front(2);

188 }

189 else if (Base == 0)

191 } else if (Base == 0)

193 }

194 else if (Base == 0)

196

197

198

199

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

202 unsigned char DigVal = Str[i];

204 DigVal = DigVal - '0';

205 else {

206 DigVal = toUpper(DigVal);

207 if (isAlpha(DigVal))

208 DigVal = DigVal - 'A' + 10;

209 else

210 return nullptr;

211 }

212

213 if (DigVal >= Base)

214

215 return nullptr;

216

217

218

219 bool VFlow;

221 if (VFlow || Result > Max)

222 return nullptr;

223 }

224

225 if (EndPtr) {

226

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

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

230 B.CreateStore(StrEnd, EndPtr);

231 }

232

233 if (Negate)

234

235 Result = -Result;

236

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

238}

239

241 for (User *U : V->users()) {

242 if (ICmpInst *IC = dyn_cast(U))

243 if (Constant *C = dyn_cast(IC->getOperand(1)))

244 if (C->isNullValue())

245 continue;

246

247 return false;

248 }

249 return true;

250}

251

255 return false;

256

258 return false;

259

261 return false;

262

263 return true;

264}

265

268 uint64_t DereferenceableBytes) {

270 if (F)

271 return;

272 for (unsigned ArgNo : ArgNos) {

273 uint64_t DerefBytes = DereferenceableBytes;

278 DereferenceableBytes);

279

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

287 }

288 }

289}

290

294 if (F)

295 return;

296

297 for (unsigned ArgNo : ArgNos) {

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

300

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

302 unsigned AS =

305 continue;

307 }

308

310 }

311}

312

323 DerefMin = std::min(X->getZExtValue(), Y->getZExtValue());

325 }

326 }

327}

328

329

330

331

332

333

337 if (auto *NewCI = dyn_cast_or_null(New))

339 return New;

340}

341

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

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

351

353}

354

355

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

358}

359

360

361

362

363

365

369

370

372 if (Len)

374 else

375 return nullptr;

376 --Len;

377

378

379 if (Len == 0)

380 return Dst;

381

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

383}

384

387

388

390 if (!DstLen)

391 return nullptr;

392

393

394

395

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

397

398

399

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

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

402 return Dst;

403}

404

406

414

415

417 if (LengthArg) {

419

420 if (!Len)

421 return Dst;

422 } else {

423 return nullptr;

424 }

425

426

428 if (SrcLen) {

430 --SrcLen;

431 } else {

432 return nullptr;

433 }

434

435

436 if (SrcLen == 0)

437 return Dst;

438

439

440 if (Len < SrcLen)

441 return nullptr;

442

443

444

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

446}

447

448

449

450

453{

456

457

458 Type *CharTy = B.getInt8Ty();

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

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

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

462

463 if (NBytes) {

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

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

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

467 }

468

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

471}

472

477

480

481

482

483 ConstantInt *CharC = dyn_cast(CharVal);

484 if (!CharC) {

486 if (Len)

488 else

489 return nullptr;

490

493 unsigned IntBits = TLI->getIntSize();

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

495 return nullptr;

496

500 emitMemChr(SrcStr, CharVal,

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

502 DL, TLI));

503 }

504

505 if (CharC->isZero()) {

508

509

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

511 }

512

513

514

517 if (CharC->isZero())

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

520 return nullptr;

521 }

522

523

524

526 ? Str.size()

528 if (I == StringRef::npos)

530

531

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

533}

534

538 ConstantInt *CharC = dyn_cast(CharVal);

540

543

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

546 return nullptr;

547 }

548

551

552

553

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

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

557}

558

561 if (Str1P == Str2P)

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

563

567

568

569 if (HasStr1 && HasStr2)

570 return ConstantInt::get(CI->getType(),

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

572

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

574 return B.CreateNeg(B.CreateZExt(

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

576

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

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

580

581

583 if (Len1)

586 if (Len2)

588

589 if (Len1 && Len2) {

593 B, DL, TLI));

594 }

595

596

597 if (!HasStr1 && HasStr2) {

601 B, DL, TLI));

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

606 B, DL, TLI));

607 }

608

610 return nullptr;

611}

612

613

614

618

623 if (Str1P == Str2P)

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

625

628

630 if (ConstantInt *LengthArg = dyn_cast(Size))

632 else

634

635 if (Length == 0)

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

637

638 if (Length == 1)

640

644

645

646 if (HasStr1 && HasStr2) {

647

650 return ConstantInt::get(CI->getType(),

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

652 }

653

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

655 return B.CreateNeg(B.CreateZExt(

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

657

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

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

661

663 if (Len1)

666 if (Len2)

668

669

670 if (!HasStr1 && HasStr2) {

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

675 B, DL, TLI));

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

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

681 B, DL, TLI));

682 }

683

684 return nullptr;

685}

686

691 if (SrcLen && Size) {

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

695 }

696

697 return nullptr;

698}

699

702 if (Dst == Src)

703 return Src;

704

706

708 if (Len)

710 else

711 return nullptr;

712

713

714

718 return Dst;

719}

720

723

724

727

728 if (Dst == Src) {

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

731 }

732

733

735 if (Len)

737 else

738 return nullptr;

739

741 Value *DstEnd = B.CreateInBoundsGEP(

743

744

745

748 return DstEnd;

749}

750

751

752

756

757

759

760

762

765 NBytes = SizeC->getZExtValue();

766 else

767 return nullptr;

768

771 if (NBytes <= 1) {

772 if (NBytes == 1)

773

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

775

776

778 }

779

780

781

782

785 return nullptr;

786

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

788

789

790 bool NulTerm = SrcLen < NBytes;

791

792 if (NulTerm)

793

794

795 NBytes = SrcLen + 1;

796 else {

797

798

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

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

801 }

802

803 if (SrcLen == 0) {

804

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

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

807 }

808

809

810

811

815

816 if (!NulTerm) {

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

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

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

820 }

821

822

823

824

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

826}

827

828

829

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

835

837

838

841 }

842

843

844

847 N = SizeC->getZExtValue();

848

849 if (N == 0)

850

851 return Dst;

852

853 if (N == 1) {

854 Type *CharTy = B.getInt8Ty();

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

856 B.CreateStore(CharVal, Dst);

857 if (!RetEnd)

858

859 return Dst;

860

861

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

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

864

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

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

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

868 }

869

870

872 if (SrcLen)

874 else

875 return nullptr;

876

877 --SrcLen;

878

879 if (SrcLen == 0) {

880

881 Align MemSetAlign =

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

888 return Dst;

889 }

890

891 if (N > SrcLen + 1) {

892 if (N > 128)

893

894 return nullptr;

895

896

899 return nullptr;

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

901

902

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

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

905 nullptr, false);

906 }

907

908

909

913 if (!RetEnd)

914 return Dst;

915

916

917

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

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

920}

921

923 unsigned CharSize,

926 Type *CharTy = B.getIntNTy(CharSize);

927

930

931

932

933

934

935

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

938 }

939

940 if (Bound) {

941 if (ConstantInt *BoundCst = dyn_cast(Bound)) {

942 if (BoundCst->isZero())

943

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

945

946 if (BoundCst->isOne()) {

947

948 Value *CharVal = B.CreateLoad(CharTy, Src, "strnlen.char0");

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

950 Value *Cmp = B.CreateICmpNE(CharVal, ZeroChar, "strnlen.char0cmp");

951 return B.CreateZExt(Cmp, CI->getType());

952 }

953 }

954 }

955

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

958

959

960 if (Bound)

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

962 return LenC;

963 }

964

965 if (Bound)

966

967 return nullptr;

968

969

970

971

972

973

974

975

976

978

980 return nullptr;

981

985 if (Slice.Array == nullptr) {

986 NullTermIdx = 0;

987 } else {

988 NullTermIdx = ~((uint64_t)0);

991 NullTermIdx = I;

992 break;

993 }

994 }

995

996

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

998 return nullptr;

999 }

1000

1004 cast(GEP->getSourceElementType())->getNumElements();

1005

1006

1007

1008

1009

1011 (isa(GEP->getOperand(0)) &&

1012 NullTermIdx == ArrSize - 1)) {

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

1016 }

1017 }

1018 }

1019

1020

1021 if (SelectInst *SI = dyn_cast(Src)) {

1024 if (LenTrue && LenFalse) {

1025 ORE.emit([&]() {

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

1028 });

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

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

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

1032 }

1033 }

1034

1035 return nullptr;

1036}

1037

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

1040 return V;

1042 return nullptr;

1043}

1044

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

1048 return V;

1049

1052 return nullptr;

1053}

1054

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

1058

1059 if (WCharSize == 0)

1060 return nullptr;

1061

1062 return optimizeStringLength(CI, B, WCharSize);

1063}

1064

1069

1070

1071

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

1074

1075

1076 if (HasS1 && HasS2) {

1077 size_t I = S1.find_first_of(S2);

1080

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

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

1083 }

1084

1085

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

1088

1089 return nullptr;

1090}

1091

1094 if (isa(EndPtr)) {

1095

1096

1098 }

1099

1100 return nullptr;

1101}

1102

1107

1108

1109

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

1112

1113

1114 if (HasS1 && HasS2) {

1115 size_t Pos = S1.find_first_not_of(S2);

1117 Pos = S1.size();

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

1119 }

1120

1121 return nullptr;

1122}

1123

1128

1129

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

1132

1133

1134 if (HasS1 && HasS2) {

1135 size_t Pos = S1.find_first_of(S2);

1137 Pos = S1.size();

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

1139 }

1140

1141

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

1144

1145 return nullptr;

1146}

1147

1149

1152

1153

1156 if (!StrLen)

1157 return nullptr;

1159 StrLen, B, DL, TLI);

1160 if (!StrNCmp)

1161 return nullptr;

1163 ICmpInst *Old = cast(U);

1167 replaceAllUsesWith(Old, Cmp);

1168 }

1169 return CI;

1170 }

1171

1172

1176

1177

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

1180

1181

1182 if (HasStr1 && HasStr2) {

1183 size_t Offset = SearchStr.find(ToFindStr);

1184

1187

1188

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

1191 }

1192

1193

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

1196 }

1197

1199 return nullptr;

1200}

1201

1209

1210 if (LenC) {

1212

1213 return NullPtr;

1214

1215 if (LenC->isOne()) {

1216

1217

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

1219

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

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

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

1223 }

1224 }

1225

1228 return nullptr;

1229

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

1231

1232

1233

1234 return NullPtr;

1235

1237 if (LenC) {

1239 if (Str.size() < EndOff)

1240

1241 return nullptr;

1242 }

1243

1244 if (ConstantInt *CharC = dyn_cast(CharVal)) {

1245

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

1248

1249

1250 return NullPtr;

1251

1252 if (LenC)

1253

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

1255

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

1257

1258

1259

1260

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

1262 "memrchr.cmp");

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

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

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

1266 }

1267 }

1268

1269

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

1272 return nullptr;

1273

1274

1275

1276

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

1278 Type *Int8Ty = B.getInt8Ty();

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

1280

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

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

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

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

1285 Value *SrcPlus =

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

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

1288}

1289

1293

1298 }

1299

1301 ConstantInt *CharC = dyn_cast(CharVal);

1304

1305

1306 if (LenC) {

1308 return NullPtr;

1309

1310 if (LenC->isOne()) {

1311

1312

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

1314

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

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

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

1318 }

1319 }

1320

1323 return nullptr;

1324

1325 if (CharC) {

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

1328

1329

1330 return NullPtr;

1331

1332

1333

1334

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

1336 "memchr.cmp");

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

1338 "memchr.ptr");

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

1340 }

1341

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

1343

1344

1345

1346 return NullPtr;

1347

1348 if (LenC)

1350

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

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

1354

1355

1356

1357

1358

1359

1360

1361

1362

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

1364 Type *Int8Ty = B.getInt8Ty();

1365

1366

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

1368

1369 Value *Sel1 = NullPtr;

1371

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

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

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

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

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

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

1379 }

1380

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

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

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

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

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

1386 }

1387

1388 if (!LenC) {

1390

1391

1392

1394

1395

1396 return nullptr;

1397 }

1398

1401

1402

1403

1404

1405

1406

1407

1408

1409

1410

1411

1413 return nullptr;

1414

1415 unsigned char Max =

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

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

1418

1419

1420

1421

1422

1423

1425

1426

1427

1428

1429

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

1432

1433 unsigned NonContRanges = 1;

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

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

1436 NonContRanges++;

1437 }

1438 }

1439

1440

1441

1442 if (NonContRanges > 2)

1443 return nullptr;

1444

1445

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

1447

1449 for (unsigned char C : SortedStr)

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

1451

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

1453 }

1454

1455

1456

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

1458

1459

1461 for (char C : Str)

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

1464

1465

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

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

1468

1469

1471 "memchr.bounds");

1472

1473

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

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

1476

1477

1478

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

1481}

1482

1483

1484

1488 if (LHS == RHS)

1490

1494 return nullptr;

1495

1496

1497

1498

1499

1500

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

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

1504 if (Pos == MinSize ||

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

1506

1507

1508

1509

1510 return Zero;

1511 }

1512

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

1514 break;

1515 }

1516

1517

1518 typedef unsigned char UChar;

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

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

1522 Value *Res = ConstantInt::get(CI->getType(), IRes);

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

1524}

1525

1526

1530 if (Len == 0)

1532

1533

1534 if (Len == 1) {

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

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

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

1540 }

1541

1542

1543

1544

1547 Align PrefAlignment = DL.getPrefTypeAlign(IntType);

1548

1549

1550 Value *LHSV = nullptr;

1551 if (auto *LHSC = dyn_cast(LHS))

1553

1554 Value *RHSV = nullptr;

1555 if (auto *RHSC = dyn_cast(RHS))

1557

1558

1559

1562 if (!LHSV)

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

1564 if (!RHSV)

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

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

1567 }

1568 }

1569

1570 return nullptr;

1571}

1572

1573

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

1578

1580

1582 return Res;

1583

1584

1586 if (!LenC)

1587 return nullptr;

1588

1590}

1591

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

1595 return V;

1596

1597

1598

1599

1606 }

1607

1608 return nullptr;

1609}

1610

1612 return optimizeMemCmpBCmpCommon(CI, B);

1613}

1614

1618 if (isa(CI))

1619 return nullptr;

1620

1621

1626}

1627

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

1635 return Dst;

1636

1637 if (N) {

1638 if (N->isNullValue())

1641

1642 !StopChar)

1643 return nullptr;

1644 } else {

1645 return nullptr;

1646 }

1647

1648

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

1655 }

1656 return nullptr;

1657 }

1658

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

1661

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

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

1666}

1667

1671

1674

1675

1676

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

1679}

1680

1684 if (isa(CI))

1685 return nullptr;

1686

1687

1692}

1693

1697 if (isa(CI))

1698 return nullptr;

1699

1700

1705}

1706

1708 if (isa(CI->getArgOperand(0)))

1710

1711 return nullptr;

1712}

1713

1714

1715

1716

1717

1721 return nullptr;

1722

1727 "notcold")

1731 else

1732 return nullptr;

1733

1734

1735

1736

1737

1738

1739

1740

1741 switch (Func) {

1742 case LibFunc_Znwm12__hot_cold_t:

1745 LibFunc_Znwm12__hot_cold_t, HotCold);

1746 break;

1747 case LibFunc_Znwm:

1750 LibFunc_Znwm12__hot_cold_t, HotCold);

1751 break;

1752 case LibFunc_Znam12__hot_cold_t:

1755 LibFunc_Znam12__hot_cold_t, HotCold);

1756 break;

1757 case LibFunc_Znam:

1760 LibFunc_Znam12__hot_cold_t, HotCold);

1761 break;

1762 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:

1766 LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);

1767 break;

1768 case LibFunc_ZnwmRKSt9nothrow_t:

1772 LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t, HotCold);

1773 break;

1774 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:

1778 LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);

1779 break;

1780 case LibFunc_ZnamRKSt9nothrow_t:

1784 LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t, HotCold);

1785 break;

1786 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:

1790 LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);

1791 break;

1792 case LibFunc_ZnwmSt11align_val_t:

1796 LibFunc_ZnwmSt11align_val_t12__hot_cold_t, HotCold);

1797 break;

1798 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:

1802 LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);

1803 break;

1804 case LibFunc_ZnamSt11align_val_t:

1808 LibFunc_ZnamSt11align_val_t12__hot_cold_t, HotCold);

1809 break;

1810 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

1814 TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,

1815 HotCold);

1816 break;

1817 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:

1821 TLI, LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t,

1822 HotCold);

1823 break;

1824 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

1828 TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,

1829 HotCold);

1830 break;

1831 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:

1835 TLI, LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t,

1836 HotCold);

1837 break;

1838 case LibFunc_size_returning_new:

1841 LibFunc_size_returning_new_hot_cold,

1842 HotCold);

1843 break;

1844 case LibFunc_size_returning_new_hot_cold:

1847 LibFunc_size_returning_new_hot_cold,

1848 HotCold);

1849 break;

1850 case LibFunc_size_returning_new_aligned:

1854 LibFunc_size_returning_new_aligned_hot_cold, HotCold);

1855 break;

1856 case LibFunc_size_returning_new_aligned_hot_cold:

1860 LibFunc_size_returning_new_aligned_hot_cold, HotCold);

1861 break;

1862 default:

1863 return nullptr;

1864 }

1865 return nullptr;

1866}

1867

1868

1869

1870

1871

1872

1878}

1879

1880

1881

1882

1883

1884

1886 if (FPExtInst *Cast = dyn_cast(Val)) {

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

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

1889 return Op;

1890 }

1891 if (ConstantFP *Const = dyn_cast(Val)) {

1892 APFloat F = Const->getValueAPF();

1893 bool losesInfo;

1895 &losesInfo);

1896 if (!losesInfo)

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

1898 }

1899 return nullptr;

1900}

1901

1902

1905 bool isPrecise = false) {

1908 return nullptr;

1909

1910

1911

1912

1913 if (isPrecise)

1915 FPTruncInst *Cast = dyn_cast(U);

1917 return nullptr;

1918 }

1919

1920

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

1925 return nullptr;

1926

1927

1928

1929

1930

1931

1933 bool IsIntrinsic = CalleeFn->isIntrinsic();

1934 if (!IsIntrinsic) {

1936 if (!CallerName.empty() && CallerName.back() == 'f' &&

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

1939 return nullptr;

1940 }

1941

1942

1945

1946

1948 if (IsIntrinsic) {

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

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

1952 } else {

1955 CalleeAttrs)

1957 }

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

1959}

1960

1961

1964 bool isPrecise = false) {

1966}

1967

1968

1971 bool isPrecise = false) {

1973}

1974

1975

1977 Value *Real, *Imag;

1978

1980

1982 return nullptr;

1983

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

1986

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

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

1989

1990 } else {

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

1992

1995

1996

1997

1998 Value *AbsOp = nullptr;

1999 if (ConstantFP *ConstReal = dyn_cast(Real)) {

2000 if (ConstReal->isZero())

2001 AbsOp = Imag;

2002

2003 } else if (ConstantFP *ConstImag = dyn_cast(Imag)) {

2004 if (ConstImag->isZero())

2005 AbsOp = Real;

2006 }

2007

2008 if (AbsOp)

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

2011

2013 return nullptr;

2014 }

2015

2016

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

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

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

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

2022 "cabs"));

2023}

2024

2025

2026

2028 if (isa(I2F) || isa(I2F)) {

2029 Value *Op = cast(I2F)->getOperand(0);

2030

2031

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

2033 if (BitWidth < DstWidth || (BitWidth == DstWidth && isa(I2F))) {

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

2035 return isa(I2F) ? B.CreateSExt(Op, IntTy)

2036 : B.CreateZExt(Op, IntTy);

2037 }

2038 }

2039

2040 return nullptr;

2041}

2042

2043

2044

2045

2050 bool Ignored;

2051

2052

2053

2054

2055

2056

2057

2058

2059

2060

2061

2062

2063

2064

2065

2066

2067 CallInst *BaseFn = dyn_cast(Base);

2070

2077 LibFunc LibFnFloat, LibFnDouble, LibFnLongDouble;

2078

2079 switch (LibFn) {

2080 default:

2081 return nullptr;

2082 case LibFunc_expf:

2083 case LibFunc_exp:

2084 case LibFunc_expl:

2085 ExpName = TLI->getName(LibFunc_exp);

2086 ID = Intrinsic::exp;

2087 LibFnFloat = LibFunc_expf;

2088 LibFnDouble = LibFunc_exp;

2089 LibFnLongDouble = LibFunc_expl;

2090 break;

2091 case LibFunc_exp2f:

2092 case LibFunc_exp2:

2093 case LibFunc_exp2l:

2094 ExpName = TLI->getName(LibFunc_exp2);

2095 ID = Intrinsic::exp2;

2096 LibFnFloat = LibFunc_exp2f;

2097 LibFnDouble = LibFunc_exp2;

2098 LibFnLongDouble = LibFunc_exp2l;

2099 break;

2100 }

2101

2102

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

2107 LibFnLongDouble, B,

2109

2110

2111

2112

2113

2114 substituteInParent(BaseFn, ExpFn);

2115 return ExpFn;

2116 }

2117 }

2118

2119

2120

2123 return nullptr;

2124

2125 AttributeList NoAttrs;

2126

2128

2129

2131 (isa(Expo) || isa(Expo)) &&

2132 (UseIntrinsic ||

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

2134

2135

2136

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

2139

2140 if (UseIntrinsic) {

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

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

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

2144 }

2145

2147 One, ExpoI, TLI, LibFunc_ldexp, LibFunc_ldexpf,

2148 LibFunc_ldexpl, B, NoAttrs));

2149 }

2150 }

2151

2152

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

2156 BaseR = BaseR / *BaseF;

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

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

2159 APSInt NI(64, false);

2160 if ((IsInteger || IsReciprocal) &&

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

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

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

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

2168 nullptr, "exp2"));

2169 else

2171 LibFunc_exp2f,

2172 LibFunc_exp2l, B, NoAttrs));

2173 }

2174 }

2175

2176

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

2179

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

2183 return copyFlags(*Pow, NewExp10);

2184 }

2185

2187 LibFunc_exp10f, LibFunc_exp10l,

2188 B, NoAttrs));

2189 }

2190

2191

2194

2195

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

2198

2199 Value *Log = nullptr;

2201 Log = ConstantFP::get(Ty, std::log2(BaseF->convertToFloat()));

2203 Log = ConstantFP::get(Ty, std::log2(BaseF->convertToDouble()));

2204

2205 if (Log) {

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

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

2209 nullptr, "exp2"));

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

2211 LibFunc_exp2l))

2213 LibFunc_exp2f,

2214 LibFunc_exp2l, B, NoAttrs));

2215 }

2216 }

2217

2218 return nullptr;

2219}

2220

2224

2225 if (NoErrno)

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

2227

2228

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

2230 LibFunc_sqrtl))

2231

2232

2233

2235 LibFunc_sqrtl, B, Attrs);

2236

2237 return nullptr;

2238}

2239

2240

2245

2249 return nullptr;

2250

2251

2252

2254 return nullptr;

2255

2256

2257

2258

2259

2263 return nullptr;

2264

2266 TLI);

2267 if (!Sqrt)

2268 return nullptr;

2269

2270

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

2273

2275

2276

2277

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

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

2283 }

2284

2285

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

2288

2289 return Sqrt;

2290}

2291

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

2297}

2298

2307 bool Ignored;

2308

2309

2312

2313

2314

2316 return Base;

2317

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

2319 return Exp;

2320

2321

2322

2323

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

2326

2327

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

2330

2331

2333 return Base;

2334

2335

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

2338

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

2340 return Sqrt;

2341

2342

2343

2344

2350 Value *Sqrt = nullptr;

2351 if (!ExpoA.isInteger()) {

2353

2354

2355

2357 return nullptr;

2358

2360 return nullptr;

2361

2364 return nullptr;

2365 if (!ExpoI.isInteger())

2366 return nullptr;

2367 ExpoF = &ExpoI;

2368

2370 B, TLI);

2371 if (!Sqrt)

2372 return nullptr;

2373 }

2374

2375

2376

2382 *Pow,

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

2385 M, B));

2386

2387 if (PowI && Sqrt)

2388 return B.CreateFMul(PowI, Sqrt);

2389

2390 return PowI;

2391 }

2392 }

2393

2394

2395 if (AllowApprox && (isa(Expo) || isa(Expo))) {

2398 }

2399

2400

2401

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

2403 hasFloatVersion(M, Name)) {

2405 return Shrunk;

2406 }

2407

2408 return nullptr;

2409}

2410

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

2417 hasFloatVersion(M, Name))

2419

2420

2421

2422

2423

2424

2425

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

2427

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

2430 return Ret;

2431

2432

2433

2435 if ((isa(Op) || isa(Op)) &&

2436 (UseIntrinsic ||

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

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

2440

2441 if (UseIntrinsic) {

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

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

2444 {One, Exp}, CI));

2445 }

2446

2450 One, Exp, TLI, LibFunc_ldexp, LibFunc_ldexpf,

2452 }

2453 }

2454

2455 return Ret;

2456}

2457

2460

2461

2462

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

2467 return Ret;

2468

2469

2470

2471

2472

2473

2474

2475

2478

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

2480 : Intrinsic::maxnum;

2483}

2484

2491

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

2494 return Ret;

2495

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

2497

2498

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

2500 switch (LogLb) {

2501 case LibFunc_logf:

2502 LogID = Intrinsic::log;

2503 ExpLb = LibFunc_expf;

2504 Exp2Lb = LibFunc_exp2f;

2505 Exp10Lb = LibFunc_exp10f;

2506 PowLb = LibFunc_powf;

2507 break;

2508 case LibFunc_log:

2509 LogID = Intrinsic::log;

2510 ExpLb = LibFunc_exp;

2511 Exp2Lb = LibFunc_exp2;

2512 Exp10Lb = LibFunc_exp10;

2513 PowLb = LibFunc_pow;

2514 break;

2515 case LibFunc_logl:

2516 LogID = Intrinsic::log;

2517 ExpLb = LibFunc_expl;

2518 Exp2Lb = LibFunc_exp2l;

2519 Exp10Lb = LibFunc_exp10l;

2520 PowLb = LibFunc_powl;

2521 break;

2522 case LibFunc_log2f:

2523 LogID = Intrinsic::log2;

2524 ExpLb = LibFunc_expf;

2525 Exp2Lb = LibFunc_exp2f;

2526 Exp10Lb = LibFunc_exp10f;

2527 PowLb = LibFunc_powf;

2528 break;

2529 case LibFunc_log2:

2530 LogID = Intrinsic::log2;

2531 ExpLb = LibFunc_exp;

2532 Exp2Lb = LibFunc_exp2;

2533 Exp10Lb = LibFunc_exp10;

2534 PowLb = LibFunc_pow;

2535 break;

2536 case LibFunc_log2l:

2537 LogID = Intrinsic::log2;

2538 ExpLb = LibFunc_expl;

2539 Exp2Lb = LibFunc_exp2l;

2540 Exp10Lb = LibFunc_exp10l;

2541 PowLb = LibFunc_powl;

2542 break;

2543 case LibFunc_log10f:

2544 LogID = Intrinsic::log10;

2545 ExpLb = LibFunc_expf;

2546 Exp2Lb = LibFunc_exp2f;

2547 Exp10Lb = LibFunc_exp10f;

2548 PowLb = LibFunc_powf;

2549 break;

2550 case LibFunc_log10:

2551 LogID = Intrinsic::log10;

2552 ExpLb = LibFunc_exp;

2553 Exp2Lb = LibFunc_exp2;

2554 Exp10Lb = LibFunc_exp10;

2555 PowLb = LibFunc_pow;

2556 break;

2557 case LibFunc_log10l:

2558 LogID = Intrinsic::log10;

2559 ExpLb = LibFunc_expl;

2560 Exp2Lb = LibFunc_exp2l;

2561 Exp10Lb = LibFunc_exp10l;

2562 PowLb = LibFunc_powl;

2563 break;

2564 default:

2565 return nullptr;

2566 }

2567

2568

2570 if (!IsKnownNoErrno) {

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

2575 0, SQ);

2579 }

2580 if (IsKnownNoErrno) {

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

2582 NewLog->copyMetadata(*Log);

2584 }

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

2586 LogID == Intrinsic::log10) {

2588 ExpLb = LibFunc_expf;

2589 Exp2Lb = LibFunc_exp2f;

2590 Exp10Lb = LibFunc_exp10f;

2591 PowLb = LibFunc_powf;

2593 ExpLb = LibFunc_exp;

2594 Exp2Lb = LibFunc_exp2;

2595 Exp10Lb = LibFunc_exp10;

2596 PowLb = LibFunc_pow;

2597 } else

2598 return nullptr;

2599 } else

2600 return nullptr;

2601

2602

2605 return nullptr;

2606

2609

2613

2614

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

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

2622

2623 if (ArgID == Intrinsic::powi)

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

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

2626

2627

2628 substituteInParent(Arg, MulY);

2629 return MulY;

2630 }

2631

2632

2633

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

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

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

2638

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

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

2642 else

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

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

2648

2649

2650 substituteInParent(Arg, MulY);

2651 return MulY;

2652 }

2653

2654 return nullptr;

2655}

2656

2657

2660 return nullptr;

2661

2665 return nullptr;

2669

2670 LibFunc SqrtLb, ExpLb, Exp2Lb, Exp10Lb;

2671

2673 switch (SqrtLb) {

2674 case LibFunc_sqrtf:

2675 ExpLb = LibFunc_expf;

2676 Exp2Lb = LibFunc_exp2f;

2677 Exp10Lb = LibFunc_exp10f;

2678 break;

2679 case LibFunc_sqrt:

2680 ExpLb = LibFunc_exp;

2681 Exp2Lb = LibFunc_exp2;

2682 Exp10Lb = LibFunc_exp10;

2683 break;

2684 case LibFunc_sqrtl:

2685 ExpLb = LibFunc_expl;

2686 Exp2Lb = LibFunc_exp2l;

2687 Exp10Lb = LibFunc_exp10l;

2688 break;

2689 default:

2690 return nullptr;

2691 }

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

2694 ExpLb = LibFunc_expf;

2695 Exp2Lb = LibFunc_exp2f;

2696 Exp10Lb = LibFunc_exp10f;

2698 ExpLb = LibFunc_exp;

2699 Exp2Lb = LibFunc_exp2;

2700 Exp10Lb = LibFunc_exp10;

2701 } else

2702 return nullptr;

2703 } else

2704 return nullptr;

2705

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

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

2708 return nullptr;

2709

2711 B.SetInsertPoint(Arg);

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

2713 auto *FMul =

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

2715 CI, "merged.sqrt");

2716

2718 return Arg;

2719}

2720

2725

2726

2727

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

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

2732

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

2734 return Opt;

2735

2737 return Ret;

2738

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

2741 return Ret;

2742

2743

2744

2745

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

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

2748 Value *RepeatOp = nullptr;

2749 Value *OtherOp = nullptr;

2750 if (Op0 == Op1) {

2751

2752 RepeatOp = Op0;

2753 } else {

2754

2755

2756

2757

2758

2761 cast(Op0)->isFast()) {

2762

2763 RepeatOp = MulOp;

2764 OtherOp = Op1;

2766 cast(Op1)->isFast()) {

2767

2768 RepeatOp = MulOp;

2769 OtherOp = Op0;

2770 }

2771 }

2772 if (!RepeatOp)

2773 return Ret;

2774

2775

2776

2777

2778

2779

2780 Value *FabsCall =

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

2782 if (OtherOp) {

2783

2784

2785

2786 Value *SqrtCall =

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

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

2789 }

2790 return copyFlags(*CI, FabsCall);

2791}

2792

2794

2795

2796

2797

2799 if (!IsNoNan) {

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

2802 0, SQ);

2806 0, SQ);

2809 }

2810 }

2811

2812 if (IsNoNan) {

2814 if (auto *FRemI = dyn_cast(FRem))

2815 FRemI->setHasNoNaNs(true);

2816 return FRem;

2817 }

2818 return nullptr;

2819}

2820

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

2827 if (UnsafeFPShrink &&

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

2829 Name == "asinh") &&

2830 hasFloatVersion(M, Name))

2832

2834 auto *OpC = dyn_cast(Op1);

2835 if (!OpC)

2836 return Ret;

2837

2838

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

2840 return Ret;

2841

2842

2843

2844

2845

2846

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

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

2852 .Case("tan", LibFunc_atan)

2853 .Case("atanh", LibFunc_tanh)

2854 .Case("sinh", LibFunc_asinh)

2855 .Case("cosh", LibFunc_acosh)

2856 .Case("tanf", LibFunc_atanf)

2857 .Case("atanhf", LibFunc_tanhf)

2858 .Case("sinhf", LibFunc_asinhf)

2859 .Case("coshf", LibFunc_acoshf)

2860 .Case("tanl", LibFunc_atanl)

2861 .Case("atanhl", LibFunc_tanhl)

2862 .Case("sinhl", LibFunc_asinhl)

2863 .Case("coshl", LibFunc_acoshl)

2864 .Case("asinh", LibFunc_sinh)

2865 .Case("asinhf", LibFunc_sinhf)

2866 .Case("asinhl", LibFunc_sinhl)

2868 if (Func == inverseFunc)

2869 Ret = OpC->getArgOperand(0);

2870 }

2871 return Ret;

2872}

2873

2875

2876

2877

2879}

2880

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

2886 Type *ResTy;

2888

2890 if (UseFloat) {

2891 Name = "__sincospif_stret";

2892

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

2894

2895

2899 } else {

2900 Name = "__sincospi_stret";

2902 }

2903

2905 return false;

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

2910

2911 if (Instruction *ArgInst = dyn_cast(Arg)) {

2912

2913

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

2915 } else {

2916

2917

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

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

2920 }

2921

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

2923

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

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

2927 } else {

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

2929 "sinpi");

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

2931 "cospi");

2932 }

2933

2934 return true;

2935}

2936

2941

2944 Call->copyFastMathFlags(CI);

2946 if (IsEven) {

2947

2949 }

2950

2951 return B.CreateFNegFMF(CallInst, CI);

2952 }

2953

2954

2958 Call->copyFastMathFlags(CI);

2960 }

2961

2962 return nullptr;

2963}

2964

2967 switch (Func) {

2968 case LibFunc_cos:

2969 case LibFunc_cosf:

2970 case LibFunc_cosl:

2972

2973 case LibFunc_sin:

2974 case LibFunc_sinf:

2975 case LibFunc_sinl:

2976

2977 case LibFunc_tan:

2978 case LibFunc_tanf:

2979 case LibFunc_tanl:

2980

2981 case LibFunc_erf:

2982 case LibFunc_erff:

2983 case LibFunc_erfl:

2985

2986 default:

2987 return nullptr;

2988 }

2989}

2990

2992

2993

2995 return nullptr;

2996

3001

3003

3004

3005

3006

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

3010

3011

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

3013 return nullptr;

3014

3015 Value *Sin, *Cos, *SinCos;

3017 SinCos, TLI))

3018 return nullptr;

3019

3023 replaceAllUsesWith(C, Res);

3024 };

3025

3026 replaceTrigInsts(SinCalls, Sin);

3027 replaceTrigInsts(CosCalls, Cos);

3028 replaceTrigInsts(SinCosCalls, SinCos);

3029

3030 return IsSin ? Sin : Cos;

3031}

3032

3033void LibCallSimplifier::classifyArgUse(

3038 auto *CI = dyn_cast(Val);

3040 return;

3041

3042

3044 return;

3045

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

3052 return;

3053

3054 if (IsFloat) {

3055 if (Func == LibFunc_sinpif)

3057 else if (Func == LibFunc_cospif)

3059 else if (Func == LibFunc_sincospif_stret)

3061 } else {

3062 if (Func == LibFunc_sinpi)

3064 else if (Func == LibFunc_cospi)

3066 else if (Func == LibFunc_sincospi_stret)

3068 }

3069}

3070

3071

3076 return nullptr;

3077

3082 return nullptr;

3085 return nullptr;

3086

3087

3089 APSInt QuotInt(IntBW, false);

3090 bool IsExact;

3094 return nullptr;

3095

3096 B.CreateAlignedStore(

3097 ConstantInt::get(B.getIntNTy(IntBW), QuotInt.getExtValue()),

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

3100}

3101

3102

3104

3106 return nullptr;

3107

3108

3109

3114

3116

3119 return nullptr;

3120

3123

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

3127}

3128

3129

3130

3131

3132

3134

3135

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

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

3140 nullptr, "cttz");

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

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

3143

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

3146}

3147

3149

3150

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

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

3154 nullptr, "ctlz");

3156 V);

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

3158}

3159

3161

3162

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

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

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

3167}

3168

3170

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

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

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

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

3176}

3177

3179

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

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

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

3184}

3185

3187

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

3190}

3191

3192

3196 return nullptr;

3197

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

3199}

3200

3201

3203 bool AsSigned) {

3205 if (isa(EndPtr)) {

3206

3207

3209 EndPtr = nullptr;

3211 return nullptr;

3212

3215 return nullptr;

3216

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

3219 }

3220

3221 return nullptr;

3222}

3223

3224

3225

3226

3227

3229

3231 int StreamArg) {

3233

3234

3235

3236

3237

3238

3239

3240

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

3244 }

3245

3246 return nullptr;

3247}

3248

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

3251 return false;

3252

3253 if (StreamArg < 0)

3254 return true;

3255

3256

3257

3258

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

3260 return false;

3262 if (!LI)

3263 return false;

3266 return false;

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

3268}

3269

3271

3274 return nullptr;

3275

3276

3277 if (FormatStr.empty())

3279

3280

3281

3282

3284 return nullptr;

3285

3287

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

3289

3290

3291

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

3294 }

3295

3296

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

3300 return nullptr;

3301

3302 if (OperandStr.empty())

3303 return (Value *)CI;

3304

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

3306

3307

3308

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

3311 }

3312

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

3314 OperandStr = OperandStr.drop_back();

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

3317 }

3318 return nullptr;

3319 }

3320

3321

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

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

3324

3325

3326 FormatStr = FormatStr.drop_back();

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

3329 }

3330

3331

3332

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

3335

3336

3339 }

3340

3341

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

3345 return nullptr;

3346}

3347

3349

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

3354 return V;

3355 }

3356

3358

3359

3360

3364 Callee->getAttributes());

3366 New->setCalledFunction(IPrintFFn);

3367 B.Insert(New);

3368 return New;

3369 }

3370

3371

3372

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

3376 Callee->getAttributes());

3378 New->setCalledFunction(SmallPrintFFn);

3379 B.Insert(New);

3380 return New;

3381 }

3382

3383 return nullptr;

3384}

3385

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

3388

3391 return nullptr;

3392

3393

3396

3397

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

3399 return nullptr;

3400

3401

3403

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

3406 }

3407

3408

3409

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

3411 return nullptr;

3412

3413

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

3415

3417 return nullptr;

3420 B.CreateStore(V, Ptr);

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

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

3423

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

3425 }

3426

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

3428

3429

3431 return nullptr;

3432

3434

3436

3438 if (SrcLen) {

3441

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

3444

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

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

3447 }

3448

3451 return nullptr;

3452

3454 if (!Len)

3455 return nullptr;

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

3459

3460

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

3462 }

3463 return nullptr;

3464}

3465

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

3471 return V;

3472 }

3473

3475

3476

3477

3481 FT, Callee->getAttributes());

3483 New->setCalledFunction(SIPrintFFn);

3484 B.Insert(New);

3485 return New;

3486 }

3487

3488

3489

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

3493 Callee->getAttributes());

3495 New->setCalledFunction(SmallSPrintFFn);

3496 B.Insert(New);

3497 return New;

3498 }

3499

3500 return nullptr;

3501}

3502

3503

3504

3505

3506

3507

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

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

3512

3513 unsigned IntBits = TLI->getIntSize();

3515 if (Str.size() > IntMax)

3516

3517

3518

3519 return nullptr;

3520

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

3522 if (N == 0)

3523 return StrLen;

3524

3525

3526

3528 if (N > Str.size())

3529

3530

3531 NCopy = Str.size() + 1;

3532 else

3533 NCopy = N - 1;

3534

3536 if (NCopy && StrArg)

3537

3540

3541 if (N > Str.size())

3542

3543

3544 return StrLen;

3545

3546

3547 Type *Int8Ty = B.getInt8Ty();

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

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

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

3551 return StrLen;

3552}

3553

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

3556

3559 return nullptr;

3560

3563 if (N > IntMax)

3564

3565

3566 return nullptr;

3567

3570

3571

3574 return nullptr;

3575

3576

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

3579

3580

3581 return nullptr;

3582

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

3584 }

3585

3586

3587

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

3589 return nullptr;

3590

3591

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

3593 if (N <= 1) {

3594

3595

3596

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

3599 }

3600

3601

3603 return nullptr;

3606 B.CreateStore(V, Ptr);

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

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

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

3610 }

3611

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

3613 return nullptr;

3614

3616

3619 return nullptr;

3620

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

3622}

3623

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

3626 return V;

3627 }

3628

3631 return nullptr;

3632}

3633

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

3636 optimizeErrorReporting(CI, B, 0);

3637

3638

3641 return nullptr;

3642

3643

3644

3645

3647 return nullptr;

3648

3649

3651

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

3653 return nullptr;

3654

3659 }

3660

3661

3662

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

3664 return nullptr;

3665

3666

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

3668

3670 return nullptr;

3673 "chari");

3675 }

3676

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

3678

3680 return nullptr;

3683 }

3684 return nullptr;

3685}

3686

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

3692 return V;

3693 }

3694

3695

3696

3700 FT, Callee->getAttributes());

3702 New->setCalledFunction(FIPrintFFn);

3703 B.Insert(New);

3704 return New;

3705 }

3706

3707

3708

3711 auto SmallFPrintFFn =

3713 Callee->getAttributes());

3715 New->setCalledFunction(SmallFPrintFFn);

3716 B.Insert(New);

3717 return New;

3718 }

3719

3720 return nullptr;

3721}

3722

3724 optimizeErrorReporting(CI, B, 3);

3725

3726

3729 if (SizeC && CountC) {

3731

3732

3733 if (Bytes == 0)

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

3735

3736

3737

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

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

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

3744 }

3745 }

3746

3747 return nullptr;

3748}

3749

3751 optimizeErrorReporting(CI, B, 1);

3752

3753

3754

3757 return nullptr;

3758

3759

3761 return nullptr;

3762

3763

3765 if (!Len)

3766 return nullptr;

3767

3768

3772 *CI,

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

3776}

3777

3781 return nullptr;

3782

3783

3784

3787

3788

3791 }

3792

3793 return nullptr;

3794}

3795

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

3797

3798

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

3803 }

3804 return nullptr;

3805}

3806

3808

3812}

3813

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

3816 FloatFuncName += 'f';

3818}

3819

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

3825

3826

3828

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

3833 switch (Func) {

3834 case LibFunc_strcat:

3835 return optimizeStrCat(CI, Builder);

3836 case LibFunc_strncat:

3837 return optimizeStrNCat(CI, Builder);

3838 case LibFunc_strchr:

3839 return optimizeStrChr(CI, Builder);

3840 case LibFunc_strrchr:

3841 return optimizeStrRChr(CI, Builder);

3842 case LibFunc_strcmp:

3843 return optimizeStrCmp(CI, Builder);

3844 case LibFunc_strncmp:

3845 return optimizeStrNCmp(CI, Builder);

3846 case LibFunc_strcpy:

3847 return optimizeStrCpy(CI, Builder);

3848 case LibFunc_stpcpy:

3849 return optimizeStpCpy(CI, Builder);

3850 case LibFunc_strlcpy:

3851 return optimizeStrLCpy(CI, Builder);

3852 case LibFunc_stpncpy:

3853 return optimizeStringNCpy(CI, true, Builder);

3854 case LibFunc_strncpy:

3855 return optimizeStringNCpy(CI, false, Builder);

3856 case LibFunc_strlen:

3857 return optimizeStrLen(CI, Builder);

3858 case LibFunc_strnlen:

3859 return optimizeStrNLen(CI, Builder);

3860 case LibFunc_strpbrk:

3861 return optimizeStrPBrk(CI, Builder);

3862 case LibFunc_strndup:

3863 return optimizeStrNDup(CI, Builder);

3864 case LibFunc_strtol:

3865 case LibFunc_strtod:

3866 case LibFunc_strtof:

3867 case LibFunc_strtoul:

3868 case LibFunc_strtoll:

3869 case LibFunc_strtold:

3870 case LibFunc_strtoull:

3871 return optimizeStrTo(CI, Builder);

3872 case LibFunc_strspn:

3873 return optimizeStrSpn(CI, Builder);

3874 case LibFunc_strcspn:

3875 return optimizeStrCSpn(CI, Builder);

3876 case LibFunc_strstr:

3877 return optimizeStrStr(CI, Builder);

3878 case LibFunc_memchr:

3879 return optimizeMemChr(CI, Builder);

3880 case LibFunc_memrchr:

3881 return optimizeMemRChr(CI, Builder);

3882 case LibFunc_bcmp:

3883 return optimizeBCmp(CI, Builder);

3884 case LibFunc_memcmp:

3885 return optimizeMemCmp(CI, Builder);

3886 case LibFunc_memcpy:

3887 return optimizeMemCpy(CI, Builder);

3888 case LibFunc_memccpy:

3889 return optimizeMemCCpy(CI, Builder);

3890 case LibFunc_mempcpy:

3891 return optimizeMemPCpy(CI, Builder);

3892 case LibFunc_memmove:

3893 return optimizeMemMove(CI, Builder);

3894 case LibFunc_memset:

3895 return optimizeMemSet(CI, Builder);

3896 case LibFunc_realloc:

3897 return optimizeRealloc(CI, Builder);

3898 case LibFunc_wcslen:

3899 return optimizeWcslen(CI, Builder);

3900 case LibFunc_bcopy:

3901 return optimizeBCopy(CI, Builder);

3902 case LibFunc_Znwm:

3903 case LibFunc_ZnwmRKSt9nothrow_t:

3904 case LibFunc_ZnwmSt11align_val_t:

3905 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:

3906 case LibFunc_Znam:

3907 case LibFunc_ZnamRKSt9nothrow_t:

3908 case LibFunc_ZnamSt11align_val_t:

3909 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:

3910 case LibFunc_Znwm12__hot_cold_t:

3911 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:

3912 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:

3913 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

3914 case LibFunc_Znam12__hot_cold_t:

3915 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:

3916 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:

3917 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:

3918 case LibFunc_size_returning_new:

3919 case LibFunc_size_returning_new_hot_cold:

3920 case LibFunc_size_returning_new_aligned:

3921 case LibFunc_size_returning_new_aligned_hot_cold:

3922 return optimizeNew(CI, Builder, Func);

3923 default:

3924 break;

3925 }

3926 }

3927 return nullptr;

3928}

3929

3930

3934 return nullptr;

3935

3937

3938 if (CharSeq.empty())

3939 Fill = APInt(32, 0);

3941 return nullptr;

3942

3944}

3945

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

3950

3951

3953 return nullptr;

3954

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

3956 return V;

3957

3958 switch (Func) {

3959 case LibFunc_sinpif:

3960 case LibFunc_sinpi:

3961 return optimizeSinCosPi(CI, true, Builder);

3962 case LibFunc_cospif:

3963 case LibFunc_cospi:

3964 return optimizeSinCosPi(CI, false, Builder);

3965 case LibFunc_powf:

3966 case LibFunc_pow:

3967 case LibFunc_powl:

3968 return optimizePow(CI, Builder);

3969 case LibFunc_exp2l:

3970 case LibFunc_exp2:

3971 case LibFunc_exp2f:

3972 return optimizeExp2(CI, Builder);

3973 case LibFunc_fabsf:

3974 case LibFunc_fabs:

3975 case LibFunc_fabsl:

3977 case LibFunc_sqrtf:

3978 case LibFunc_sqrt:

3979 case LibFunc_sqrtl:

3980 return optimizeSqrt(CI, Builder);

3981 case LibFunc_fmod:

3982 case LibFunc_fmodf:

3983 case LibFunc_fmodl:

3984 return optimizeFMod(CI, Builder);

3985 case LibFunc_logf:

3986 case LibFunc_log:

3987 case LibFunc_logl:

3988 case LibFunc_log10f:

3989 case LibFunc_log10:

3990 case LibFunc_log10l:

3991 case LibFunc_log1pf:

3992 case LibFunc_log1p:

3993 case LibFunc_log1pl:

3994 case LibFunc_log2f:

3995 case LibFunc_log2:

3996 case LibFunc_log2l:

3997 case LibFunc_logbf:

3998 case LibFunc_logb:

3999 case LibFunc_logbl:

4000 return optimizeLog(CI, Builder);

4001 case LibFunc_tan:

4002 case LibFunc_tanf:

4003 case LibFunc_tanl:

4004 case LibFunc_sinh:

4005 case LibFunc_sinhf:

4006 case LibFunc_sinhl:

4007 case LibFunc_asinh:

4008 case LibFunc_asinhf:

4009 case LibFunc_asinhl:

4010 case LibFunc_cosh:

4011 case LibFunc_coshf:

4012 case LibFunc_coshl:

4013 case LibFunc_atanh:

4014 case LibFunc_atanhf:

4015 case LibFunc_atanhl:

4016 return optimizeTrigInversionPairs(CI, Builder);

4017 case LibFunc_ceil:

4019 case LibFunc_floor:

4021 case LibFunc_round:

4023 case LibFunc_roundeven:

4025 case LibFunc_nearbyint:

4027 case LibFunc_rint:

4029 case LibFunc_trunc:

4031 case LibFunc_acos:

4032 case LibFunc_acosh:

4033 case LibFunc_asin:

4034 case LibFunc_atan:

4035 case LibFunc_cbrt:

4036 case LibFunc_exp:

4037 case LibFunc_exp10:

4038 case LibFunc_expm1:

4039 case LibFunc_cos:

4040 case LibFunc_sin:

4041 case LibFunc_tanh:

4044 return nullptr;

4045 case LibFunc_copysign:

4048 return nullptr;

4049 case LibFunc_fdim:

4050 case LibFunc_fdimf:

4051 case LibFunc_fdiml:

4052 return optimizeFdim(CI, Builder);

4053 case LibFunc_fminf:

4054 case LibFunc_fmin:

4055 case LibFunc_fminl:

4056 case LibFunc_fmaxf:

4057 case LibFunc_fmax:

4058 case LibFunc_fmaxl:

4059 return optimizeFMinFMax(CI, Builder);

4060 case LibFunc_cabs:

4061 case LibFunc_cabsf:

4062 case LibFunc_cabsl:

4063 return optimizeCAbs(CI, Builder);

4064 case LibFunc_remquo:

4065 case LibFunc_remquof:

4066 case LibFunc_remquol:

4067 return optimizeRemquo(CI, Builder);

4068 case LibFunc_nan:

4069 case LibFunc_nanf:

4070 case LibFunc_nanl:

4072 default:

4073 return nullptr;

4074 }

4075}

4076

4080

4081

4082

4083

4085 return nullptr;

4086

4090

4093

4096

4097

4098

4099

4102 else if (isa(CI) && CI->isFast())

4103 UnsafeFPShrink = true;

4104

4105

4107 if (!IsCallingConvC)

4108 return nullptr;

4109

4110

4111 switch (II->getIntrinsicID()) {

4112 case Intrinsic::pow:

4113 return optimizePow(CI, Builder);

4114 case Intrinsic::exp2:

4115 return optimizeExp2(CI, Builder);

4116 case Intrinsic:🪵

4117 case Intrinsic::log2:

4118 case Intrinsic::log10:

4119 return optimizeLog(CI, Builder);

4120 case Intrinsic::sqrt:

4121 return optimizeSqrt(CI, Builder);

4122 case Intrinsic::memset:

4123 return optimizeMemSet(CI, Builder);

4124 case Intrinsic::memcpy:

4125 return optimizeMemCpy(CI, Builder);

4126 case Intrinsic::memmove:

4127 return optimizeMemMove(CI, Builder);

4128 default:

4129 return nullptr;

4130 }

4131 }

4132

4133

4134 if (Value *SimplifiedFortifiedCI =

4135 FortifiedSimplifier.optimizeCall(CI, Builder))

4136 return SimplifiedFortifiedCI;

4137

4138

4140

4142 return nullptr;

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

4144 return V;

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

4146 return V;

4147 switch (Func) {

4148 case LibFunc_ffs:

4149 case LibFunc_ffsl:

4150 case LibFunc_ffsll:

4151 return optimizeFFS(CI, Builder);

4152 case LibFunc_fls:

4153 case LibFunc_flsl:

4154 case LibFunc_flsll:

4155 return optimizeFls(CI, Builder);

4156 case LibFunc_abs:

4157 case LibFunc_labs:

4158 case LibFunc_llabs:

4159 return optimizeAbs(CI, Builder);

4160 case LibFunc_isdigit:

4161 return optimizeIsDigit(CI, Builder);

4162 case LibFunc_isascii:

4163 return optimizeIsAscii(CI, Builder);

4164 case LibFunc_toascii:

4165 return optimizeToAscii(CI, Builder);

4166 case LibFunc_atoi:

4167 case LibFunc_atol:

4168 case LibFunc_atoll:

4169 return optimizeAtoi(CI, Builder);

4170 case LibFunc_strtol:

4171 case LibFunc_strtoll:

4172 return optimizeStrToInt(CI, Builder, true);

4173 case LibFunc_strtoul:

4174 case LibFunc_strtoull:

4175 return optimizeStrToInt(CI, Builder, false);

4176 case LibFunc_printf:

4177 return optimizePrintF(CI, Builder);

4178 case LibFunc_sprintf:

4179 return optimizeSPrintF(CI, Builder);

4180 case LibFunc_snprintf:

4181 return optimizeSnPrintF(CI, Builder);

4182 case LibFunc_fprintf:

4183 return optimizeFPrintF(CI, Builder);

4184 case LibFunc_fwrite:

4185 return optimizeFWrite(CI, Builder);

4186 case LibFunc_fputs:

4187 return optimizeFPuts(CI, Builder);

4188 case LibFunc_puts:

4189 return optimizePuts(CI, Builder);

4190 case LibFunc_perror:

4191 return optimizeErrorReporting(CI, Builder);

4192 case LibFunc_vfprintf:

4193 case LibFunc_fiprintf:

4194 return optimizeErrorReporting(CI, Builder, 0);

4195 case LibFunc_exit:

4196 case LibFunc_Exit:

4197 return optimizeExit(CI);

4198 default:

4199 return nullptr;

4200 }

4201 }

4202 return nullptr;

4203}

4204

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

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

4213

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

4215

4216 Replacer(I, With);

4217}

4218

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

4220 Eraser(I);

4221}

4222

4223

4224

4225

4226

4227

4228

4229

4230

4231

4232

4233

4234

4235

4236

4237

4238

4239

4240

4241

4242

4243

4244

4245

4246

4247

4248

4249

4250

4251

4252

4253

4254

4255

4256

4257

4258bool FortifiedLibCallSimplifier::isFortifiedCallFoldable(

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

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

4261

4262

4263 if (FlagOp) {

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

4266 return false;

4267 }

4268

4270 return true;

4271

4273 dyn_cast(CI->getArgOperand(ObjSizeOp))) {

4274 if (ObjSizeCI->isMinusOne())

4275 return true;

4276

4277 if (OnlyLowerUnknownSize)

4278 return false;

4279 if (StrOp) {

4281

4282

4283 if (Len)

4285 else

4286 return false;

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

4288 }

4289

4290 if (SizeOp) {

4292 dyn_cast(CI->getArgOperand(*SizeOp)))

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

4294 }

4295 }

4296 return false;

4297}

4298

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

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

4307 }

4308 return nullptr;

4309}

4310

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

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

4319 }

4320 return nullptr;

4321}

4322

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

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

4331 }

4332 return nullptr;

4333}

4334

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

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

4342 }

4343 return nullptr;

4344}

4345

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

4352

4353

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

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

4357 }

4358

4359

4360

4361

4362

4363

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

4365 if (Func == LibFunc_strcpy_chk)

4367 else

4369 }

4370

4371 if (OnlyLowerUnknownSize)

4372 return nullptr;

4373

4374

4376 if (Len)

4378 else

4379 return nullptr;

4380

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

4385

4386

4387 if (Ret && Func == LibFunc_stpcpy_chk)

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

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

4390 return copyFlags(*CI, cast(Ret));

4391}

4392

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

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

4398 return nullptr;

4399}

4400

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

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

4405 if (Func == LibFunc_strncpy_chk)

4409 else

4413 }

4414

4415 return nullptr;

4416}

4417

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

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

4424

4425 return nullptr;

4426}

4427

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

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

4435 }

4436

4437 return nullptr;

4438}

4439

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

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

4446 VariadicArgs, B, TLI));

4447 }

4448

4449 return nullptr;

4450}

4451

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

4454 if (isFortifiedCallFoldable(CI, 2))

4457

4458 return nullptr;

4459}

4460

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

4463 if (isFortifiedCallFoldable(CI, 3))

4467

4468 return nullptr;

4469}

4470

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

4473 if (isFortifiedCallFoldable(CI, 3))

4477

4478 return nullptr;

4479}

4480

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

4483 if (isFortifiedCallFoldable(CI, 3))

4487

4488 return nullptr;

4489}

4490

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

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

4497

4498 return nullptr;

4499}

4500

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

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

4507

4508 return nullptr;

4509}

4510

4513

4514

4515

4516

4517

4518

4519

4520

4521

4522

4523

4524

4525

4529

4532

4535

4536

4537

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

4539 return nullptr;

4540

4541

4543 return nullptr;

4544

4545 switch (Func) {

4546 case LibFunc_memcpy_chk:

4547 return optimizeMemCpyChk(CI, Builder);

4548 case LibFunc_mempcpy_chk:

4549 return optimizeMemPCpyChk(CI, Builder);

4550 case LibFunc_memmove_chk:

4551 return optimizeMemMoveChk(CI, Builder);

4552 case LibFunc_memset_chk:

4553 return optimizeMemSetChk(CI, Builder);

4554 case LibFunc_stpcpy_chk:

4555 case LibFunc_strcpy_chk:

4556 return optimizeStrpCpyChk(CI, Builder, Func);

4557 case LibFunc_strlen_chk:

4558 return optimizeStrLenChk(CI, Builder);

4559 case LibFunc_stpncpy_chk:

4560 case LibFunc_strncpy_chk:

4561 return optimizeStrpNCpyChk(CI, Builder, Func);

4562 case LibFunc_memccpy_chk:

4563 return optimizeMemCCpyChk(CI, Builder);

4564 case LibFunc_snprintf_chk:

4565 return optimizeSNPrintfChk(CI, Builder);

4566 case LibFunc_sprintf_chk:

4567 return optimizeSPrintfChk(CI, Builder);

4568 case LibFunc_strcat_chk:

4569 return optimizeStrCatChk(CI, Builder);

4570 case LibFunc_strlcat_chk:

4571 return optimizeStrLCat(CI, Builder);

4572 case LibFunc_strncat_chk:

4573 return optimizeStrNCatChk(CI, Builder);

4574 case LibFunc_strlcpy_chk:

4575 return optimizeStrLCpyChk(CI, Builder);

4576 case LibFunc_vsnprintf_chk:

4577 return optimizeVSNPrintfChk(CI, Builder);

4578 case LibFunc_vsprintf_chk:

4579 return optimizeVSPrintfChk(CI, Builder);

4580 default:

4581 break;

4582 }

4583 return nullptr;

4584}

4585

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

This file implements the APSInt class, which is a simple class that represents an arbitrary sized int...

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")

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

uint64_t IntrinsicInst * II

static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")

static bool isBinary(MachineInstr &MI)

const SmallVectorImpl< MachineOperand > & Cond

static bool isDigit(const char C)

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

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

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

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

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

static bool insertSinCosCall(IRBuilderBase &B, Function *OrigCallee, Value *Arg, bool UseFloat, Value *&Sin, Value *&Cos, Value *&SinCos, const TargetLibraryInfo *TLI)

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

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

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

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

Shrink double -> float for binary functions.

static bool ignoreCallingConv(LibFunc Func)

static cl::opt< bool > OptimizeExistingHotColdNew("optimize-existing-hot-cold-new", cl::Hidden, cl::init(false), cl::desc("Enable optimization of existing hot/cold operator new library calls"))

static void annotateDereferenceableBytes(CallInst *CI, ArrayRef< unsigned > ArgNos, uint64_t DereferenceableBytes)

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

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

Shrink double -> float functions.

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

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

static Value * valueHasFloatPrecision(Value *Val)

Return a variant of Val with float type.

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

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

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

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

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

static StringRef substr(StringRef Str, uint64_t Len)

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

static bool isTrigLibCall(CallInst *CI)

static Value * optimizeNaN(CallInst *CI)

Constant folding nan/nanf/nanl.

static bool isOnlyUsedInComparisonWithZero(Value *V)

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

static bool callHasFloatingPointArgument(const CallInst *CI)

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

Shrink double -> float for unary functions.

static bool callHasFP128Argument(const CallInst *CI)

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

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

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

static cl::opt< bool > EnableUnsafeFPShrink("enable-double-float-shrink", cl::Hidden, cl::init(false), cl::desc("Enable unsafe double to float " "shrinking for math lib calls"))

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

This file defines the SmallString class.

opStatus divide(const APFloat &RHS, roundingMode RM)

bool isFiniteNonZero() const

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

opStatus subtract(const APFloat &RHS, roundingMode RM)

double convertToDouble() const

Converts this APFloat to host double value.

bool isExactlyValue(double V) const

We don't rely on operator== working on double values, as it returns true for things that are clearly ...

opStatus add(const APFloat &RHS, roundingMode RM)

const fltSemantics & getSemantics() const

float convertToFloat() const

Converts this APFloat to host float value.

opStatus remainder(const APFloat &RHS)

opStatus convertToInteger(MutableArrayRef< integerPart > Input, unsigned int Width, bool IsSigned, roundingMode RM, bool *IsExact) const

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.

An arbitrary precision integer that knows its signedness.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

A cache of @llvm.assume calls within a function.

static AttributeList get(LLVMContext &C, ArrayRef< std::pair< unsigned, Attribute > > Attrs)

Create an AttributeList with the specified parameters in it.

Attribute getFnAttr(Attribute::AttrKind Kind) const

Return the attribute object that exists for the function.

AttributeSet getParamAttrs(unsigned ArgNo) const

The attributes for the argument or parameter at the given index are returned.

AttributeList addParamAttributes(LLVMContext &C, unsigned ArgNo, const AttrBuilder &B) const

Add an argument attribute to the list.

MaybeAlign getAlignment() const

static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes)

StringRef getValueAsString() const

Return the attribute's value as a string.

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...

void addFnAttr(Attribute::AttrKind Kind)

Adds the attribute to the function.

void removeParamAttrs(unsigned ArgNo, const AttributeMask &AttrsToRemove)

Removes the attributes from the given argument.

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

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

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.

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

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

uint64_t getElementAsInteger(unsigned 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 Constant * getInfinity(Type *Ty, bool Negative=false)

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

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 Constant * getNullValue(Type *Ty)

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

This class represents an Operation in the Expression.

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

bool fitsInLegalInteger(unsigned Width) const

Returns true if the specified type fits in a native integer type supported by the CPU.

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.

Convenience struct for specifying and reasoning about fast-math flags.

void setNoSignedZeros(bool B=true)

static FastMathFlags getFast()

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

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

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

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

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.

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.

void setDefaultOperandBundles(ArrayRef< OperandBundleDef > OpBundles)

Instruction * clone() const

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

bool hasNoNaNs() const LLVM_READONLY

Determine whether the no-NaNs flag is set.

bool hasNoInfs() const LLVM_READONLY

Determine whether the no-infs flag is set.

bool hasNoSignedZeros() const LLVM_READONLY

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

const Module * getModule() const

Return the module owning the function this instruction belongs to or nullptr it the function does not...

bool isFast() const LLVM_READONLY

Determine whether all fast-math-flags are set.

const Function * getFunction() const

Return the function this instruction belongs to.

FastMathFlags getFastMathFlags() const LLVM_READONLY

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

bool hasApproxFunc() const LLVM_READONLY

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

bool hasAllowReassoc() const LLVM_READONLY

Determine whether the allow-reassociation flag is set.

const DataLayout & getDataLayout() const

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

Class to represent integer types.

static 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)

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

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

An instruction for reading from memory.

Value * getPointerOperand()

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

const std::string & getTargetTriple() const

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

Analysis providing profile information.

This class represents the LLVM 'select' instruction.

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

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.

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.

static constexpr size_t npos

int compare(StringRef RHS) const

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

StringRef drop_back(size_t N=1) const

Return a StringRef equal to 'this' but with the last N elements dropped.

A switch()-like statement whose cases are string literals.

StringSwitch & Case(StringLiteral S, T Value)

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

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

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

unsigned getWCharSize(const Module &M) const

Returns the size of the wchar_t type in bytes or 0 if the size is unknown.

ConstantInt * getAsSizeT(uint64_t V, const Module &M) const

Returns a constant materialized as a size_t type.

unsigned getSizeTSize(const Module &M) const

Returns the size of the size_t type in bits.

bool getLibFunc(StringRef funcName, LibFunc &F) const

Searches for a particular function name.

StringRef getName(LibFunc F) const

unsigned getIntSize() const

Get size of a C-level int or unsigned int, in bits.

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.

unsigned getIntegerBitWidth() const

const fltSemantics & getFltSemantics() 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.

unsigned getPointerAddressSpace() const

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

bool isStructTy() const

True if this is an instance of StructType.

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.

Type * getScalarType() const

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

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

LLVMContext & getContext() const

All values hold a context through their type.

StringRef getName() const

Return a constant reference to the value's name.

void takeName(Value *V)

Transfer the name from V to this value.

int getNumOccurrences() const

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

const ParentTy * getParent() const

AttributeMask typeIncompatible(Type *Ty, AttributeSet AS, AttributeSafetyKind ASK=ASK_ALL)

Which attributes cannot be applied to a type.

@ C

The default llvm calling convention, compatible with C.

unsigned ID

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

Flag

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

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.

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

OneUse_match< T > m_OneUse(const T &SubPattern)

specific_fpval m_FPOne()

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

apint_match m_APInt(const APInt *&Res)

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

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

apfloat_match m_APFloat(const APFloat *&Res)

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

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

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

initializer< Ty > init(const Ty &Val)

NodeAddr< FuncNode * > Func

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.

int64_t maxIntN(int64_t N)

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

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.

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.

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

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

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.

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.

bool isOnlyUsedInZeroEqualityComparison(const Instruction *CxtI)

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

bool isKnownNeverInfinity(const Value *V, unsigned Depth, const SimplifyQuery &SQ)

Return true if the floating-point scalar value is not an infinity or if the floating-point vector val...

APFloat abs(APFloat X)

Returns the absolute value of the argument.

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.

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.

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

Emit a call to the sprintf function.

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.

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.

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

Emit a call to the strlcat function.

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

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.

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

Emit a call to the strncat function.

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

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

Emit a call to the vsnprintf function.

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.

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.

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

Emit a call to the memcmp function.

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.

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

Emit a call to the fputs function.

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

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

void sort(IteratorTy Start, IteratorTy End)

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

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

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

Emit a call to the bcmp function.

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.

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

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

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

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.

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

Emit a call to the fputc function.

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.

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

Emit a call to the strcat function.

Value * emitVSPrintf(Value *Dest, Value *Fmt, Value *VAList, IRBuilderBase &B, const TargetLibraryInfo *TLI)

Emit a call to the vsprintf function.

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.

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

Emit a call to the fwrite function.

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.

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.

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

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

DWARFExpression::Operation Op

@ NearestTiesToEven

roundTiesToEven.

constexpr unsigned BitWidth

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

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

Emit a call to the malloc function.

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

Emit a call to the memchr function.

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

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

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

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

Emit a call to the memccpy function.

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

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

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

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

bool isGEPBasedOnPointerToString(const GEPOperator *GEP, unsigned CharSize=8)

Returns true if the GEP is based on a pointer to a string (array of.

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

Emit a call to the strlcpy function.

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

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.

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

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

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

Emit a call to the mempcpy function.

uint64_t maxUIntN(uint64_t N)

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

constexpr uint64_t NextPowerOf2(uint64_t A)

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

static const fltSemantics & IEEEsingle() LLVM_READNONE

static constexpr roundingMode rmTowardNegative

static constexpr roundingMode rmNearestTiesToEven

static constexpr roundingMode rmTowardZero

opStatus

IEEE-754R 7: Default exception handling.

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

Holds functions to get, set or test bitfields.

Represents offset+length into a ConstantDataArray.

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

bool isKnownNeverLogicalZero(const Function &F, Type *Ty) 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 -...

Align valueOrOne() const

For convenience, returns a valid alignment or 1 if undefined.