LLVM: lib/Transforms/Scalar/MemCpyOptimizer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

58#include

59#include

60#include

61#include

62

63using namespace llvm;

64

65#define DEBUG_TYPE "memcpyopt"

66

68 "enable-memcpyopt-without-libcalls", cl::Hidden,

69 cl::desc("Enable memcpyopt even when libcalls are disabled"));

70

71STATISTIC(NumMemCpyInstr, "Number of memcpy instructions deleted");

72STATISTIC(NumMemMoveInstr, "Number of memmove instructions deleted");

73STATISTIC(NumMemSetInfer, "Number of memsets inferred");

74STATISTIC(NumMoveToCpy, "Number of memmoves converted to memcpy");

75STATISTIC(NumCpyToSet, "Number of memcpys converted to memset");

76STATISTIC(NumCallSlot, "Number of call slot optimizations performed");

77STATISTIC(NumStackMove, "Number of stack-move optimizations performed");

78

79namespace {

80

81

82

83

84

85

86

87

88

89

90

91struct MemsetRange {

92

93

94 int64_t Start, End;

95

96

97

99

100

102

103

105

106 bool isProfitableToUseMemset(const DataLayout &DL) const;

107};

108

109}

110

113

114bool MemsetRange::isProfitableToUseMemset(const DataLayout &DL) const {

115

116 if (TheStores.size() >= 4 || End - Start >= 16)

117 return true;

118

119

120 if (TheStores.size() < 2)

121 return false;

122

123

124

125 for (Instruction *SI : TheStores)

127 return true;

128

129

130

131 if (TheStores.size() == 2)

132 return false;

133

134

135

136

137

138

139

140

141

142

143

144 unsigned Bytes = unsigned(End - Start);

145 unsigned MaxIntSize = DL.getLargestLegalIntTypeSizeInBits() / 8;

146 if (MaxIntSize == 0)

147 MaxIntSize = 1;

148 unsigned NumPointerStores = Bytes / MaxIntSize;

149

150

151 unsigned NumByteStores = Bytes % MaxIntSize;

152

153

154

155

156 return TheStores.size() > NumPointerStores + NumByteStores;

157}

158

159namespace {

160

161class MemsetRanges {

163

164

166

167 const DataLayout &DL;

168

169public:

170 MemsetRanges(const DataLayout &DL) : DL(DL) {}

171

173

174 const_iterator begin() const { return Ranges.begin(); }

175 const_iterator end() const { return Ranges.end(); }

176 bool empty() const { return Ranges.empty(); }

177

178 void addInst(int64_t OffsetFromFirst, Instruction *Inst) {

180 addStore(OffsetFromFirst, SI);

181 else

183 }

184

185 void addStore(int64_t OffsetFromFirst, StoreInst *SI) {

186 TypeSize StoreSize = DL.getTypeStoreSize(SI->getOperand(0)->getType());

187 assert(!StoreSize.isScalable() && "Can't track scalable-typed stores");

189 SI->getPointerOperand(), SI->getAlign(), SI);

190 }

191

192 void addMemSet(int64_t OffsetFromFirst, MemSetInst *MSI) {

195 }

196

197 void addRange(int64_t Start, int64_t Size, Value *Ptr, MaybeAlign Alignment,

198 Instruction *Inst);

199};

200

201}

202

203

204

205

206void MemsetRanges::addRange(int64_t Start, int64_t Size, Value *Ptr,

207 MaybeAlign Alignment, Instruction *Inst) {

209

211 Ranges, [=](const MemsetRange &O) { return O.End < Start; });

212

213

214

215

216 if (I == Ranges.end() || End < I->Start) {

217 MemsetRange &R = *Ranges.insert(I, MemsetRange());

219 R.End = End;

220 R.StartPtr = Ptr;

221 R.Alignment = Alignment;

222 R.TheStores.push_back(Inst);

223 return;

224 }

225

226

227 I->TheStores.push_back(Inst);

228

229

230

231 if (I->Start <= Start && I->End >= End)

232 return;

233

234

235

236

237

238

239

240 if (Start < I->Start) {

242 I->StartPtr = Ptr;

243 I->Alignment = Alignment;

244 }

245

246

247

248

249 if (End > I->End) {

250 I->End = End;

251 range_iterator NextI = I;

252 while (++NextI != Ranges.end() && End >= NextI->Start) {

253

254 I->TheStores.append(NextI->TheStores.begin(), NextI->TheStores.end());

255 if (NextI->End > I->End)

256 I->End = NextI->End;

258 NextI = I;

259 }

260 }

261}

262

263

264

265

266

267

268

271 assert(Start->getParent() == End->getParent() && "Must be in same block");

272

273 if (Start->getFunction()->doesNotThrow())

274 return false;

275

276

277

278 bool RequiresNoCaptureBeforeUnwind;

280 RequiresNoCaptureBeforeUnwind) &&

281 !RequiresNoCaptureBeforeUnwind)

282 return false;

283

284

286 [](const Instruction &I) { return I.mayThrow(); });

287}

288

289void MemCpyOptPass::eraseInstruction(Instruction *I) {

290 MSSAU->removeMemoryAccess(I);

291 EEA->removeInstruction(I);

292 I->eraseFromParent();

293}

294

295

296

297

298

302 Instruction **SkippedLifetimeStart = nullptr) {

303 assert(Start->getBlock() == End->getBlock() && "Only local supported");

309 if (II && II->getIntrinsicID() == Intrinsic::lifetime_start &&

310 SkippedLifetimeStart && !*SkippedLifetimeStart) {

311 *SkippedLifetimeStart = I;

312 continue;

313 }

314

315 return true;

316 }

317 }

318 return false;

319}

320

321

322

327

328

329

330 return Start->getBlock() != End->getBlock() ||

334 if (isa(&Acc))

335 return false;

336 Instruction *AccInst =

337 cast(&Acc)->getMemoryInst();

338 return isModSet(AA.getModRefInfo(AccInst, Loc));

339 });

340 }

341

342

345 return !MSSA->dominates(Clobber, Start);

346}

347

348

349

350

351

352Instruction *MemCpyOptPass::tryMergingIntoMemset(Instruction *StartInst,

354 Value *ByteVal) {

356

357

359 if (DL.getTypeStoreSize(SI->getOperand(0)->getType()).isScalable())

360 return nullptr;

361

362

363

364

365

367

369

370

371

372

373 MemoryUseOrDef *MemInsertPoint = nullptr;

374 for (++BI; !BI->isTerminator(); ++BI) {

375 auto *CurrentAcc =

377 if (CurrentAcc)

378 MemInsertPoint = CurrentAcc;

379

380

381

383 if (CB->onlyAccessesInaccessibleMemory())

384 continue;

385 }

386

388

389

390

391 if (BI->mayWriteToMemory() || BI->mayReadFromMemory())

392 break;

393 continue;

394 }

395

397

398 if (!NextStore->isSimple())

399 break;

400

401 Value *StoredVal = NextStore->getValueOperand();

402

403

404

406 break;

407

408

409 if (DL.getTypeStoreSize(StoredVal->getType()).isScalable())

410 break;

411

412

415 ByteVal = StoredByte;

416 if (ByteVal != StoredByte)

417 break;

418

419

420 std::optional<int64_t> Offset =

423 break;

424

426 } else {

428

429 if (MSI->isVolatile() || ByteVal != MSI->getValue() ||

431 break;

432

433

434 std::optional<int64_t> Offset =

435 MSI->getDest()->getPointerOffsetFrom(StartPtr, DL);

437 break;

438

440 }

441 }

442

443

444

446 return nullptr;

447

448

449

450

451 Ranges.addInst(0, StartInst);

452

453

454

455

457

458

459

461 for (const MemsetRange &Range : Ranges) {

462 if (Range.TheStores.size() == 1)

463 continue;

464

465

466 if (Range.isProfitableToUseMemset(DL))

467 continue;

468

469

470

471 StartPtr = Range.StartPtr;

472

473 AMemSet = Builder.CreateMemSet(StartPtr, ByteVal, Range.End - Range.Start,

474 Range.Alignment);

476

477 LLVM_DEBUG(dbgs() << "Replace stores:\n"; for (Instruction *SI

479 << *SI << '\n';

480 dbgs() << "With: " << *AMemSet << '\n');

481 if (Range.TheStores.empty())

483

486 ? MSSAU->createMemoryAccessBefore(AMemSet, nullptr, MemInsertPoint)

487 : MSSAU->createMemoryAccessAfter(AMemSet, nullptr, MemInsertPoint));

488 MSSAU->insertDef(NewDef, true);

489 MemInsertPoint = NewDef;

490

491

492 for (Instruction *SI : Range.TheStores)

494

495 ++NumMemSetInfer;

496 }

497

498 return AMemSet;

499}

500

501

502

503

504

505bool MemCpyOptPass::moveUp(StoreInst *SI, Instruction *P, const LoadInst *LI) {

506

509 return false;

510

511

512

513 DenseSet<Instruction *> Args;

514 auto AddArg = [&](Value *Arg) {

516 if (I && I->getParent() == SI->getParent()) {

517

518 if (I == P)

519 return false;

521 }

522 return true;

523 };

524 if (!AddArg(SI->getPointerOperand()))

525 return false;

526

527

528 SmallVector<Instruction *, 8> ToLift{SI};

529

530

532

533

535

537

538 for (auto I = --SI->getIterator(), E = P->getIterator(); I != E; --I) {

539 auto *C = &*I;

540

541

542

544 return false;

545

546 bool MayAlias = isModOrRefSet(AA->getModRefInfo(C, std::nullopt));

547

548 bool NeedLift = false;

549 if (Args.erase(C))

550 NeedLift = true;

551 else if (MayAlias) {

552 NeedLift = llvm::any_of(MemLocs, [C, this](const MemoryLocation &ML) {

554 });

555

556 if (!NeedLift)

559 });

560 }

561

562 if (!NeedLift)

563 continue;

564

565 if (MayAlias) {

566

567

568 if (isModSet(AA->getModRefInfo(C, LoadLoc)))

569 return false;

571

573 return false;

574

577

580 return false;

581

583 } else

584

585 return false;

586 }

587

589 for (Value *Op : C->operands())

590 if (!AddArg(Op))

591 return false;

592 }

593

594

595

596

597

598

599

600

601 MemoryUseOrDef *MemInsertPoint = nullptr;

602 if (MemoryUseOrDef *MA = MSSA->getMemoryAccess(P)) {

604 } else {

608 if (MemoryUseOrDef *MA = MSSA->getMemoryAccess(&I)) {

609 MemInsertPoint = MA;

610 break;

611 }

612 }

613 }

614

615

617 LLVM_DEBUG(dbgs() << "Lifting " << *I << " before " << *P << "\n");

618 I->moveBefore(P->getIterator());

619 assert(MemInsertPoint && "Must have found insert point");

620 if (MemoryUseOrDef *MA = MSSA->getMemoryAccess(I)) {

621 MSSAU->moveAfter(MA, MemInsertPoint);

622 MemInsertPoint = MA;

623 }

624 }

625

626 return true;

627}

628

629bool MemCpyOptPass::processStoreOfLoad(StoreInst *SI, LoadInst *LI,

630 const DataLayout &DL,

633 return false;

634

635 BatchAAResults BAA(*AA, EEA);

637

638

639

640

641 if (T->isAggregateType() &&

643 (TLI->has(LibFunc_memcpy) && TLI->has(LibFunc_memmove)))) {

645

646

647

648

649

650

653 if (isModSet(BAA.getModRefInfo(&I, LoadLoc))) {

654 P = &I;

655 break;

656 }

657 }

658

659

660

661

662

663 if (P == SI || moveUp(SI, P, LI)) {

664

665

666

667

668 bool UseMemMove = false;

669 if (isModSet(AA->getModRefInfo(SI, LoadLoc)))

670 UseMemMove = true;

671

674 Builder.CreateTypeSize(Builder.getInt64Ty(), DL.getTypeStoreSize(T));

676 if (UseMemMove)

677 M = Builder.CreateMemMove(SI->getPointerOperand(), SI->getAlign(),

680 else

681 M = Builder.CreateMemCpy(SI->getPointerOperand(), SI->getAlign(),

683 M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);

684

685 LLVM_DEBUG(dbgs() << "Promoting " << *LI << " to " << *SI << " => " << *M

686 << "\n");

687

688 auto *LastDef = cast(MSSA->getMemoryAccess(SI));

689 auto *NewAccess = MSSAU->createMemoryAccessAfter(M, nullptr, LastDef);

690 MSSAU->insertDef(cast(NewAccess), true);

691

694 ++NumMemCpyInstr;

695

696

697 BBI = M->getIterator();

698 return true;

699 }

700 }

701

702

703

704

705 auto GetCall = [&]() -> CallInst * {

706

707

709 MSSA->getWalker()->getClobberingMemoryAccess(LI, BAA)))

711 return nullptr;

712 };

713

714 bool Changed = performCallSlotOptzn(

715 LI, SI, SI->getPointerOperand()->stripPointerCasts(),

717 DL.getTypeStoreSize(SI->getOperand(0)->getType()),

718 std::min(SI->getAlign(), LI->getAlign()), BAA, GetCall);

722 ++NumMemCpyInstr;

723 return true;

724 }

725

726

727

728

731 if (performStackMoveOptzn(LI, SI, DestAlloca, SrcAlloca,

732 DL.getTypeStoreSize(T), BAA)) {

733

734 BBI = SI->getNextNode()->getIterator();

737 ++NumMemCpyInstr;

738 return true;

739 }

740 }

741 }

742

743 return false;

744}

745

747 if (SI->isSimple())

748 return false;

749

750

751

752

753

754

755

756 if (SI->getMetadata(LLVMContext::MD_nontemporal))

757 return false;

758

759 const DataLayout &DL = SI->getDataLayout();

760

761 Value *StoredVal = SI->getValueOperand();

762

763

764

766 return false;

767

768

770 return processStoreOfLoad(SI, LI, DL, BBI);

771

772

773

774

775

777 return false;

778

779

780

781

782

783

784

785 Value *V = SI->getOperand(0);

787 if (!ByteVal)

788 return false;

789

790 if (Instruction *I =

791 tryMergingIntoMemset(SI, SI->getPointerOperand(), ByteVal)) {

792 BBI = I->getIterator();

793 return true;

794 }

795

796

797

798

799 auto *T = V->getType();

800 if (T->isAggregateType())

801 return false;

802

803 TypeSize Size = DL.getTypeStoreSize(T);

804 if (Size.isScalable())

805 return false;

806

808 auto *M = Builder.CreateMemSet(SI->getPointerOperand(), ByteVal, Size,

809 SI->getAlign());

810 M->copyMetadata(*SI, LLVMContext::MD_DIAssignID);

811

812 LLVM_DEBUG(dbgs() << "Promoting " << *SI << " to " << *M << "\n");

813

814

815

816 auto *StoreDef = cast(MSSA->getMemoryAccess(SI));

817 auto *NewAccess = MSSAU->createMemoryAccessBefore(M, nullptr, StoreDef);

818 MSSAU->insertDef(cast(NewAccess), false);

819

821 NumMemSetInfer++;

822

823

824 BBI = M->getIterator();

825 return true;

826}

827

828bool MemCpyOptPass::processMemSet(MemSetInst *MSI, BasicBlock::iterator &BBI) {

829

830

832 if (Instruction *I =

833 tryMergingIntoMemset(MSI, MSI->getDest(), MSI->getValue())) {

834 BBI = I->getIterator();

835 return true;

836 }

837 return false;

838}

839

840

841

842

843bool MemCpyOptPass::performCallSlotOptzn(Instruction *cpyLoad,

844 Instruction *cpyStore, Value *cpyDest,

845 Value *cpySrc, TypeSize cpySize,

846 Align cpyDestAlign,

847 BatchAAResults &BAA,

848 std::function<CallInst *()> GetC) {

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

865 return false;

866

867

869 if (!srcAlloca)

870 return false;

871

873 if (!srcArraySize)

874 return false;

875

877 TypeSize SrcAllocaSize = DL.getTypeAllocSize(srcAlloca->getAllocatedType());

878

880 return false;

881 uint64_t srcSize = SrcAllocaSize * srcArraySize->getZExtValue();

882

883 if (cpySize < srcSize)

884 return false;

885

886 CallInst *C = GetC();

887 if (C)

888 return false;

889

890

891 if (Function *F = C->getCalledFunction())

892 if (F->isIntrinsic() && F->getIntrinsicID() == Intrinsic::lifetime_start)

893 return false;

894

895 if (C->getParent() != cpyStore->getParent()) {

896 LLVM_DEBUG(dbgs() << "Call Slot: block local restriction\n");

897 return false;

898 }

899

900 MemoryLocation DestLoc =

903 : MemoryLocation::getForDest(cast(cpyStore));

904

905

906

907 Instruction *SkippedLifetimeStart = nullptr;

909 MSSA->getMemoryAccess(cpyStore), &SkippedLifetimeStart)) {

910 LLVM_DEBUG(dbgs() << "Call Slot: Dest pointer modified after call\n");

911 return false;

912 }

913

914

915

916

917 if (SkippedLifetimeStart) {

918 auto *LifetimeArg =

920 if (LifetimeArg && LifetimeArg->getParent() == C->getParent() &&

921 C->comesBefore(LifetimeArg))

922 return false;

923 }

924

925

926

927 bool ExplicitlyDereferenceableOnly;

929 ExplicitlyDereferenceableOnly) ||

931 DL, C, AC, DT)) {

932 LLVM_DEBUG(dbgs() << "Call Slot: Dest pointer not dereferenceable\n");

933 return false;

934 }

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949

951 LLVM_DEBUG(dbgs() << "Call Slot: Dest may be visible through unwinding\n");

952 return false;

953 }

954

955

956 Align srcAlign = srcAlloca->getAlign();

957 bool isDestSufficientlyAligned = srcAlign <= cpyDestAlign;

958

959

960 if (!isDestSufficientlyAligned && isa<AllocaInst>(cpyDest)) {

961 LLVM_DEBUG(dbgs() << "Call Slot: Dest not sufficiently aligned\n");

962 return false;

963 }

964

965

966

967

968

970 while (!srcUseList.empty()) {

971 User *U = srcUseList.pop_back_val();

972

975 continue;

976 }

978 continue;

979

980 if (U != C && U != cpyLoad) {

981 LLVM_DEBUG(dbgs() << "Call slot: Source accessed by " << *U << "\n");

982 return false;

983 }

984 }

985

986

987

988 bool SrcIsCaptured = any_of(C->args(), [&](Use &U) {

989 return U->stripPointerCasts() == cpySrc &&

990 !C->doesNotCapture(C->getArgOperandNo(&U));

991 });

992

993

994

995

996 if (SrcIsCaptured) {

997

998

999

1000

1004 true))

1005 return false;

1006

1007 MemoryLocation SrcLoc =

1009 for (Instruction &I :

1010 make_range(++C->getIterator(), C->getParent()->end())) {

1011

1013 if (II->getIntrinsicID() == Intrinsic::lifetime_end &&

1014 II->getArgOperand(0) == srcAlloca)

1015 break;

1016 }

1017

1018

1020 break;

1021

1022

1023 if (&I == cpyLoad)

1024 continue;

1025

1026

1027

1028

1029

1031 return false;

1032 }

1033 }

1034

1035

1036

1037 bool NeedMoveGEP = false;

1038 if (!DT->dominates(cpyDest, C)) {

1039

1041 if (GEP && GEP->hasAllConstantIndices() &&

1042 DT->dominates(GEP->getPointerOperand(), C))

1043 NeedMoveGEP = true;

1044 else

1045 return false;

1046 }

1047

1048

1049

1050

1051

1054

1058 return false;

1059

1060

1061

1063 return false;

1064 for (unsigned ArgI = 0; ArgI < C->arg_size(); ++ArgI)

1065 if (C->getArgOperand(ArgI)->stripPointerCasts() == cpySrc &&

1066 cpySrc->getType() != C->getArgOperand(ArgI)->getType())

1067 return false;

1068

1069

1070 bool changedArgument = false;

1071 for (unsigned ArgI = 0; ArgI < C->arg_size(); ++ArgI)

1072 if (C->getArgOperand(ArgI)->stripPointerCasts() == cpySrc) {

1073 changedArgument = true;

1074 C->setArgOperand(ArgI, cpyDest);

1075 }

1076

1077 if (!changedArgument)

1078 return false;

1079

1080

1081 if (!isDestSufficientlyAligned) {

1084 }

1085

1086 if (NeedMoveGEP) {

1088 GEP->moveBefore(C->getIterator());

1089 }

1090

1091 if (SkippedLifetimeStart) {

1092 SkippedLifetimeStart->moveBefore(C->getIterator());

1093 MSSAU->moveBefore(MSSA->getMemoryAccess(SkippedLifetimeStart),

1094 MSSA->getMemoryAccess(C));

1095 }

1096

1098 if (cpyLoad != cpyStore)

1100

1101 ++NumCallSlot;

1102 return true;

1103}

1104

1105

1106

1107bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,

1108 MemCpyInst *MDep,

1109 BatchAAResults &BAA) {

1110

1112 return false;

1113

1114

1115

1116

1117

1118

1119

1121 return false;

1122

1123 int64_t MForwardOffset = 0;

1124 const DataLayout &DL = M->getModule()->getDataLayout();

1125

1126

1127 if (M->getSource() != MDep->getDest()) {

1128 std::optional<int64_t> Offset =

1129 M->getSource()->getPointerOffsetFrom(MDep->getDest(), DL);

1131 return false;

1132 MForwardOffset = *Offset;

1133 }

1134

1135 Value *CopyLength = M->getLength();

1136

1137

1138

1139

1140 if (MForwardOffset != 0 || MDep->getLength() != CopyLength) {

1143

1144

1145

1146 if (!MDepLen || !MLen)

1147 return false;

1148 if (MDepLen->getZExtValue() < MLen->getZExtValue() + MForwardOffset) {

1150 return false;

1151 if (MDepLen->getZExtValue() <= (uint64_t)MForwardOffset)

1152 return false;

1153

1154

1155 CopyLength = ConstantInt::get(CopyLength->getType(),

1156 MDepLen->getZExtValue() - MForwardOffset);

1157 }

1158 }

1159

1161 auto *CopySource = MDep->getSource();

1164 if (NewCopySource && NewCopySource->use_empty())

1165

1166

1167

1168

1169

1171 });

1172 MaybeAlign CopySourceAlign = MDep->getSourceAlign();

1174

1175 if (MDep->getLength() != CopyLength) {

1177 MCopyLoc = MCopyLoc.getWithNewSize(

1179 }

1180

1181

1182

1183

1184

1185

1186 if (MForwardOffset > 0) {

1187

1188 std::optional<int64_t> MDestOffset =

1189 M->getRawDest()->getPointerOffsetFrom(MDep->getRawSource(), DL);

1190 if (MDestOffset == MForwardOffset)

1191 CopySource = M->getDest();

1192 else {

1193 CopySource = Builder.CreateInBoundsPtrAdd(

1194 CopySource, Builder.getInt64(MForwardOffset));

1196 }

1197

1198 MCopyLoc = MCopyLoc.getWithNewPtr(CopySource);

1199 if (CopySourceAlign)

1200 CopySourceAlign = commonAlignment(*CopySourceAlign, MForwardOffset);

1201 }

1202

1203

1204

1205

1206

1207

1208

1209

1210

1211

1212 if (writtenBetween(MSSA, BAA, MCopyLoc, MSSA->getMemoryAccess(MDep),

1213 MSSA->getMemoryAccess(M)))

1214 return false;

1215

1216

1217 if (BAA.isMustAlias(M->getDest(), CopySource)) {

1218

1220 ++NumMemCpyInstr;

1221 return true;

1222 }

1223

1224

1225

1226

1227

1228

1229 bool UseMemMove = false;

1231

1232

1233

1234 if (M->isForceInlined())

1235 return false;

1236 UseMemMove = true;

1237 }

1238

1239

1240 LLVM_DEBUG(dbgs() << "MemCpyOptPass: Forwarding memcpy->memcpy src:\n"

1241 << *MDep << '\n'

1242 << *M << '\n');

1243

1244

1245

1247 if (UseMemMove)

1248 NewM = Builder.CreateMemMove(M->getDest(), M->getDestAlign(), CopySource,

1249 CopySourceAlign, CopyLength, M->isVolatile());

1250 else if (M->isForceInlined())

1251

1252

1253

1254 NewM = Builder.CreateMemCpyInline(M->getDest(), M->getDestAlign(),

1255 CopySource, CopySourceAlign, CopyLength,

1256 M->isVolatile());

1257 else

1258 NewM = Builder.CreateMemCpy(M->getDest(), M->getDestAlign(), CopySource,

1259 CopySourceAlign, CopyLength, M->isVolatile());

1260

1261 NewM->copyMetadata(*M, LLVMContext::MD_DIAssignID);

1262

1264 auto *LastDef = cast(MSSA->getMemoryAccess(M));

1265 auto *NewAccess = MSSAU->createMemoryAccessAfter(NewM, nullptr, LastDef);

1266 MSSAU->insertDef(cast(NewAccess), true);

1267

1268

1270 ++NumMemCpyInstr;

1271 return true;

1272}

1273

1274

1275

1276

1277

1278

1279

1280

1281

1282

1283

1284

1285

1286

1287

1288

1289

1290

1291

1292

1293bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,

1294 MemSetInst *MemSet,

1295 BatchAAResults &BAA) {

1296

1298 return false;

1299

1300

1301

1302

1303

1306 SimplifyQuery(MemCpy->getDataLayout(), DT, AC, MemCpy)))

1307 return false;

1308

1309

1310

1312 return false;

1313

1314

1315

1316

1318 MSSA->getMemoryAccess(MemSet),

1319 MSSA->getMemoryAccess(MemCpy)))

1320 return false;

1321

1322

1325

1327 return false;

1328

1329

1330

1331 if (DestSize == SrcSize) {

1333 return true;

1334 }

1335

1336

1338

1339

1342 if (DestAlign > 1)

1344 Alignment = commonAlignment(DestAlign, SrcSizeC->getZExtValue());

1345

1347

1348

1349

1350

1351

1352

1354 "Preserving debug location based on moving memset within BB.");

1355 Builder.SetCurrentDebugLocation(MemSet->getDebugLoc());

1356

1357

1361 SrcSize = Builder.CreateZExt(SrcSize, DestSize->getType());

1362 else

1363 DestSize = Builder.CreateZExt(DestSize, SrcSize->getType());

1364 }

1365

1366 Value *Ule = Builder.CreateICmpULE(DestSize, SrcSize);

1367 Value *SizeDiff = Builder.CreateSub(DestSize, SrcSize);

1368 Value *MemsetLen = Builder.CreateSelect(

1369 Ule, ConstantInt::getNullValue(DestSize->getType()), SizeDiff);

1370

1371

1375 Builder.CreateMemSet(Builder.CreatePtrAdd(Dest, SrcSize),

1376 MemSet->getOperand(1), MemsetLen, Alignment);

1377

1379 "MemCpy must be a MemoryDef");

1380

1381

1382 auto *LastDef = cast(MSSA->getMemoryAccess(MemCpy));

1383 auto *NewAccess =

1384 MSSAU->createMemoryAccessBefore(NewMemSet, nullptr, LastDef);

1385 MSSAU->insertDef(cast(NewAccess), true);

1386

1388 return true;

1389}

1390

1391

1392

1397

1399 if (II->getIntrinsicID() == Intrinsic::lifetime_start)

1401 return II->getArgOperand(0) == Alloca;

1402

1403 return false;

1404}

1405

1406

1407

1408

1409

1410

1419 return true;

1420 return false;

1421}

1422

1423

1424

1425

1426

1427

1428

1429

1430

1431

1432

1433

1434

1435bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,

1436 MemSetInst *MemSet,

1437 BatchAAResults &BAA) {

1440

1441 int64_t MOffset = 0;

1443

1444

1446 std::optional<int64_t> Offset =

1449 return false;

1451 }

1452

1453 if (MOffset != 0 || MemSetSize != CopySize) {

1454

1455

1458 if (!CMemSetSize || !CCopySize ||

1459 CCopySize->getZExtValue() + MOffset > CMemSetSize->getZExtValue()) {

1461 return false;

1462

1463 if (CMemSetSize && CCopySize) {

1464

1465

1466 assert(CCopySize->getZExtValue() + MOffset >

1467 CMemSetSize->getZExtValue());

1468 if (MOffset == 0)

1469 CopySize = MemSetSize;

1470 else

1471 CopySize =

1472 ConstantInt::get(CopySize->getType(),

1473 CMemSetSize->getZExtValue() <= (uint64_t)MOffset

1474 ? 0

1475 : CMemSetSize->getZExtValue() - MOffset);

1476 }

1477 }

1478 }

1479

1484 auto *LastDef = cast(MSSA->getMemoryAccess(MemCpy));

1485 auto *NewAccess = MSSAU->createMemoryAccessAfter(NewM, nullptr, LastDef);

1486 MSSAU->insertDef(cast(NewAccess), true);

1487

1488 return true;

1489}

1490

1491

1492

1493

1494

1495

1496

1497

1498

1499

1500

1501

1502

1503bool MemCpyOptPass::performStackMoveOptzn(Instruction *Load, Instruction *Store,

1504 AllocaInst *DestAlloca,

1505 AllocaInst *SrcAlloca, TypeSize Size,

1506 BatchAAResults &BAA) {

1507 LLVM_DEBUG(dbgs() << "Stack Move: Attempting to optimize:\n"

1508 << *Store << "\n");

1509

1510

1512 LLVM_DEBUG(dbgs() << "Stack Move: Address space mismatch\n");

1513 return false;

1514 }

1515

1516

1519 if (!SrcSize || Size != *SrcSize) {

1520 LLVM_DEBUG(dbgs() << "Stack Move: Source alloca size mismatch\n");

1521 return false;

1522 }

1524 if (!DestSize || Size != *DestSize) {

1525 LLVM_DEBUG(dbgs() << "Stack Move: Destination alloca size mismatch\n");

1526 return false;

1527 }

1528

1530 return false;

1531

1532

1533

1534

1535

1536

1537 SmallVector<Instruction *, 4> LifetimeMarkers;

1538 SmallPtrSet<Instruction *, 4> AAMetadataInstrs;

1539 bool SrcNotDom = false;

1540

1541 auto CaptureTrackingWithModRef =

1542 [&](Instruction *AI, function_ref<bool(Instruction *)> ModRefCallback,

1543 bool &AddressCaptured) -> bool {

1544 SmallVector<Instruction *, 8> Worklist;

1547 Worklist.reserve(MaxUsesToExplore);

1548 SmallPtrSet<const Use *, 20> Visited;

1549 while (!Worklist.empty()) {

1551 for (const Use &U : I->uses()) {

1553

1554

1555 if (!DT->dominates(SrcAlloca, UI))

1556 SrcNotDom = true;

1557

1558 if (Visited.size() >= MaxUsesToExplore) {

1561 << "Stack Move: Exceeded max uses to see ModRef, bailing\n");

1562 return false;

1563 }

1564 if (!Visited.insert(&U).second)

1565 continue;

1568 return false;

1570

1571 if (UI->mayReadOrWriteMemory()) {

1572 if (UI->isLifetimeStartOrEnd()) {

1573

1574

1575

1576

1577

1579 continue;

1580 }

1581 AAMetadataInstrs.insert(UI);

1582

1583 if (!ModRefCallback(UI))

1584 return false;

1585 }

1586

1589 continue;

1590 }

1591 }

1592 }

1593 return true;

1594 };

1595

1596

1597

1598 ModRefInfo DestModRef = ModRefInfo::NoModRef;

1600 SmallVector<BasicBlock *, 8> ReachabilityWorklist;

1601 auto DestModRefCallback = [&](Instruction *UI) -> bool {

1602

1603 if (UI == Store)

1604 return true;

1606 DestModRef |= Res;

1608

1609

1610

1611 if (UI->getParent() == Store->getParent()) {

1612

1613

1614

1615

1616

1618

1619

1620 if (UI->comesBefore(Store))

1621 return false;

1622

1623

1625 return true;

1626

1627

1629 } else {

1630 ReachabilityWorklist.push_back(UI->getParent());

1631 }

1632 }

1633 return true;

1634 };

1635

1636 bool DestAddressCaptured = false;

1637 if (!CaptureTrackingWithModRef(DestAlloca, DestModRefCallback,

1638 DestAddressCaptured))

1639 return false;

1640

1641 if (!ReachabilityWorklist.empty() &&

1643 nullptr, DT, nullptr))

1644 return false;

1645

1646

1647

1648

1650

1651 auto SrcModRefCallback = [&](Instruction *UI) -> bool {

1652

1653

1654 if (PDT->dominates(Load, UI) || UI == Load || UI == Store)

1655 return true;

1659 return false;

1660

1661 return true;

1662 };

1663

1664 bool SrcAddressCaptured = false;

1665 if (!CaptureTrackingWithModRef(SrcAlloca, SrcModRefCallback,

1666 SrcAddressCaptured))

1667 return false;

1668

1669

1670

1671 if (DestAddressCaptured && SrcAddressCaptured)

1672 return false;

1673

1674

1675

1676 if (SrcNotDom)

1678 SrcAlloca->getParent()->getFirstInsertionPt());

1679

1682

1683

1686

1687

1689

1690

1691

1692

1693 if (!LifetimeMarkers.empty()) {

1694 for (Instruction *I : LifetimeMarkers)

1696 }

1697

1698

1699

1700

1701

1702

1703 for (Instruction *I : AAMetadataInstrs) {

1704 I->setMetadata(LLVMContext::MD_alias_scope, nullptr);

1705 I->setMetadata(LLVMContext::MD_noalias, nullptr);

1706 I->setMetadata(LLVMContext::MD_tbaa, nullptr);

1707 I->setMetadata(LLVMContext::MD_tbaa_struct, nullptr);

1708 }

1709

1710 LLVM_DEBUG(dbgs() << "Stack Move: Performed staack-move optimization\n");

1711 NumStackMove++;

1712 return true;

1713}

1714

1719

1722 return false;

1723}

1724

1725

1726

1727

1728

1729

1730bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {

1731

1732 if (M->isVolatile())

1733 return false;

1734

1735

1736 if (M->getSource() == M->getDest()) {

1737 ++BBI;

1739 return true;

1740 }

1741

1742

1744 ++BBI;

1746 return true;

1747 }

1748

1749 MemoryUseOrDef *MA = MSSA->getMemoryAccess(M);

1750 if (!MA)

1751

1752 return false;

1753

1754

1756 if (GV->isConstant() && GV->hasDefinitiveInitializer())

1758 M->getDataLayout())) {

1760 Instruction *NewM = Builder.CreateMemSet(

1761 M->getRawDest(), ByteVal, M->getLength(), M->getDestAlign(), false);

1763 auto *NewAccess =

1764 MSSAU->createMemoryAccessAfter(NewM, nullptr, LastDef);

1765 MSSAU->insertDef(cast(NewAccess), true);

1766

1768 ++NumCpyToSet;

1769 return true;

1770 }

1771

1772 BatchAAResults BAA(*AA, EEA);

1773

1776 const MemoryAccess *DestClobber =

1777 MSSA->getWalker()->getClobberingMemoryAccess(AnyClobber, DestLoc, BAA);

1778

1779

1780

1781

1782

1785 if (DestClobber->getBlock() == M->getParent())

1786 if (processMemSetMemCpyDependence(M, MDep, BAA))

1787 return true;

1788

1789 MemoryAccess *SrcClobber = MSSA->getWalker()->getClobberingMemoryAccess(

1791

1792

1793

1794

1795

1796

1797

1798

1799

1801 if (Instruction *MI = MD->getMemoryInst()) {

1804 if (performCallSlotOptzn(M, M, M->getDest(), M->getSource(),

1806 M->getDestAlign().valueOrOne(), BAA,

1807 [C]() -> CallInst * { return C; })) {

1808 LLVM_DEBUG(dbgs() << "Performed call slot optimization:\n"

1809 << " call: " << *C << "\n"

1810 << " memcpy: " << *M << "\n");

1812 ++NumMemCpyInstr;

1813 return true;

1814 }

1815 }

1816 }

1818 if (processMemCpyMemCpyDependence(M, MDep, BAA))

1819 return true;

1821 if (performMemCpyToMemSetOptzn(M, MDep, BAA)) {

1822 LLVM_DEBUG(dbgs() << "Converted memcpy to memset\n");

1824 ++NumCpyToSet;

1825 return true;

1826 }

1827 }

1828 }

1829

1831 LLVM_DEBUG(dbgs() << "Removed memcpy from undef\n");

1833 ++NumMemCpyInstr;

1834 return true;

1835 }

1836 }

1837

1838

1839

1840

1842 if (!DestAlloca)

1843 return false;

1845 if (!SrcAlloca)

1846 return false;

1848 if (Len == nullptr)

1849 return false;

1850 if (performStackMoveOptzn(M, M, DestAlloca, SrcAlloca,

1852

1853 BBI = M->getNextNode()->getIterator();

1855 ++NumMemCpyInstr;

1856 return true;

1857 }

1858

1859 return false;

1860}

1861

1862

1863

1864bool MemCpyOptPass::isMemMoveMemSetDependency(MemMoveInst *M) {

1865 const auto &DL = M->getDataLayout();

1866 MemoryUseOrDef *MemMoveAccess = MSSA->getMemoryAccess(M);

1867 if (!MemMoveAccess)

1868 return false;

1869

1870

1872 auto *MemMoveSourceOp = M->getSource();

1874 if (!Source)

1875 return false;

1876

1877 APInt Offset(DL.getIndexTypeSizeInBits(Source->getType()), 0);

1878 LocationSize MemMoveLocSize = SourceLoc.Size;

1879 if (Source->getPointerOperand() != M->getDest() ||

1880 !MemMoveLocSize.hasValue() ||

1882 return false;

1883 }

1884

1885 uint64_t MemMoveSize = MemMoveLocSize.getValue();

1886 LocationSize TotalSize =

1888 MemoryLocation CombinedLoc(M->getDest(), TotalSize);

1889

1890

1891

1892 BatchAAResults BAA(*AA);

1895 MSSA->getWalker()->getClobberingMemoryAccess(FirstDef, CombinedLoc, BAA));

1896 if (!DestClobber)

1897 return false;

1898

1900 if (!MS)

1901 return false;

1902

1903

1905 if (!MemSetLength || MemSetLength->getZExtValue() < MemMoveSize)

1906 return false;

1907

1908

1909 if (!BAA.isMustAlias(MS->getDest(), M->getDest()))

1910 return false;

1911

1912 return true;

1913}

1914

1915

1916

1917bool MemCpyOptPass::processMemMove(MemMoveInst *M, BasicBlock::iterator &BBI) {

1918

1920

1921

1922 if (M->isVolatile() && isMemMoveMemSetDependency(M)) {

1923 LLVM_DEBUG(dbgs() << "Removed redundant memmove.\n");

1924 ++BBI;

1926 ++NumMemMoveInstr;

1927 return true;

1928 }

1929 return false;

1930 }

1931

1932 LLVM_DEBUG(dbgs() << "MemCpyOptPass: Optimizing memmove -> memcpy: " << *M

1933 << "\n");

1934

1935

1936 Type *ArgTys[3] = {M->getRawDest()->getType(), M->getRawSource()->getType(),

1937 M->getLength()->getType()};

1939 M->getModule(), Intrinsic::memcpy, ArgTys));

1940

1941

1942

1943

1944 ++NumMoveToCpy;

1945 return true;

1946}

1947

1948

1949bool MemCpyOptPass::processByValArgument(CallBase &CB, unsigned ArgNo) {

1951

1954 TypeSize ByValSize = DL.getTypeAllocSize(ByValTy);

1956 MemoryUseOrDef *CallAccess = MSSA->getMemoryAccess(&CB);

1957 if (!CallAccess)

1958 return false;

1959 MemCpyInst *MDep = nullptr;

1960 BatchAAResults BAA(*AA, EEA);

1961 MemoryAccess *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(

1965

1966

1967

1968

1971 return false;

1972

1973

1975 if (!C1 || !TypeSize::isKnownGE(

1977 return false;

1978

1979

1980

1981 MaybeAlign ByValAlign = CB.getParamAlign(ArgNo);

1982 if (!ByValAlign)

1983 return false;

1984

1985

1986

1988 if ((!MemDepAlign || *MemDepAlign < *ByValAlign) &&

1990 DT) < *ByValAlign)

1991 return false;

1992

1993

1995 return false;

1996

1997

1998

1999

2000

2001

2002

2004 MSSA->getMemoryAccess(MDep), CallAccess))

2005 return false;

2006

2007 LLVM_DEBUG(dbgs() << "MemCpyOptPass: Forwarding memcpy to byval:\n"

2008 << " " << *MDep << "\n"

2009 << " " << CB << "\n");

2010

2011

2014 ++NumMemCpyInstr;

2015 return true;

2016}

2017

2018

2019

2020

2021

2022

2023

2024

2025

2026

2027

2028

2029

2030

2031

2032bool MemCpyOptPass::processImmutArgument(CallBase &CB, unsigned ArgNo) {

2033 BatchAAResults BAA(*AA, EEA);

2035

2036

2038 return false;

2039

2040

2041

2042

2043 if (!CB.paramHasAttr(ArgNo, Attribute::NoAlias) &&

2046 return false;

2047

2049

2050

2051

2052

2054 if (!AI)

2055 return false;

2056

2057 std::optional AllocaSize = AI->getAllocationSize(DL);

2058

2059

2060 if (!AllocaSize || AllocaSize->isScalable())

2061 return false;

2063 MemoryUseOrDef *CallAccess = MSSA->getMemoryAccess(&CB);

2064 if (!CallAccess)

2065 return false;

2066

2067 MemCpyInst *MDep = nullptr;

2068 MemoryAccess *Clobber = MSSA->getWalker()->getClobberingMemoryAccess(

2072

2073

2074

2076 return false;

2077

2078

2080 return false;

2081

2082

2084 if (!MDepLen || AllocaSize != MDepLen->getValue())

2085 return false;

2086

2087

2088

2089

2091 Align AllocaAlign = AI->getAlign();

2092 if (MemDepAlign < AllocaAlign &&

2094 DT) < AllocaAlign)

2095 return false;

2096

2097

2098

2099

2100

2101

2102

2104 MSSA->getMemoryAccess(MDep), CallAccess))

2105 return false;

2106

2107

2109 return false;

2110

2111 LLVM_DEBUG(dbgs() << "MemCpyOptPass: Forwarding memcpy to Immut src:\n"

2112 << " " << *MDep << "\n"

2113 << " " << CB << "\n");

2114

2115

2118 ++NumMemCpyInstr;

2119 return true;

2120}

2121

2122

2123bool MemCpyOptPass::iterateOnFunction(Function &F) {

2124 bool MadeChange = false;

2125

2126

2127 for (BasicBlock &BB : F) {

2128

2129

2130

2131

2132 if (!DT->isReachableFromEntry(&BB))

2133 continue;

2134

2136

2138

2139 bool RepeatInstruction = false;

2140

2142 MadeChange |= processStore(SI, BI);

2144 RepeatInstruction = processMemSet(M, BI);

2146 RepeatInstruction = processMemCpy(M, BI);

2148 RepeatInstruction = processMemMove(M, BI);

2150 for (unsigned i = 0, e = CB->arg_size(); i != e; ++i) {

2152 MadeChange |= processByValArgument(*CB, i);

2154 MadeChange |= processImmutArgument(*CB, i);

2155 }

2156 }

2157

2158

2159 if (RepeatInstruction) {

2160 if (BI != BB.begin())

2161 --BI;

2162 MadeChange = true;

2163 }

2164 }

2165 }

2166

2167 return MadeChange;

2168}

2169

2177

2178 bool MadeChange = runImpl(F, &TLI, AA, AC, DT, PDT, &MSSA->getMSSA());

2179 if (!MadeChange)

2181

2185 return PA;

2186}

2187

2192 bool MadeChange = false;

2193 TLI = TLI_;

2194 AA = AA_;

2195 AC = AC_;

2196 DT = DT_;

2197 PDT = PDT_;

2198 MSSA = MSSA_;

2200 MSSAU = &MSSAU_;

2202 EEA = &EEA_;

2203

2204 while (true) {

2205 if (!iterateOnFunction(F))

2206 break;

2207 MadeChange = true;

2208 }

2209

2212

2213 return MadeChange;

2214}

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

This file contains the declarations for the subclasses of Constant, which represent the different fla...

This file defines the DenseSet and SmallDenseSet classes.

static bool runImpl(Function &F, const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)

This is the interface for a simple mod/ref and alias analysis over globals.

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

This header defines various interfaces for pass management in LLVM.

static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU)

static bool mayBeVisibleThroughUnwinding(Value *V, Instruction *Start, Instruction *End)

Definition MemCpyOptimizer.cpp:269

static bool isZeroSize(Value *Size)

Definition MemCpyOptimizer.cpp:1715

static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V, MemoryDef *Def)

Determine whether the pointer V had only undefined content (due to Def), either because it was freshl...

Definition MemCpyOptimizer.cpp:1393

static bool accessedBetween(BatchAAResults &AA, MemoryLocation Loc, const MemoryUseOrDef *Start, const MemoryUseOrDef *End, Instruction **SkippedLifetimeStart=nullptr)

Definition MemCpyOptimizer.cpp:299

static bool overreadUndefContents(MemorySSA *MSSA, MemCpyInst *MemCpy, MemIntrinsic *MemSrc, BatchAAResults &BAA)

Definition MemCpyOptimizer.cpp:1411

static cl::opt< bool > EnableMemCpyOptWithoutLibcalls("enable-memcpyopt-without-libcalls", cl::Hidden, cl::desc("Enable memcpyopt even when libcalls are disabled"))

static bool writtenBetween(MemorySSA *MSSA, BatchAAResults &AA, MemoryLocation Loc, const MemoryUseOrDef *Start, const MemoryUseOrDef *End)

Definition MemCpyOptimizer.cpp:323

This file provides utility analysis objects describing memory locations.

This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...

ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))

uint64_t IntrinsicInst * II

This file contains the declarations for profiling metadata utility functions.

This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

A manager for alias analyses.

LLVM_ABI bool isStaticAlloca() const

Return true if this alloca is in the entry block of the function and is a constant size.

Align getAlign() const

Return the alignment of the memory that is being allocated by the instruction.

unsigned getAddressSpace() const

Return the address space for the allocation.

LLVM_ABI std::optional< TypeSize > getAllocationSize(const DataLayout &DL) const

Get allocation size in bytes.

void setAlignment(Align Align)

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

Get the result of an analysis pass for a given IR unit.

A function analysis which provides an AssumptionCache.

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

iterator begin()

Instruction iterator methods.

LLVM_ABI bool isEntryBlock() const

Return true if this is the entry block of the containing function.

InstListType::iterator iterator

Instruction iterators...

This class is a wrapper over an AAResults, and it is intended to be used only when there are no IR ch...

bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB)

ModRefInfo getModRefInfo(const Instruction *I, const std::optional< MemoryLocation > &OptLoc)

ModRefInfo callCapturesBefore(const Instruction *I, const MemoryLocation &MemLoc, DominatorTree *DT)

Represents analyses that only rely on functions' control flow.

bool doesNotCapture(unsigned OpNo) const

Determine whether this data operand is not captured.

LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const

Determine whether the argument or parameter has the given attribute.

bool isByValArgument(unsigned ArgNo) const

Determine whether this argument is passed by value.

MaybeAlign getParamAlign(unsigned ArgNo) const

Extract the alignment for a call or parameter (0=unknown).

bool onlyReadsMemory(unsigned OpNo) const

Type * getParamByValType(unsigned ArgNo) const

Extract the byval type for a call or parameter.

Value * getArgOperand(unsigned i) const

void setArgOperand(unsigned i, Value *v)

unsigned arg_size() const

uint64_t getZExtValue() const

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

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

Analysis pass which computes a DominatorTree.

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

Context-sensitive CaptureAnalysis provider, which computes and caches the earliest common dominator c...

LLVM_ABI void mergeDIAssignID(ArrayRef< const Instruction * > SourceInstructions)

Merge the DIAssignID metadata from this instruction and those attached to instructions in SourceInstr...

const DebugLoc & getDebugLoc() const

Return the debug location for this node as a DebugLoc.

LLVM_ABI const Module * getModule() const

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

LLVM_ABI void moveBefore(InstListType::iterator InsertPos)

Unlink this instruction from its current basic block and insert it into the basic block that MovePos ...

LLVM_ABI void dropUnknownNonDebugMetadata(ArrayRef< unsigned > KnownIDs={})

Drop all unknown metadata except for debug locations.

void setDebugLoc(DebugLoc Loc)

Set the debug location information for this instruction.

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

Copy metadata from SrcInst to this instruction.

LLVM_ABI const DataLayout & getDataLayout() const

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

Value * getPointerOperand()

Align getAlign() const

Return the alignment of the access that is being performed.

static LocationSize precise(uint64_t Value)

TypeSize getValue() const

This class wraps the llvm.memcpy intrinsic.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)

Definition MemCpyOptimizer.cpp:2170

bool runImpl(Function &F, TargetLibraryInfo *TLI, AAResults *AA, AssumptionCache *AC, DominatorTree *DT, PostDominatorTree *PDT, MemorySSA *MSSA)

Definition MemCpyOptimizer.cpp:2188

Value * getLength() const

Value * getRawDest() const

Value * getDest() const

This is just like getRawDest, but it strips off any cast instructions (including addrspacecast) that ...

MaybeAlign getDestAlign() const

This is the common base class for memset/memcpy/memmove.

Value * getRawSource() const

Return the arguments to the instruction.

MaybeAlign getSourceAlign() const

Value * getSource() const

This is just like getRawSource, but it strips off any cast instructions that feed it,...

BasicBlock * getBlock() const

AllAccessType::self_iterator getIterator()

Get the iterators for the all access list and the defs only list We default to the all access list.

Represents a read-write access to memory, whether it is a must-alias, or a may-alias.

Representation for a specific memory location.

static LLVM_ABI MemoryLocation get(const LoadInst *LI)

Return a location with information about the memory reference by the given instruction.

static LLVM_ABI MemoryLocation getForSource(const MemTransferInst *MTI)

Return a location representing the source of a memory transfer.

LocationSize Size

The maximum size of the location, in address-units, or UnknownSize if the size is not known.

static MemoryLocation getBeforeOrAfter(const Value *Ptr, const AAMDNodes &AATags=AAMDNodes())

Return a location that may access any location before or after Ptr, while remaining within the underl...

static LLVM_ABI MemoryLocation getForDest(const MemIntrinsic *MI)

Return a location representing the destination of a memory set or transfer.

An analysis that produces MemorySSA for a function.

MemoryAccess * getClobberingMemoryAccess(const Instruction *I, BatchAAResults &AA)

Given a memory Mod/Ref/ModRef'ing instruction, calling this will give you the nearest dominating Memo...

Encapsulates MemorySSA, including all data associated with memory accesses.

LLVM_ABI bool dominates(const MemoryAccess *A, const MemoryAccess *B) const

Given two memory accesses in potentially different blocks, determine whether MemoryAccess A dominates...

LLVM_ABI void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const

Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...

LLVM_ABI MemorySSAWalker * getWalker()

MemoryUseOrDef * getMemoryAccess(const Instruction *I) const

Given a memory Mod/Ref'ing instruction, get the MemorySSA access associated with it.

bool isLiveOnEntryDef(const MemoryAccess *MA) const

Return true if MA represents the live on entry value.

Class that has the common methods + fields of memory uses/defs.

MemoryAccess * getDefiningAccess() const

Get the access that produces the memory state used by this Use.

Instruction * getMemoryInst() const

Get the instruction that this MemoryUse represents.

const DataLayout & getDataLayout() const

Get the data layout for the module's target platform.

Analysis pass which computes a PostDominatorTree.

PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

PreservedAnalyses & preserveSet()

Mark an analysis set as preserved.

PreservedAnalyses & preserve()

Mark an analysis as preserved.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

void reserve(size_type N)

typename SuperClass::const_iterator const_iterator

void append(ItTy in_start, ItTy in_end)

Add the specified range to the end of the SmallVector.

typename SuperClass::iterator iterator

void push_back(const T &Elt)

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

Analysis pass providing the TargetLibraryInfo.

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

static constexpr TypeSize getFixed(ScalarTy ExactSize)

LLVM_ABI unsigned getIntegerBitWidth() const

Type * getScalarType() const

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

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.

LLVM_ABI void replaceAllUsesWith(Value *V)

Change all uses of this to point to a new Value.

LLVM_ABI const Value * stripPointerCasts() const

Strip off pointer casts, all-zero GEPs and address space casts.

LLVM_ABI std::optional< int64_t > getPointerOffsetFrom(const Value *Other, const DataLayout &DL) const

If this ptr is provably equal to Other plus a constant offset, return that offset in bytes.

constexpr ScalarTy getFixedValue() const

constexpr bool isScalable() const

Returns whether the quantity is scaled by a runtime quantity (vscale).

const ParentTy * getParent() const

reverse_self_iterator getReverseIterator()

self_iterator getIterator()

This provides a very simple, boring adaptor for a begin and end iterator into a range type.

Abstract Attribute helper functions.

constexpr char Align[]

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

constexpr char Args[]

Key for Kernel::Metadata::mArgs.

@ C

The default llvm calling convention, compatible with C.

@ BasicBlock

Various leaf nodes.

LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})

Look up the Function declaration of the intrinsic id in the Module M.

@ User

could "use" a pointer

friend class Instruction

Iterator for Instructions in a `BasicBlock.

LLVM_ABI iterator begin() const

This is an optimization pass for GlobalISel generic memory operations.

FunctionAddr VTableAddr Value

detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)

bool capturesAddress(CaptureComponents CC)

LLVM_ABI bool isPotentiallyReachableFromMany(SmallVectorImpl< BasicBlock * > &Worklist, const BasicBlock *StopBB, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)

Determine whether there is at least one path from a block in 'Worklist' to 'StopBB' without passing t...

LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)

Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...

decltype(auto) dyn_cast(const From &Val)

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

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

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

auto partition_point(R &&Range, Predicate P)

Binary search for the first iterator in a range where a predicate is false.

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

auto cast_or_null(const Y &Val)

LLVM_ABI unsigned getDefaultMaxUsesToExploreForCaptureTracking()

getDefaultMaxUsesToExploreForCaptureTracking - Return default value of the maximal number of uses to ...

LLVM_ABI bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, const Instruction *I, const DominatorTree *DT, bool IncludeI=false, unsigned MaxUsesToExplore=0, const LoopInfo *LI=nullptr)

PointerMayBeCapturedBefore - Return true if this pointer value may be captured by the enclosing funct...

LLVM_ABI Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)

See if we can compute a simplified version of this instruction.

auto dyn_cast_or_null(const Y &Val)

bool any_of(R &&range, UnaryPredicate P)

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

auto reverse(ContainerTy &&C)

LLVM_ABI Align getOrEnforceKnownAlignment(Value *V, MaybeAlign PrefAlign, const DataLayout &DL, const Instruction *CxtI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr)

Try to ensure that the alignment of V is at least PrefAlign bytes.

bool isModSet(const ModRefInfo MRI)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

bool isModOrRefSet(const ModRefInfo MRI)

LLVM_ABI bool isNotVisibleOnUnwind(const Value *Object, bool &RequiresNoCaptureBeforeUnwind)

Return true if Object memory is not visible after an unwind, in the sense that program semantics cann...

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

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

RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)

ModRefInfo

Flags indicating whether a memory access modifies or references memory.

IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >

LLVM_ABI bool VerifyMemorySSA

Enables verification of MemorySSA.

RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)

DWARFExpression::Operation Op

LLVM_ABI bool isIdentifiedFunctionLocal(const Value *V)

Return true if V is umabigously identified at the function-level.

LLVM_ABI bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)

Return true if this function can prove that the instruction I will always transfer execution to one o...

decltype(auto) cast(const From &Val)

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

LLVM_ABI Value * isBytewiseValue(Value *V, const DataLayout &DL)

If the specified value can be set by repeating the same byte in memory, return the i8 value that it i...

Align commonAlignment(Align A, uint64_t Offset)

Returns the alignment that satisfies both alignments.

LLVM_ABI void combineAAMetadata(Instruction *K, const Instruction *J)

Combine metadata of two instructions, where instruction J is a memory access that has been merged int...

bool capturesAnything(CaptureComponents CC)

LLVM_ABI UseCaptureInfo DetermineUseCaptureKind(const Use &U, const Value *Base)

Determine what kind of capture behaviour U may exhibit.

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

LLVM_ABI const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=MaxLookupSearchDepth)

This method strips off any GEP address adjustments, pointer casts or llvm.threadlocal....

AAResults AliasAnalysis

Temporary typedef for legacy code that uses a generic AliasAnalysis pointer or reference.

bool capturesAnyProvenance(CaptureComponents CC)

bool isRefSet(const ModRefInfo MRI)

LLVM_ABI bool isWritableObject(const Value *Object, bool &ExplicitlyDereferenceableOnly)

Return true if the Object is writable, in the sense that any location based on this pointer that can ...

This struct is a compact representation of a valid (power of two) or undefined (0) alignment.

Align valueOrOne() const

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

CaptureComponents UseCC

Components captured by this use.

CaptureComponents ResultCC

Components captured by the return value of the user of this Use.