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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

86#include

87#include

88using namespace llvm;

89

90namespace llvm {

92}

93

94#define DEBUG_TYPE "licm"

95

96STATISTIC(NumCreatedBlocks, "Number of blocks created");

97STATISTIC(NumClonedBranches, "Number of branches cloned");

98STATISTIC(NumSunk, "Number of instructions sunk out of loop");

99STATISTIC(NumHoisted, "Number of instructions hoisted out of loop");

100STATISTIC(NumMovedLoads, "Number of load insts hoisted or sunk");

101STATISTIC(NumMovedCalls, "Number of call insts hoisted or sunk");

102STATISTIC(NumPromotionCandidates, "Number of promotion candidates");

103STATISTIC(NumLoadPromoted, "Number of load-only promotions");

104STATISTIC(NumLoadStorePromoted, "Number of load and store promotions");

106 "Number of min/max expressions hoisted out of the loop");

108 "Number of geps reassociated and hoisted out of the loop");

109STATISTIC(NumAddSubHoisted, "Number of add/subtract expressions reassociated "

110 "and hoisted out of the loop");

111STATISTIC(NumFPAssociationsHoisted, "Number of invariant FP expressions "

112 "reassociated and hoisted out of the loop");

114 "Number of invariant int expressions "

115 "reassociated and hoisted out of the loop");

116STATISTIC(NumBOAssociationsHoisted, "Number of invariant BinaryOp expressions "

117 "reassociated and hoisted out of the loop");

118

119

122 cl::desc("Disable memory promotion in LICM pass"));

123

126 cl::desc("Enable control flow (and PHI) hoisting in LICM"));

127

130 cl::desc("Force thread model single in LICM pass"));

131

134 cl::desc("Max num uses visited for identifying load "

135 "invariance in loop using invariant start (default = 8)"));

136

140 "Set upper limit for the number of transformations performed "

141 "during a single round of hoisting the reassociated expressions."));

142

146 "Set upper limit for the number of transformations performed "

147 "during a single round of hoisting the reassociated expressions."));

148

149

150

151

152

153

154

155

156

159 cl::desc("Enable imprecision in LICM in pathological cases, in exchange "

160 "for faster compile. Caps the MemorySSA clobbering calls."));

161

162

163

164

167 cl::desc("[LICM & MemorySSA] When MSSA in LICM is disabled, this has no "

168 "effect. When MSSA in LICM is enabled, then this is the maximum "

169 "number of accesses allowed to be present in a loop in order to "

170 "enable memory promotion."));

171

176 bool &FoldableInLoop, bool LoopNestMode);

192 bool InvariantGroup);

195

203

206

210

214 std::pair<SmallSetVector<Value *, 8>, bool>;

217

218namespace {

219struct LoopInvariantCodeMotion {

224

225 LoopInvariantCodeMotion(unsigned LicmMssaOptCap,

226 unsigned LicmMssaNoAccForPromotionCap,

227 bool LicmAllowSpeculation)

228 : LicmMssaOptCap(LicmMssaOptCap),

229 LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap),

230 LicmAllowSpeculation(LicmAllowSpeculation) {}

231

232private:

233 unsigned LicmMssaOptCap;

234 unsigned LicmMssaNoAccForPromotionCap;

235 bool LicmAllowSpeculation;

236};

237

238struct LegacyLICMPass : public LoopPass {

239 static char ID;

240 LegacyLICMPass(

243 bool LicmAllowSpeculation = true)

244 : LoopPass(ID), LICM(LicmMssaOptCap, LicmMssaNoAccForPromotionCap,

245 LicmAllowSpeculation) {

247 }

248

250 if (skipLoop(L))

251 return false;

252

253 LLVM_DEBUG(dbgs() << "Perform LICM on Loop with header at block "

254 << L->getHeader()->getNameOrAsOperand() << "\n");

255

256 Function *F = L->getHeader()->getParent();

257

258 auto *SE = getAnalysisIfAvailable();

259 MemorySSA *MSSA = &getAnalysis().getMSSA();

260

261

262

264 return LICM.runOnLoop(

265 L, &getAnalysis().getAAResults(),

266 &getAnalysis().getLoopInfo(),

267 &getAnalysis().getDomTree(),

268 &getAnalysis().getAssumptionCache(*F),

269 &getAnalysis().getTLI(*F),

270 &getAnalysis().getTTI(*F),

271 SE ? &SE->getSE() : nullptr, MSSA, &ORE);

272 }

273

274

275

276

277 void getAnalysisUsage(AnalysisUsage &AU) const override {

289 }

290

291private:

292 LoopInvariantCodeMotion LICM;

293};

294}

295

298 if (!AR.MSSA)

300 false);

301

302

303

304

306

309 if (!LICM.runOnLoop(&L, &AR.AA, &AR.LI, &AR.DT, &AR.AC, &AR.TLI, &AR.TTI,

310 &AR.SE, AR.MSSA, &ORE))

312

315

316 return PA;

317}

318

322 OS, MapClassName2PassName);

323

324 OS << '<';

326 OS << '>';

327}

328

332 if (!AR.MSSA)

334 false);

335

336

337

338

340

343

345 bool Changed = LICM.runOnLoop(&OutermostLoop, &AR.AA, &AR.LI, &AR.DT, &AR.AC,

346 &AR.TLI, &AR.TTI, &AR.SE, AR.MSSA, &ORE, true);

347

348 if (!Changed)

350

352

356

357 return PA;

358}

359

363 OS, MapClassName2PassName);

364

365 OS << '<';

367 OS << '>';

368}

369

370char LegacyLICMPass::ID = 0;

372 false, false)

380

382

386 IsSink, L, MSSA) {}

387

389 unsigned LicmMssaOptCap, unsigned LicmMssaNoAccForPromotionCap, bool IsSink,

391 : LicmMssaOptCap(LicmMssaOptCap),

392 LicmMssaNoAccForPromotionCap(LicmMssaNoAccForPromotionCap),

393 IsSink(IsSink) {

394 unsigned AccessCapCount = 0;

395 for (auto *BB : L.getBlocks())

397 for (const auto &MA : *Accesses) {

398 (void)MA;

399 ++AccessCapCount;

402 return;

403 }

404 }

405}

406

407

408

409

416 bool LoopNestMode) {

417 bool Changed = false;

418

419 assert(L->isLCSSAForm(*DT) && "Loop is not in LCSSA form.");

420

421

422

424 return false;

425 }

426

427

428

429

430

431

432

433

434

435

437 return llvm::any_of(*BB, [](Instruction &I) {

438 IntrinsicInst *II = dyn_cast(&I);

439 return II && II->getIntrinsicID() == Intrinsic::coro_suspend;

440 });

441 });

442

445 true, *L, *MSSA);

446

447

448 BasicBlock *Preheader = L->getLoopPreheader();

449

450

453

454

455

456

457

458

459

460

461

462

463 if (L->hasDedicatedExits())

464 Changed |=

465 LoopNestMode

467 TLI, TTI, L, MSSAU, &SafetyInfo, Flags, ORE)

469 MSSAU, &SafetyInfo, Flags, ORE);

470 Flags.setIsSink(false);

471 if (Preheader)

472 Changed |= hoistRegion(DT->getNode(L->getHeader()), AA, LI, DT, AC, TLI, L,

473 MSSAU, SE, &SafetyInfo, Flags, ORE, LoopNestMode,

474 LicmAllowSpeculation);

475

476

477

478

479

480

481

482

484 Flags.tooManyMemoryAccesses() && !HasCoroSuspendInst) {

485

487 L->getUniqueExitBlocks(ExitBlocks);

488

489

491 return isa(Exit->getTerminator());

492 });

493

494 if (!HasCatchSwitch) {

498 MSSAInsertPts.reserve(ExitBlocks.size());

499 for (BasicBlock *ExitBlock : ExitBlocks) {

500 InsertPts.push_back(ExitBlock->getFirstInsertionPt());

501 MSSAInsertPts.push_back(nullptr);

502 }

503

505

506

507

508 bool Promoted = false;

509 bool LocalPromoted;

510 do {

511 LocalPromoted = false;

512 for (auto [PointerMustAliases, HasReadsOutsideSet] :

515 PointerMustAliases, ExitBlocks, InsertPts, MSSAInsertPts, PIC, LI,

516 DT, AC, TLI, TTI, L, MSSAU, &SafetyInfo, ORE,

517 LicmAllowSpeculation, HasReadsOutsideSet);

518 }

519 Promoted |= LocalPromoted;

520 } while (LocalPromoted);

521

522

523

524

525

526

527

528 if (Promoted)

530

531 Changed |= Promoted;

532 }

533 }

534

535

536

537

538 assert(L->isLCSSAForm(*DT) && "Loop not left in LCSSA form after LICM!");

539 assert((L->isOutermost() || L->getParentLoop()->isLCSSAForm(*DT)) &&

540 "Parent loop not left in LCSSA form after LICM!");

541

544

545 if (Changed && SE)

547 return Changed;

548}

549

550

551

552

553

554

561

562

563 assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&

564 CurLoop != nullptr && SafetyInfo != nullptr &&

565 "Unexpected input to sinkRegion.");

566

567

568

569

572

573 bool Changed = false;

575

577 continue;

578

581

582

583

585 LLVM_DEBUG(dbgs() << "LICM deleting dead inst: " << I << '\n');

588 ++II;

590 Changed = true;

591 continue;

592 }

593

594

595

596

597

598

599 bool FoldableInLoop = false;

600 bool LoopNestMode = OutermostLoop != nullptr;

601 if (I.mayHaveSideEffects() &&

603 SafetyInfo, TTI, FoldableInLoop,

604 LoopNestMode) &&

606 if (sink(I, LI, DT, CurLoop, SafetyInfo, MSSAU, ORE)) {

607 if (!FoldableInLoop) {

608 ++II;

611 }

612 Changed = true;

613 }

614 }

615 }

616 }

619 return Changed;

620}

621

629

630 bool Changed = false;

632 Worklist.insert(CurLoop);

634 while (!Worklist.empty()) {

637 MSSAU, SafetyInfo, Flags, ORE, CurLoop);

638 }

639 return Changed;

640}

641

642namespace {

643

644

645

646

647

648

649

650class ControlFlowHoister {

651private:

652

655 Loop *CurLoop;

657

658

659

661

662

663

665

666public:

669 : LI(LI), DT(DT), CurLoop(CurLoop), MSSAU(MSSAU) {}

670

671 void registerPossiblyHoistableBranch(BranchInst *BI) {

672

675 return;

676

677

678

679

682 if (!CurLoop->contains(TrueDest) || !CurLoop->contains(FalseDest) ||

683 TrueDest == FalseDest)

684 return;

685

686

687

688

689

690

695 if (TrueDestSucc.count(FalseDest)) {

696 CommonSucc = FalseDest;

697 } else if (FalseDestSucc.count(TrueDest)) {

698 CommonSucc = TrueDest;

699 } else {

701

702 if (TrueDestSucc.size() == 1)

703 CommonSucc = *TrueDestSucc.begin();

704

705

706

707 else if (!TrueDestSucc.empty()) {

709 auto IsSucc = [&](BasicBlock &BB) { return TrueDestSucc.count(&BB); };

711 assert(It != F->end() && "Could not find successor in function");

712 CommonSucc = &*It;

713 }

714 }

715

716

717

718

719

720

721

722

723 if (CommonSucc && DT->dominates(BI, CommonSucc))

724 HoistableBranches[BI] = CommonSucc;

725 }

726

727 bool canHoistPHI(PHINode *PN) {

728

730 return false;

731

732

736 PredecessorBlocks.insert(PredBB);

737

738

739

740

741

743 return false;

744 for (auto &Pair : HoistableBranches) {

745 if (Pair.second == BB) {

746

747

748 if (Pair.first->getSuccessor(0) == BB) {

749 PredecessorBlocks.erase(Pair.first->getParent());

750 PredecessorBlocks.erase(Pair.first->getSuccessor(1));

751 } else if (Pair.first->getSuccessor(1) == BB) {

752 PredecessorBlocks.erase(Pair.first->getParent());

753 PredecessorBlocks.erase(Pair.first->getSuccessor(0));

754 } else {

755 PredecessorBlocks.erase(Pair.first->getSuccessor(0));

756 PredecessorBlocks.erase(Pair.first->getSuccessor(1));

757 }

758 }

759 }

760

761

762 return PredecessorBlocks.empty();

763 }

764

768

769 if (HoistDestinationMap.count(BB))

770 return HoistDestinationMap[BB];

771

772

773 auto HasBBAsSuccessor =

775 return BB != Pair.second && (Pair.first->getSuccessor(0) == BB ||

776 Pair.first->getSuccessor(1) == BB);

777 };

778 auto It = llvm::find_if(HoistableBranches, HasBBAsSuccessor);

779

780

782 if (It == HoistableBranches.end()) {

785 << " as hoist destination for "

787 HoistDestinationMap[BB] = InitialPreheader;

788 return InitialPreheader;

789 }

791 assert(std::find_if(++It, HoistableBranches.end(), HasBBAsSuccessor) ==

792 HoistableBranches.end() &&

793 "BB is expected to be the target of at most one branch");

794

798 BasicBlock *CommonSucc = HoistableBranches[BI];

800

801

802 auto CreateHoistedBlock = [&](BasicBlock *Orig) {

803 if (HoistDestinationMap.count(Orig))

804 return HoistDestinationMap[Orig];

807 HoistDestinationMap[Orig] = New;

811 ++NumCreatedBlocks;

813 << " as hoist destination for " << Orig->getName()

814 << "\n");

815 return New;

816 };

817 BasicBlock *HoistTrueDest = CreateHoistedBlock(TrueDest);

818 BasicBlock *HoistFalseDest = CreateHoistedBlock(FalseDest);

819 BasicBlock *HoistCommonSucc = CreateHoistedBlock(CommonSucc);

820

821

823

824

826 assert(TargetSucc && "Expected hoist target to have a single successor");

827 HoistCommonSucc->moveBefore(TargetSucc);

829 }

831 HoistTrueDest->moveBefore(HoistCommonSucc);

833 }

835 HoistFalseDest->moveBefore(HoistCommonSucc);

837 }

838

839

840

841 if (HoistTarget == InitialPreheader) {

842

846

850

851

852 for (auto &Pair : HoistDestinationMap)

853 if (Pair.second == InitialPreheader && Pair.first != BI->getParent())

854 Pair.second = HoistCommonSucc;

855 }

856

857

861 ++NumClonedBranches;

862

864 "Hoisting blocks should not have destroyed preheader");

865 return HoistDestinationMap[BB];

866 }

867};

868}

869

870

871

872

873

874

882 bool AllowSpeculation) {

883

884 assert(N != nullptr && AA != nullptr && LI != nullptr && DT != nullptr &&

885 CurLoop != nullptr && SafetyInfo != nullptr &&

886 "Unexpected input to hoistRegion.");

887

888 ControlFlowHoister CFH(LI, DT, CurLoop, MSSAU);

889

890

891

893

894

895

896

899 bool Changed = false;

902

903

904 if (!LoopNestMode && inSubLoop(BB, CurLoop, LI))

905 continue;

906

908

909

910

911

912

913

914

918 I, DT, TLI, CurLoop, SafetyInfo, ORE,

919 Preheader->getTerminator(), AC, AllowSpeculation)) {

920 hoist(I, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB), SafetyInfo,

921 MSSAU, SE, ORE);

923 Changed = true;

924 continue;

925 }

926

927

928

929 if (I.getOpcode() == Instruction::FDiv && I.hasAllowReciprocal() &&

931 auto Divisor = I.getOperand(1);

932 auto One = llvm::ConstantFP::get(Divisor->getType(), 1.0);

933 auto ReciprocalDivisor = BinaryOperator::CreateFDiv(One, Divisor);

934 ReciprocalDivisor->setFastMathFlags(I.getFastMathFlags());

936 ReciprocalDivisor->insertBefore(&I);

937 ReciprocalDivisor->setDebugLoc(I.getDebugLoc());

938

939 auto Product =

940 BinaryOperator::CreateFMul(I.getOperand(0), ReciprocalDivisor);

941 Product->setFastMathFlags(I.getFastMathFlags());

943 Product->insertAfter(&I);

944 Product->setDebugLoc(I.getDebugLoc());

945 I.replaceAllUsesWith(Product);

947

948 hoist(*ReciprocalDivisor, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB),

949 SafetyInfo, MSSAU, SE, ORE);

950 HoistedInstructions.push_back(ReciprocalDivisor);

951 Changed = true;

952 continue;

953 }

954

955 auto IsInvariantStart = [&](Instruction &I) {

956 using namespace PatternMatch;

957 return I.use_empty() &&

958 match(&I, m_IntrinsicIntrinsic::invariant\_start());

959 };

960 auto MustExecuteWithoutWritesBefore = [&](Instruction &I) {

963 };

964 if ((IsInvariantStart(I) || isGuard(&I)) &&

966 MustExecuteWithoutWritesBefore(I)) {

967 hoist(I, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB), SafetyInfo,

968 MSSAU, SE, ORE);

970 Changed = true;

971 continue;

972 }

973

974 if (PHINode *PN = dyn_cast(&I)) {

975 if (CFH.canHoistPHI(PN)) {

976

977

981 hoist(*PN, DT, CurLoop, CFH.getOrCreateHoistedBlock(BB), SafetyInfo,

982 MSSAU, SE, ORE);

983 assert(DT->dominates(PN, BB) && "Conditional PHIs not expected");

984 Changed = true;

985 continue;

986 }

987 }

988

989

990

992 Changed = true;

993 continue;

994 }

995

996

997

998 if (BranchInst *BI = dyn_cast(&I))

999 CFH.registerPossiblyHoistableBranch(BI);

1000 }

1001 }

1002

1003

1004

1005

1006

1007

1008

1009

1014 [&](Use &U) { return DT->dominates(I, U); })) {

1017 if (!HoistPoint || !DT->dominates(HoistPoint->getParent(), Dominator)) {

1018 if (HoistPoint)

1020 "New hoist point expected to dominate old hoist point");

1022 }

1024 << HoistPoint->getParent()->getNameOrAsOperand()

1025 << ": " << *I << "\n");

1027 SE);

1028 HoistPoint = I;

1029 Changed = true;

1030 }

1031 }

1032 }

1035

1036

1037

1038#ifdef EXPENSIVE_CHECKS

1039 if (Changed) {

1040 assert(DT->verify(DominatorTree::VerificationLevel::Fast) &&

1041 "Dominator tree verification failed");

1043 }

1044#endif

1045

1046 return Changed;

1047}

1048

1049

1050

1051

1052

1054 Loop *CurLoop) {

1057 const TypeSize LocSizeInBits = DL.getTypeSizeInBits(LI->getType());

1058

1059

1060

1061

1062

1063

1064

1065

1066

1067

1069 return false;

1070

1071

1072

1073 if (isa(Addr))

1074 return false;

1075

1076 unsigned UsesVisited = 0;

1077

1078

1079 for (auto *U : Addr->users()) {

1080

1082 return false;

1084

1085

1086 if (II || II->getIntrinsicID() != Intrinsic::invariant_start ||

1087 II->use_empty())

1088 continue;

1089 ConstantInt *InvariantSize = cast(II->getArgOperand(0));

1090

1091

1093 continue;

1095

1096

1097

1098

1099 if (LocSizeInBits.getFixedValue() <= InvariantSizeInBits &&

1101 return true;

1102 }

1103

1104 return false;

1105}

1106

1107namespace {

1108

1109

1110

1111bool isHoistableAndSinkableInst(Instruction &I) {

1112

1113 return (isa(I) || isa(I) || isa(I) ||

1114 isa(I) || isa(I) || isa(I) ||

1115 isa(I) || isa(I) ||

1116 isa(I) || isa(I) ||

1117 isa(I) || isa(I) ||

1118 isa(I) || isa(I) ||

1119 isa(I) || isa(I));

1120}

1121

1123 for (auto *BB : L->getBlocks())

1125 return false;

1126 return true;

1127}

1128

1129

1132 for (auto *BB : L->getBlocks())

1134 int NotAPhi = 0;

1135 for (const auto &Acc : *Accs) {

1136 if (isa(&Acc))

1137 continue;

1138 const auto *MUD = cast(&Acc);

1139 if (MUD->getMemoryInst() != I || NotAPhi++ == 1)

1140 return false;

1141 }

1142 }

1143 return true;

1144}

1145}

1146

1151

1152 if (Flags.tooManyClobberingCalls())

1154

1157 Flags.incrementClobberingCalls();

1158 return Source;

1159}

1160

1163 bool TargetExecutesOncePerLoop,

1166

1167 if (!isHoistableAndSinkableInst(I))

1168 return false;

1169

1171

1172 if (LoadInst *LI = dyn_cast(&I)) {

1173 if (!LI->isUnordered())

1174 return false;

1175

1176

1177

1179 return true;

1180 if (LI->hasMetadata(LLVMContext::MD_invariant_load))

1181 return true;

1182

1183 if (LI->isAtomic() && !TargetExecutesOncePerLoop)

1184 return false;

1185

1186

1188 return true;

1189

1191

1192 bool InvariantGroup = LI->hasMetadata(LLVMContext::MD_invariant_group);

1193

1195 MSSA, MU, CurLoop, I, Flags, InvariantGroup);

1196

1197

1199 ORE->emit([&]() {

1201 DEBUG_TYPE, "LoadWithLoopInvariantAddressInvalidated", LI)

1202 << "failed to move load with loop-invariant address "

1203 "because the loop may invalidate its value";

1204 });

1205

1207 } else if (CallInst *CI = dyn_cast(&I)) {

1208

1209 if (isa(I))

1210 return false;

1211

1212

1213 if (CI->mayThrow())

1214 return false;

1215

1216

1217

1218

1219

1220 if (CI->isConvergent())

1221 return false;

1222

1223

1224

1225

1226

1227

1228 if (CI->getFunction()->isPresplitCoroutine())

1229 return false;

1230

1231 using namespace PatternMatch;

1232 if (match(CI, m_IntrinsicIntrinsic::assume()))

1233

1234 return true;

1235

1236

1238

1240 return true;

1242

1243

1244

1246

1247 for (Value *Op : CI->args())

1248 if (Op->getType()->isPointerTy() &&

1250 MSSA, cast(MSSA->getMemoryAccess(CI)), CurLoop, I,

1251 Flags, false))

1252 return false;

1253 return true;

1254 }

1255

1256

1257

1258 if (isReadOnly(MSSAU, CurLoop))

1259 return true;

1260 }

1261

1262

1263

1264

1265 return false;

1266 } else if (auto *FI = dyn_cast(&I)) {

1267

1268

1269 return isOnlyMemoryAccess(FI, CurLoop, MSSAU);

1270 } else if (auto *SI = dyn_cast(&I)) {

1271 if (!SI->isUnordered())

1272 return false;

1273

1274

1275

1276

1277

1278

1279 if (isOnlyMemoryAccess(SI, CurLoop, MSSAU))

1280 return true;

1281

1282

1283 if (Flags.tooManyMemoryAccesses())

1284 return false;

1285

1289

1291 CurLoop->contains(Source->getBlock()))

1292 return false;

1293

1294

1295

1296

1297

1298

1299 for (auto *BB : CurLoop->getBlocks())

1301 for (const auto &MA : *Accesses)

1302 if (const auto *MU = dyn_cast(&MA)) {

1306 CurLoop->contains(MD->getBlock()))

1307 return false;

1308

1309

1310

1311

1312 if (!Flags.getIsSink() && !MSSA->dominates(SIMD, MU))

1313 return false;

1314 } else if (const auto *MD = dyn_cast(&MA)) {

1315 if (auto *LI = dyn_cast(MD->getMemoryInst())) {

1316 (void)LI;

1317 assert(!LI->isUnordered() && "Expected unordered load");

1318 return false;

1319 }

1320

1321 if (auto *CI = dyn_cast(MD->getMemoryInst())) {

1322

1323

1324

1327 return false;

1328 }

1329 }

1330 }

1331 return true;

1332 }

1333

1334 assert(I.mayReadOrWriteMemory() && "unhandled aliasing");

1335

1336

1337

1338 return true;

1339}

1340

1341

1342

1343

1344

1345

1348 if (IncValue != &I)

1349 return false;

1350

1351 return true;

1352}

1353

1354

1357 if (auto *GEP = dyn_cast(&I)) {

1361 return false;

1362

1363

1364

1366 for (const User *U : GEP->users()) {

1367 const Instruction *UI = cast(U);

1368 if (CurLoop->contains(UI) &&

1370 (!isa(UI) && !isa(UI))))

1371 return false;

1372 }

1373 return true;

1374 }

1375

1376 return false;

1377}

1378

1379

1380

1381

1382

1383

1384

1388 bool &FoldableInLoop, bool LoopNestMode) {

1389 const auto &BlockColors = SafetyInfo->getBlockColors();

1391 for (const User *U : I.users()) {

1392 const Instruction *UI = cast(U);

1393 if (const PHINode *PN = dyn_cast(UI)) {

1395

1397 return false;

1398

1399

1400

1401 if (isa(I))

1402 if (!BlockColors.empty() &&

1403 BlockColors.find(const_cast<BasicBlock *>(BB))->second.size() != 1)

1404 return false;

1405

1406 if (LoopNestMode) {

1407 while (isa(UI) && UI->hasOneUser() &&

1410 break;

1411 UI = cast(UI->user_back());

1412 }

1413 }

1414 }

1415

1416 if (CurLoop->contains(UI)) {

1417 if (IsFoldable) {

1418 FoldableInLoop = true;

1419 continue;

1420 }

1421 return false;

1422 }

1423 }

1424 return true;

1425}

1426

1431 if (auto *CI = dyn_cast(&I)) {

1432 const auto &BlockColors = SafetyInfo->getBlockColors();

1433

1434

1435

1436

1438 for (unsigned BundleIdx = 0, BundleEnd = CI->getNumOperandBundles();

1439 BundleIdx != BundleEnd; ++BundleIdx) {

1440 OperandBundleUse Bundle = CI->getOperandBundleAt(BundleIdx);

1442 continue;

1443

1445 }

1446

1447 if (!BlockColors.empty()) {

1448 const ColorVector &CV = BlockColors.find(&ExitBlock)->second;

1449 assert(CV.size() == 1 && "non-unique color for exit block!");

1454 }

1455

1457 New->copyMetadata(*CI);

1458 } else {

1459 New = I.clone();

1460 }

1461

1463 if (I.getName().empty())

1464 New->setName(I.getName() + ".le");

1465

1467

1468

1469

1472 false);

1473 if (NewMemAcc) {

1474 if (auto *MemDef = dyn_cast(NewMemAcc))

1475 MSSAU.insertDef(MemDef, true);

1476 else {

1477 auto *MemUse = cast(NewMemAcc);

1478 MSSAU.insertUse(MemUse, true);

1479 }

1480 }

1481 }

1482

1483

1484

1485

1486

1487

1488

1489

1490 for (Use &Op : New->operands())

1492 auto *OInst = cast(Op.get());

1495 OInst->getName() + ".lcssa");

1499 Op = OpPN;

1500 }

1501 return New;

1502}

1503

1508 I.eraseFromParent();

1509}

1510

1517 I.moveBefore(*Dest->getParent(), Dest);

1518 if (MemoryUseOrDef *OldMemAcc = cast_or_null(

1520 MSSAU.moveToPlace(OldMemAcc, Dest->getParent(),

1522 if (SE)

1524}

1525

1532 "Expect only trivially replaceable PHI");

1535 auto It = SunkCopies.find(ExitBlock);

1536 if (It != SunkCopies.end())

1537 New = It->second;

1538 else

1540 *I, *ExitBlock, *TPN, LI, SafetyInfo, MSSAU);

1541 return New;

1542}

1543

1547 return false;

1548

1549

1550

1551

1553 return false;

1555 if (isa(BBPred->getTerminator()))

1556 return false;

1557 }

1558 return true;

1559}

1560

1565#ifndef NDEBUG

1569 ExitBlocks.end());

1570#endif

1572 assert(ExitBlockSet.count(ExitBB) && "Expect the PHI is in an exit block.");

1573

1574

1575

1576

1577

1578

1579

1580

1581

1582

1583

1584

1585

1586

1587

1588

1589

1590

1591

1592

1593

1594

1595

1596

1597

1598

1599

1600

1601

1602

1603

1604

1605

1606 const auto &BlockColors = SafetyInfo->getBlockColors();

1608 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);

1609 while (!PredBBs.empty()) {

1612 "Expect all predecessors are in the loop");

1615 ExitBB, PredBB, ".split.loop.exit", &DTU, LI, MSSAU, true);

1616

1617

1618

1619 if (!BlockColors.empty())

1620

1621

1622

1623 SafetyInfo->copyColors(NewPred, PredBB);

1624 }

1625 PredBBs.remove(PredBB);

1626 }

1627}

1628

1629

1630

1631

1632

1633

1637 bool Changed = false;

1638 LLVM_DEBUG(dbgs() << "LICM sinking instruction: " << I << "\n");

1639

1640

1641

1644 auto *User = cast(*UI);

1645 Use &U = UI.getUse();

1646 ++UI;

1647

1649 continue;

1650

1653 Changed = true;

1654 continue;

1655 }

1656

1657

1659

1660

1661

1662

1666 Changed = true;

1667 continue;

1668 }

1669

1670 VisitedUsers.insert(PN);

1672 continue;

1673

1675 return Changed;

1676

1677

1678

1680

1681

1682

1683 UI = I.user_begin();

1684 UE = I.user_end();

1685 }

1686

1687 if (VisitedUsers.empty())

1688 return Changed;

1689

1690 ORE->emit([&]() {

1692 << "sinking " << ore::NV("Inst", &I);

1693 });

1694 if (isa(I))

1695 ++NumMovedLoads;

1696 else if (isa(I))

1697 ++NumMovedCalls;

1698 ++NumSunk;

1699

1700#ifndef NDEBUG

1704 ExitBlocks.end());

1705#endif

1706

1707

1709

1710

1711

1712

1713

1714

1716 for (auto *UI : Users) {

1717 auto *User = cast(UI);

1718

1720 continue;

1721

1724 "The LCSSA PHI is not in an exit block!");

1725

1726

1728 PN, &I, LI, SunkCopies, SafetyInfo, CurLoop, MSSAU);

1729

1730 New->dropLocation();

1733 Changed = true;

1734 }

1735 return Changed;

1736}

1737

1738

1739

1740

1746 << I << "\n");

1747 ORE->emit([&]() {

1750 });

1751

1752

1753

1754

1755

1756

1757

1758

1759

1760 if ((I.hasMetadataOtherThanDebugLoc() || isa(I)) &&

1761

1762

1763

1765 I.dropUBImplyingAttrsAndMetadata();

1766

1767 if (isa(I))

1768

1770 else

1771

1773 MSSAU, SE);

1774

1775 I.updateLocationAfterHoist();

1776

1777 if (isa(I))

1778 ++NumMovedLoads;

1779 else if (isa(I))

1780 ++NumMovedCalls;

1781 ++NumHoisted;

1782}

1783

1784

1785

1786

1792 if (AllowSpeculation &&

1794 return true;

1795

1796 bool GuaranteedToExecute =

1798

1799 if (!GuaranteedToExecute) {

1800 auto *LI = dyn_cast(&Inst);

1801 if (LI && CurLoop->isLoopInvariant(LI->getPointerOperand()))

1802 ORE->emit([&]() {

1804 DEBUG_TYPE, "LoadWithLoopInvariantAddressCondExecuted", LI)

1805 << "failed to hoist load with loop-invariant address "

1806 "because load is conditionally executed";

1807 });

1808 }

1809

1810 return GuaranteedToExecute;

1811}

1812

1813namespace {

1815 Value *SomePtr;

1823 Align Alignment;

1824 bool UnorderedAtomic;

1827 bool CanInsertStoresInExitBlocks;

1829

1830

1831

1832

1835 return V;

1836

1838

1839

1841 I->getName() + ".lcssa");

1845 return PN;

1846 }

1847

1848public:

1854 Align Alignment, bool UnorderedAtomic, const AAMDNodes &AATags,

1855 ICFLoopSafetyInfo &SafetyInfo, bool CanInsertStoresInExitBlocks)

1857 LoopInsertPts(LIP), MSSAInsertPts(MSSAIP), PredCache(PIC), MSSAU(MSSAU),

1858 LI(li), DL(std::move(dl)), Alignment(Alignment),

1859 UnorderedAtomic(UnorderedAtomic), AATags(AATags),

1860 SafetyInfo(SafetyInfo),

1861 CanInsertStoresInExitBlocks(CanInsertStoresInExitBlocks), Uses(Insts) {}

1862

1863 void insertStoresInLoopExitBlocks() {

1864

1865

1866

1867

1869 for (unsigned i = 0, e = LoopExitBlocks.size(); i != e; ++i) {

1870 BasicBlock *ExitBlock = LoopExitBlocks[i];

1871 Value *LiveInValue = SSA.GetValueInMiddleOfBlock(ExitBlock);

1872 LiveInValue = maybeInsertLCSSAPHI(LiveInValue, ExitBlock);

1873 Value *Ptr = maybeInsertLCSSAPHI(SomePtr, ExitBlock);

1876 if (UnorderedAtomic)

1877 NewSI->setOrdering(AtomicOrdering::Unordered);

1880

1881

1882 if (i == 0) {

1883

1884

1885

1887 NewID = cast_or_null(

1888 NewSI->getMetadata(LLVMContext::MD_DIAssignID));

1889 } else {

1890

1891

1892 NewSI->setMetadata(LLVMContext::MD_DIAssignID, NewID);

1893 }

1894

1895 if (AATags)

1897

1898 MemoryAccess *MSSAInsertPoint = MSSAInsertPts[i];

1900 if (!MSSAInsertPoint) {

1903 } else {

1904 NewMemAcc =

1906 }

1907 MSSAInsertPts[i] = NewMemAcc;

1908 MSSAU.insertDef(cast(NewMemAcc), true);

1909

1910 }

1911 }

1912

1913 void doExtraRewritesBeforeFinalDeletion() override {

1914 if (CanInsertStoresInExitBlocks)

1915 insertStoresInLoopExitBlocks();

1916 }

1917

1918 void instructionDeleted(Instruction *I) const override {

1921 }

1922

1923 bool shouldDelete(Instruction *I) const override {

1924 if (isa(I))

1925 return CanInsertStoresInExitBlocks;

1926 return true;

1927 }

1928};

1929

1930bool isNotCapturedBeforeOrInLoop(const Value *V, const Loop *L,

1932

1933

1934

1935

1937 true,

1938 L->getHeader()->getTerminator(), DT);

1939}

1940

1941

1942

1943bool isNotVisibleOnUnwindInLoop(const Value *Object, const Loop *L,

1945 bool RequiresNoCaptureBeforeUnwind;

1947 return false;

1948

1949 return !RequiresNoCaptureBeforeUnwind ||

1950 isNotCapturedBeforeOrInLoop(Object, L, DT);

1951}

1952

1955

1956

1958 isNotCapturedBeforeOrInLoop(Object, L, DT)) ||

1960}

1961

1962}

1963

1964

1965

1966

1967

1968

1978 bool HasReadsOutsideSet) {

1979

1980 assert(LI != nullptr && DT != nullptr && CurLoop != nullptr &&

1981 SafetyInfo != nullptr &&

1982 "Unexpected Input to promoteLoopAccessesToScalars");

1983

1985 dbgs() << "Trying to promote set of must-aliased pointers:\n";

1986 for (Value *Ptr : PointerMustAliases)

1987 dbgs() << " " << *Ptr << "\n";

1988 });

1989 ++NumPromotionCandidates;

1990

1991 Value *SomePtr = *PointerMustAliases.begin();

1993

1994

1995

1996

1997

1998

1999

2000

2001

2002

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013

2014

2015

2016

2017

2018

2019

2020

2021

2022

2023

2024

2025

2026

2027

2028

2029

2030

2031 bool DereferenceableInPH = false;

2032 bool StoreIsGuanteedToExecute = false;

2033 bool LoadIsGuaranteedToExecute = false;

2034 bool FoundLoadToPromote = false;

2035

2036

2037 enum {

2038 StoreSafe,

2039 StoreUnsafe,

2040 StoreSafetyUnknown,

2041 } StoreSafety = StoreSafetyUnknown;

2042

2044

2045

2046

2047 Align Alignment;

2048

2049 bool SawUnorderedAtomic = false;

2050 bool SawNotAtomic = false;

2052

2054

2055

2056

2057 if (HasReadsOutsideSet)

2058 StoreSafety = StoreUnsafe;

2059

2060 if (StoreSafety == StoreSafetyUnknown && SafetyInfo->anyBlockMayThrow()) {

2061

2062

2063

2064

2065

2067 if (!isNotVisibleOnUnwindInLoop(Object, CurLoop, DT))

2068 StoreSafety = StoreUnsafe;

2069 }

2070

2071

2072

2073

2074 Type *AccessTy = nullptr;

2075 for (Value *ASIV : PointerMustAliases) {

2076 for (Use &U : ASIV->uses()) {

2077

2078 Instruction *UI = dyn_cast(U.getUser());

2079 if (!UI || !CurLoop->contains(UI))

2080 continue;

2081

2082

2083

2084 if (LoadInst *Load = dyn_cast(UI)) {

2085 if (!Load->isUnordered())

2086 return false;

2087

2088 SawUnorderedAtomic |= Load->isAtomic();

2089 SawNotAtomic |= !Load->isAtomic();

2090 FoundLoadToPromote = true;

2091

2092 Align InstAlignment = Load->getAlign();

2093

2094 if (!LoadIsGuaranteedToExecute)

2095 LoadIsGuaranteedToExecute =

2097

2098

2099

2100

2101

2102 if (!DereferenceableInPH || (InstAlignment > Alignment))

2104 *Load, DT, TLI, CurLoop, SafetyInfo, ORE,

2105 Preheader->getTerminator(), AC, AllowSpeculation)) {

2106 DereferenceableInPH = true;

2107 Alignment = std::max(Alignment, InstAlignment);

2108 }

2109 } else if (const StoreInst *Store = dyn_cast(UI)) {

2110

2111

2113 continue;

2114 if (!Store->isUnordered())

2115 return false;

2116

2117 SawUnorderedAtomic |= Store->isAtomic();

2118 SawNotAtomic |= !Store->isAtomic();

2119

2120

2121

2122

2123

2124

2125 Align InstAlignment = Store->getAlign();

2126 bool GuaranteedToExecute =

2128 StoreIsGuanteedToExecute |= GuaranteedToExecute;

2129 if (GuaranteedToExecute) {

2130 DereferenceableInPH = true;

2131 if (StoreSafety == StoreSafetyUnknown)

2132 StoreSafety = StoreSafe;

2133 Alignment = std::max(Alignment, InstAlignment);

2134 }

2135

2136

2137

2138

2139

2140

2141

2142 if (StoreSafety == StoreSafetyUnknown &&

2144 return DT->dominates(Store->getParent(), Exit);

2145 }))

2146 StoreSafety = StoreSafe;

2147

2148

2149

2150 if (!DereferenceableInPH) {

2152 Store->getPointerOperand(), Store->getValueOperand()->getType(),

2153 Store->getAlign(), MDL, Preheader->getTerminator(), AC, DT, TLI);

2154 }

2155 } else

2156 continue;

2157

2158 if (!AccessTy)

2161 return false;

2162

2163

2164 if (LoopUses.empty()) {

2165

2167 } else if (AATags) {

2169 }

2170

2172 }

2173 }

2174

2175

2176

2177

2178

2179 if (SawUnorderedAtomic && SawNotAtomic)

2180 return false;

2181

2182

2183

2184

2185 if (SawUnorderedAtomic && Alignment < MDL.getTypeStoreSize(AccessTy))

2186 return false;

2187

2188

2189 if (!DereferenceableInPH) {

2190 LLVM_DEBUG(dbgs() << "Not promoting: Not dereferenceable in preheader\n");

2191 return false;

2192 }

2193

2194

2195

2196

2197

2198 if (StoreSafety == StoreSafetyUnknown) {

2200 bool ExplicitlyDereferenceableOnly;

2201 if (isWritableObject(Object, ExplicitlyDereferenceableOnly) &&

2202 (!ExplicitlyDereferenceableOnly ||

2204 isThreadLocalObject(Object, CurLoop, DT, TTI))

2205 StoreSafety = StoreSafe;

2206 }

2207

2208

2209

2210 if (StoreSafety != StoreSafe && !FoundLoadToPromote)

2211

2212 return false;

2213

2214

2215 if (StoreSafety == StoreSafe) {

2216 LLVM_DEBUG(dbgs() << "LICM: Promoting load/store of the value: " << *SomePtr

2217 << '\n');

2218 ++NumLoadStorePromoted;

2219 } else {

2220 LLVM_DEBUG(dbgs() << "LICM: Promoting load of the value: " << *SomePtr

2221 << '\n');

2222 ++NumLoadPromoted;

2223 }

2224

2225 ORE->emit([&]() {

2227 LoopUses[0])

2228 << "Moving accesses to memory location out of the loop";

2229 });

2230

2231

2232 std::vector<DILocation *> LoopUsesLocs;

2233 for (auto *U : LoopUses)

2234 LoopUsesLocs.push_back(U->getDebugLoc().get());

2236

2237

2240 LoopPromoter Promoter(SomePtr, LoopUses, SSA, ExitBlocks, InsertPts,

2241 MSSAInsertPts, PIC, MSSAU, *LI, DL, Alignment,

2242 SawUnorderedAtomic,

2243 StoreIsGuanteedToExecute ? AATags : AAMDNodes(),

2244 *SafetyInfo, StoreSafety == StoreSafe);

2245

2246

2247

2248 LoadInst *PreheaderLoad = nullptr;

2249 if (FoundLoadToPromote || !StoreIsGuanteedToExecute) {

2250 PreheaderLoad =

2251 new LoadInst(AccessTy, SomePtr, SomePtr->getName() + ".promoted",

2253 if (SawUnorderedAtomic)

2257 if (AATags && LoadIsGuaranteedToExecute)

2259

2262 MemoryUse *NewMemUse = cast(PreheaderLoadMemoryAccess);

2263 MSSAU.insertUse(NewMemUse, true);

2264 SSA.AddAvailableValue(Preheader, PreheaderLoad);

2265 } else {

2267 }

2268

2271

2272

2273 Promoter.run(LoopUses);

2274

2277

2278 if (PreheaderLoad && PreheaderLoad->use_empty())

2280

2281 return true;

2282}

2283

2286 for (const BasicBlock *BB : L->blocks())

2288 for (const auto &Access : *Accesses)

2289 if (const auto *MUD = dyn_cast(&Access))

2290 Fn(MUD->getMemoryInst());

2291}

2292

2293

2294

2299

2300 auto IsPotentiallyPromotable = [L](const Instruction *I) {

2301 if (const auto *SI = dyn_cast(I))

2302 return L->isLoopInvariant(SI->getPointerOperand());

2303 if (const auto *LI = dyn_cast(I))

2304 return L->isLoopInvariant(LI->getPointerOperand());

2305 return false;

2306 };

2307

2308

2311 if (IsPotentiallyPromotable(I)) {

2312 AttemptingPromotion.insert(I);

2314 }

2315 });

2316

2317

2320 if (!AS.isForwardingAliasSet() && AS.isMod() && AS.isMustAlias())

2322

2323 if (Sets.empty())

2324 return {};

2325

2326

2328 if (AttemptingPromotion.contains(I))

2329 return;

2330

2332 ModRefInfo MR = Pair.getPointer()->aliasesUnknownInst(I, BatchAA);

2333

2334 if (isModSet(MR))

2335 return true;

2336 if (isRefSet(MR)) {

2337

2338 Pair.setInt(true);

2339

2340

2341 return !Pair.getPointer()->isRef();

2342 }

2343 return false;

2344 });

2345 });

2346

2348 for (auto [Set, HasReadsOutsideSet] : Sets) {

2350 for (const auto &MemLoc : *Set)

2351 PointerMustAliases.insert(const_cast<Value *>(MemLoc.Ptr));

2352 Result.emplace_back(std::move(PointerMustAliases), HasReadsOutsideSet);

2353 }

2354

2356}

2357

2361 bool InvariantGroup) {

2362

2363 if (!Flags.getIsSink()) {

2364

2365

2366

2367

2368

2369

2370

2371

2372

2376 CurLoop->contains(Source->getBlock()) &&

2377 !(InvariantGroup && Source->getBlock() == CurLoop->getHeader() && isa(Source));

2378 }

2379

2380

2381

2382

2383

2384

2385

2386

2387

2388

2389

2390

2391

2392

2393

2394

2395

2396

2397 if (Flags.tooManyMemoryAccesses())

2398 return true;

2399 for (auto *BB : CurLoop->getBlocks())

2401 return true;

2402

2405

2406 return false;

2407}

2408

2410 if (const auto *Accesses = MSSA.getBlockDefs(&BB))

2411 for (const auto &MA : *Accesses)

2412 if (const auto *MD = dyn_cast(&MA))

2414 return true;

2415 return false;

2416}

2417

2418

2419

2420

2424 using namespace PatternMatch;

2425 Value *Cond1, *Cond2;

2429

2430 } else

2431 return false;

2432

2436 return false;

2438 return false;

2440 return false;

2441 if (L.isLoopInvariant(LHS)) {

2444 }

2445 if (L.isLoopInvariant(LHS) || !L.isLoopInvariant(RHS))

2446 return false;

2449 return true;

2450 };

2452 Value *LHS1, *LHS2, *RHS1, *RHS2;

2453 if (!MatchICmpAgainstInvariant(Cond1, P1, LHS1, RHS1) ||

2454 !MatchICmpAgainstInvariant(Cond2, P2, LHS2, RHS2))

2455 return false;

2457 if (!MatchingPred || LHS1 != LHS2)

2458 return false;

2459

2460

2465 "Relational predicate is either less (or equal) or greater (or equal)!");

2467 ? (UseMin ? Intrinsic::smin : Intrinsic::smax)

2468 : (UseMin ? Intrinsic::umin : Intrinsic::umax);

2469 auto *Preheader = L.getLoopPreheader();

2470 assert(Preheader && "Loop is not in simplify form?");

2472

2473

2474

2475

2476 if (isa(I))

2479 id, RHS1, RHS2, nullptr,

2482 (UseMin ? "min" : "max"));

2489 I.replaceAllUsesWith(NewCond);

2491 eraseInstruction(*cast(Cond1), SafetyInfo, MSSAU);

2492 eraseInstruction(*cast(Cond2), SafetyInfo, MSSAU);

2493 return true;

2494}

2495

2496

2497

2501 auto *GEP = dyn_cast(&I);

2502 if (GEP)

2503 return false;

2504

2505 auto *Src = dyn_cast(GEP->getPointerOperand());

2506 if (!Src || !Src->hasOneUse() || !L.contains(Src))

2507 return false;

2508

2509 Value *SrcPtr = Src->getPointerOperand();

2510 auto LoopInvariant = [&](Value *V) { return L.isLoopInvariant(V); };

2511 if (!L.isLoopInvariant(SrcPtr) || all\_of(GEP->indices(), LoopInvariant))

2512 return false;

2513

2514

2515

2516

2517

2518 if (all_of(Src->indices(), LoopInvariant))

2519 return false;

2520

2521

2522

2523

2527 };

2528 bool IsInBounds = Src->isInBounds() && GEP->isInBounds() &&

2531

2532 BasicBlock *Preheader = L.getLoopPreheader();

2534 Value *NewSrc = Builder.CreateGEP(GEP->getSourceElementType(), SrcPtr,

2536 "invariant.gep", IsInBounds);

2538 Value *NewGEP = Builder.CreateGEP(Src->getSourceElementType(), NewSrc,

2540 IsInBounds);

2541 GEP->replaceAllUsesWith(NewGEP);

2544 return true;

2545}

2546

2547

2548

2553 assert(!L.isLoopInvariant(VariantLHS) && "Precondition.");

2554 assert(L.isLoopInvariant(InvariantRHS) && "Precondition.");

2555

2557

2558

2559 using namespace PatternMatch;

2560 Value *VariantOp, *InvariantOp;

2561 if (IsSigned &&

2563 return false;

2564 if (!IsSigned &&

2566 return false;

2567

2568

2569

2570 if (L.isLoopInvariant(VariantOp))

2571 std::swap(VariantOp, InvariantOp);

2572 if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp))

2573 return false;

2574

2575

2576

2577

2578

2579 auto &DL = L.getHeader()->getDataLayout();

2583 return false;

2584 if (!IsSigned &&

2587 return false;

2588 auto *Preheader = L.getLoopPreheader();

2589 assert(Preheader && "Loop is not in simplify form?");

2591 Value *NewCmpOp =

2592 Builder.CreateSub(InvariantRHS, InvariantOp, "invariant.op",

2593 !IsSigned, IsSigned);

2597 eraseInstruction(cast(*VariantLHS), SafetyInfo, MSSAU);

2598 return true;

2599}

2600

2601

2602

2603

2608 assert(!L.isLoopInvariant(VariantLHS) && "Precondition.");

2609 assert(L.isLoopInvariant(InvariantRHS) && "Precondition.");

2610

2612

2613

2614 using namespace PatternMatch;

2615 Value *VariantOp, *InvariantOp;

2616 if (IsSigned &&

2618 return false;

2619 if (!IsSigned &&

2621 return false;

2622

2623 bool VariantSubtracted = false;

2624

2625

2626

2627 if (L.isLoopInvariant(VariantOp)) {

2628 std::swap(VariantOp, InvariantOp);

2629 VariantSubtracted = true;

2631 }

2632 if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp))

2633 return false;

2634

2635

2636

2637

2638

2639

2640 auto &DL = L.getHeader()->getDataLayout();

2642 if (VariantSubtracted && IsSigned) {

2643

2646 return false;

2647 } else if (VariantSubtracted && !IsSigned) {

2648

2651 return false;

2652 } else if (!VariantSubtracted && IsSigned) {

2653

2656 return false;

2657 } else {

2658

2661 return false;

2662 }

2663 auto *Preheader = L.getLoopPreheader();

2664 assert(Preheader && "Loop is not in simplify form?");

2666 Value *NewCmpOp =

2667 VariantSubtracted

2668 ? Builder.CreateSub(InvariantOp, InvariantRHS, "invariant.op",

2669 !IsSigned, IsSigned)

2670 : Builder.CreateAdd(InvariantOp, InvariantRHS, "invariant.op",

2671 !IsSigned, IsSigned);

2675 eraseInstruction(cast(*VariantLHS), SafetyInfo, MSSAU);

2676 return true;

2677}

2678

2679

2683 using namespace PatternMatch;

2687 return false;

2688

2689

2690 if (L.isLoopInvariant(LHS)) {

2693 }

2694

2695

2696 if (L.isLoopInvariant(LHS) || !L.isLoopInvariant(RHS) || LHS->hasOneUse())

2697 return false;

2698

2699

2700

2701 if (hoistAdd(Pred, LHS, RHS, cast(I), L, SafetyInfo, MSSAU, AC, DT))

2702 return true;

2703

2704 if (hoistSub(Pred, LHS, RHS, cast(I), L, SafetyInfo, MSSAU, AC, DT))

2705 return true;

2706

2707 return false;

2708}

2709

2711 unsigned FPOpcode) {

2712 if (I->getOpcode() == IntOpcode)

2713 return true;

2714 if (I->getOpcode() == FPOpcode && I->hasAllowReassoc() &&

2715 I->hasNoSignedZeros())

2716 return true;

2717 return false;

2718}

2719

2720

2721

2722

2723

2724

2730 return false;

2731 Value *VariantOp = I.getOperand(0);

2732 Value *InvariantOp = I.getOperand(1);

2733 if (L.isLoopInvariant(VariantOp))

2734 std::swap(VariantOp, InvariantOp);

2735 if (L.isLoopInvariant(VariantOp) || !L.isLoopInvariant(InvariantOp))

2736 return false;

2737 Value *Factor = InvariantOp;

2738

2739

2743 if (BinaryOperator *VariantBinOp = dyn_cast(VariantOp))

2744 Worklist.push_back(VariantBinOp);

2745 while (!Worklist.empty()) {

2748 return false;

2749 if (isReassociableOp(BO, Instruction::Add, Instruction::FAdd) &&

2750 isa(BO->getOperand(0)) &&

2751 isa(BO->getOperand(1))) {

2755 continue;

2756 }

2757 if (isReassociableOp(BO, Instruction::Mul, Instruction::FMul) ||

2758 L.isLoopInvariant(BO))

2759 return false;

2762 if (L.isLoopInvariant(U0))

2764 else if (L.isLoopInvariant(U1))

2766 else

2767 return false;

2768 unsigned Limit = I.getType()->isIntOrIntVectorTy()

2771 if (Changes.size() > Limit)

2772 return false;

2773 }

2774 if (Changes.empty())

2775 return false;

2776

2777

2778 if (I.getType()->isIntOrIntVectorTy()) {

2779 for (auto *Add : Adds)

2780 Add->dropPoisonGeneratingFlags();

2781 }

2782

2783

2784 auto *Preheader = L.getLoopPreheader();

2785 assert(Preheader && "Loop is not in simplify form?");

2787 for (auto *U : Changes) {

2788 assert(L.isLoopInvariant(U->get()));

2789 auto *Ins = cast(U->getUser());

2791 if (I.getType()->isIntOrIntVectorTy()) {

2792 Mul = Builder.CreateMul(U->get(), Factor, "factor.op.mul");

2793

2794 Ins->dropPoisonGeneratingFlags();

2795 } else

2796 Mul = Builder.CreateFMulFMF(U->get(), Factor, Ins, "factor.op.fmul");

2797

2798

2799 unsigned OpIdx = U->getOperandNo();

2800 auto *LHS = OpIdx == 0 ? Mul : Ins->getOperand(0);

2801 auto *RHS = OpIdx == 1 ? Mul : Ins->getOperand(1);

2802 auto *NewBO =

2804 Ins->getName() + ".reass", Ins->getIterator());

2805 NewBO->copyIRFlags(Ins);

2806 if (VariantOp == Ins)

2807 VariantOp = NewBO;

2808 Ins->replaceAllUsesWith(NewBO);

2810 }

2811

2812 I.replaceAllUsesWith(VariantOp);

2814 return true;

2815}

2816

2817

2818

2819

2820

2821

2822

2823

2824

2825

2826

2831 auto *BO = dyn_cast(&I);

2832 if (!BO || !BO->isAssociative())

2833 return false;

2834

2836 bool LVInRHS = L.isLoopInvariant(BO->getOperand(0));

2837 auto *BO0 = dyn_cast(BO->getOperand(LVInRHS));

2838 if (!BO0 || BO0->getOpcode() != Opcode || !BO0->isAssociative() ||

2839 BO0->hasNUsesOrMore(3))

2840 return false;

2841

2842 Value *LV = BO0->getOperand(0);

2843 Value *C1 = BO0->getOperand(1);

2844 Value *C2 = BO->getOperand(!LVInRHS);

2845

2846 assert(BO->isCommutative() && BO0->isCommutative() &&

2847 "Associativity implies commutativity");

2848 if (L.isLoopInvariant(LV) && !L.isLoopInvariant(C1))

2850 if (L.isLoopInvariant(LV) || !L.isLoopInvariant(C1) || !L.isLoopInvariant(C2))

2851 return false;

2852

2853 auto *Preheader = L.getLoopPreheader();

2854 assert(Preheader && "Loop is not in simplify form?");

2855

2857 auto *Inv = Builder.CreateBinOp(Opcode, C1, C2, "invariant.op");

2858

2860 Opcode, LV, Inv, BO->getName() + ".reass", BO->getIterator());

2861

2862

2863 if (Opcode == Instruction::Add && BO->hasNoUnsignedWrap() &&

2864 BO0->hasNoUnsignedWrap()) {

2865

2866 if (auto *I = dyn_cast(Inv))

2867 I->setHasNoUnsignedWrap(true);

2868 NewBO->setHasNoUnsignedWrap(true);

2869 } else if (Opcode == Instruction::FAdd || Opcode == Instruction::FMul) {

2870

2871 FastMathFlags Intersect = BO->getFastMathFlags() & BO0->getFastMathFlags();

2872 if (auto *I = dyn_cast(Inv))

2873 I->setFastMathFlags(Intersect);

2874 NewBO->setFastMathFlags(Intersect);

2875 }

2876

2877 BO->replaceAllUsesWith(NewBO);

2879

2880

2881

2882 if (BO0->use_empty())

2884

2885 return true;

2886}

2887

2892

2893

2894

2896 ++NumHoisted;

2897 ++NumMinMaxHoisted;

2898 return true;

2899 }

2900

2901

2902 if (hoistGEP(I, L, SafetyInfo, MSSAU, AC, DT)) {

2903 ++NumHoisted;

2904 ++NumGEPsHoisted;

2905 return true;

2906 }

2907

2908

2909 if (hoistAddSub(I, L, SafetyInfo, MSSAU, AC, DT)) {

2910 ++NumHoisted;

2911 ++NumAddSubHoisted;

2912 return true;

2913 }

2914

2915 bool IsInt = I.getType()->isIntOrIntVectorTy();

2917 ++NumHoisted;

2918 if (IsInt)

2919 ++NumIntAssociationsHoisted;

2920 else

2921 ++NumFPAssociationsHoisted;

2922 return true;

2923 }

2924

2926 ++NumHoisted;

2927 ++NumBOAssociationsHoisted;

2928 return true;

2929 }

2930

2931 return false;

2932}

2933

2934

2935

2936

2938 assert(CurLoop->contains(BB) && "Only valid if BB is IN the loop");

2939 return LI->getLoopFor(BB) != CurLoop;

2940}

unsigned const MachineRegisterInfo * MRI

static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

This file provides various utilities for inspecting and working with the control flow graph in LLVM I...

iv Induction Variable Users

static bool isReassociableOp(Instruction *I, unsigned IntOpcode, unsigned FPOpcode)

static bool isNotUsedOrFoldableInLoop(const Instruction &I, const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, TargetTransformInfo *TTI, bool &FoldableInLoop, bool LoopNestMode)

Return true if the only users of this instruction are outside of the loop.

static bool hoistGEP(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, DominatorTree *DT)

Reassociate gep (gep ptr, idx1), idx2 to gep (gep ptr, idx2), idx1 if this allows hoisting the inner ...

static cl::opt< bool > SingleThread("licm-force-thread-model-single", cl::Hidden, cl::init(false), cl::desc("Force thread model single in LICM pass"))

static void splitPredecessorsOfLoopExit(PHINode *PN, DominatorTree *DT, LoopInfo *LI, const Loop *CurLoop, LoopSafetyInfo *SafetyInfo, MemorySSAUpdater *MSSAU)

static cl::opt< unsigned > FPAssociationUpperLimit("licm-max-num-fp-reassociations", cl::init(5U), cl::Hidden, cl::desc("Set upper limit for the number of transformations performed " "during a single round of hoisting the reassociated expressions."))

static bool isFoldableInLoop(const Instruction &I, const Loop *CurLoop, const TargetTransformInfo *TTI)

Return true if the instruction is foldable in the loop.

static bool hoistMinMax(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU)

Try to simplify things like (A < INV_1 AND icmp A < INV_2) into (A < min(INV_1, INV_2)),...

static void moveInstructionBefore(Instruction &I, BasicBlock::iterator Dest, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, ScalarEvolution *SE)

static Instruction * cloneInstructionInExitBlock(Instruction &I, BasicBlock &ExitBlock, PHINode &PN, const LoopInfo *LI, const LoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU)

static cl::opt< bool > ControlFlowHoisting("licm-control-flow-hoisting", cl::Hidden, cl::init(false), cl::desc("Enable control flow (and PHI) hoisting in LICM"))

static bool pointerInvalidatedByLoop(MemorySSA *MSSA, MemoryUse *MU, Loop *CurLoop, Instruction &I, SinkAndHoistLICMFlags &Flags, bool InvariantGroup)

static bool hoistAdd(ICmpInst::Predicate Pred, Value *VariantLHS, Value *InvariantRHS, ICmpInst &ICmp, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, DominatorTree *DT)

Try to turn things like "LV + C1 < C2" into "LV < C2 - C1".

static MemoryAccess * getClobberingMemoryAccess(MemorySSA &MSSA, BatchAAResults &BAA, SinkAndHoistLICMFlags &Flags, MemoryUseOrDef *MA)

static SmallVector< PointersAndHasReadsOutsideSet, 0 > collectPromotionCandidates(MemorySSA *MSSA, AliasAnalysis *AA, Loop *L)

static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, BasicBlock *Dest, ICFLoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU, ScalarEvolution *SE, OptimizationRemarkEmitter *ORE)

When an instruction is found to only use loop invariant operands that is safe to hoist,...

static bool canSplitPredecessors(PHINode *PN, LoopSafetyInfo *SafetyInfo)

static bool sink(Instruction &I, LoopInfo *LI, DominatorTree *DT, const Loop *CurLoop, ICFLoopSafetyInfo *SafetyInfo, MemorySSAUpdater &MSSAU, OptimizationRemarkEmitter *ORE)

When an instruction is found to only be used outside of the loop, this function moves it to the exit ...

static bool hoistAddSub(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, DominatorTree *DT)

Reassociate and hoist add/sub expressions.

static bool hoistMulAddAssociation(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, DominatorTree *DT)

Try to reassociate expressions like ((A1 * B1) + (A2 * B2) + ...) * C where A1, A2,...

static cl::opt< uint32_t > MaxNumUsesTraversed("licm-max-num-uses-traversed", cl::Hidden, cl::init(8), cl::desc("Max num uses visited for identifying load " "invariance in loop using invariant start (default = 8)"))

cl::opt< unsigned > IntAssociationUpperLimit("licm-max-num-int-reassociations", cl::init(5U), cl::Hidden, cl::desc("Set upper limit for the number of transformations performed " "during a single round of hoisting the reassociated expressions."))

static void foreachMemoryAccess(MemorySSA *MSSA, Loop *L, function_ref< void(Instruction *)> Fn)

static bool isLoadInvariantInLoop(LoadInst *LI, DominatorTree *DT, Loop *CurLoop)

static Instruction * sinkThroughTriviallyReplaceablePHI(PHINode *TPN, Instruction *I, LoopInfo *LI, SmallDenseMap< BasicBlock *, Instruction *, 32 > &SunkCopies, const LoopSafetyInfo *SafetyInfo, const Loop *CurLoop, MemorySSAUpdater &MSSAU)

static bool inSubLoop(BasicBlock *BB, Loop *CurLoop, LoopInfo *LI)

Little predicate that returns true if the specified basic block is in a subloop of the current one,...

static bool hoistSub(ICmpInst::Predicate Pred, Value *VariantLHS, Value *InvariantRHS, ICmpInst &ICmp, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, DominatorTree *DT)

Try to reassociate and hoist the following two patterns: LV - C1 < C2 --> LV < C1 + C2,...

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

static bool isSafeToExecuteUnconditionally(Instruction &Inst, const DominatorTree *DT, const TargetLibraryInfo *TLI, const Loop *CurLoop, const LoopSafetyInfo *SafetyInfo, OptimizationRemarkEmitter *ORE, const Instruction *CtxI, AssumptionCache *AC, bool AllowSpeculation)

Only sink or hoist an instruction if it is not a trapping instruction, or if the instruction is known...

static bool hoistArithmetics(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, DominatorTree *DT)

Aggregates various functions for hoisting computations out of loop.

static bool isTriviallyReplaceablePHI(const PHINode &PN, const Instruction &I)

Returns true if a PHINode is a trivially replaceable with an Instruction.

std::pair< SmallSetVector< Value *, 8 >, bool > PointersAndHasReadsOutsideSet

static cl::opt< bool > DisablePromotion("disable-licm-promotion", cl::Hidden, cl::init(false), cl::desc("Disable memory promotion in LICM pass"))

Memory promotion is enabled by default.

static bool hoistBOAssociation(Instruction &I, Loop &L, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, AssumptionCache *AC, DominatorTree *DT)

Reassociate associative binary expressions of the form.

static bool pointerInvalidatedByBlock(BasicBlock &BB, MemorySSA &MSSA, MemoryUse &MU)

This file defines the interface for the loop nest analysis.

Machine Loop Invariant Code Motion

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

Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...

uint64_t IntrinsicInst * II

PassInstrumentationCallbacks PIC

#define INITIALIZE_PASS_DEPENDENCY(depName)

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

This file provides a priority worklist.

Remove Loads Into Fake Uses

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

This file defines generic set operations that may be used on set's of different types,...

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

#define STATISTIC(VARNAME, DESC)

This pass exposes codegen information to IR-level passes.

ModRefInfo getModRefInfoMask(const MemoryLocation &Loc, bool IgnoreLocals=false)

Returns a bitmask that should be unconditionally applied to the ModRef info of a memory location.

MemoryEffects getMemoryEffects(const CallBase *Call)

Return the behavior of the given call site.

void add(const MemoryLocation &Loc)

These methods are used to add different types of instructions to the alias sets.

A container for analyses that lazily runs them and caches their results.

Represent the analysis usage information of a pass.

AnalysisUsage & addRequired()

AnalysisUsage & addPreserved()

Add the specified Pass class to the set of analyses preserved by this pass.

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

An immutable pass that tracks lazily created AssumptionCache objects.

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

LLVM Basic Block Representation.

void replaceSuccessorsPhiUsesWith(BasicBlock *Old, BasicBlock *New)

Update all phi nodes in this basic block's successors to refer to basic block New instead of basic bl...

iterator begin()

Instruction iterator methods.

const_iterator getFirstInsertionPt() const

Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...

InstListType::const_iterator getFirstNonPHIIt() const

Iterator returning form of getFirstNonPHI.

const Instruction * getFirstNonPHI() const

Returns a pointer to the first instruction in this block that is not a PHINode instruction.

static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)

Creates a new BasicBlock.

const BasicBlock * getSingleSuccessor() const

Return the successor of this block if it has a single successor.

const Function * getParent() const

Return the enclosing method, or null if none.

const DataLayout & getDataLayout() const

Get the data layout of the module this basic block belongs to.

InstListType::iterator iterator

Instruction iterators...

LLVMContext & getContext() const

Get the context in which this basic block lives.

void moveBefore(BasicBlock *MovePos)

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

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

bool canSplitPredecessors() const

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

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

static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), InsertPosition InsertBefore=nullptr)

Construct a binary instruction, given the opcode and the two operands.

Conditional or Unconditional Branch instruction.

bool isConditional() const

static BranchInst * Create(BasicBlock *IfTrue, InsertPosition InsertBefore=nullptr)

BasicBlock * getSuccessor(unsigned i) const

Value * getCondition() const

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

static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

void setPredicate(Predicate P)

Set the predicate for this instruction to the specified value.

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

Predicate getSwappedPredicate() const

For example, EQ->EQ, SLE->SGE, ULT->UGT, OEQ->OEQ, ULE->UGE, OLT->OGT, etc.

Predicate getInversePredicate() const

For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...

An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...

static std::optional< CmpPredicate > getMatching(CmpPredicate A, CmpPredicate B)

Compares two CmpPredicates taking samesign into account and returns the canonicalized CmpPredicate if...

This is the shared class of boolean and integer constants.

int64_t getSExtValue() const

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

static DILocation * getMergedLocations(ArrayRef< DILocation * > Locs)

Try to combine the vector of locations passed as input in a single one.

This class represents an Operation in the Expression.

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

TypeSize getTypeStoreSize(Type *Ty) const

Returns the maximum number of bytes that may be overwritten by storing the specified type.

iterator find(const_arg_type_t< KeyT > Val)

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

DomTreeNodeBase * getIDom() const

Analysis pass which computes a DominatorTree.

bool verify(VerificationLevel VL=VerificationLevel::Full) const

verify - checks if the tree is correct.

void changeImmediateDominator(DomTreeNodeBase< NodeT > *N, DomTreeNodeBase< NodeT > *NewIDom)

changeImmediateDominator - This method is used to update the dominator tree information when a node's...

DomTreeNodeBase< NodeT > * addNewBlock(NodeT *BB, NodeT *DomBB)

Add a new node to the dominator tree information.

DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const

getNode - return the (Post)DominatorTree node for the specified basic block.

bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const

properlyDominates - Returns true iff A dominates B and A != B.

Legacy analysis pass which computes a DominatorTree.

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

bool isReachableFromEntry(const Use &U) const

Provide an overload for a Use.

bool dominates(const BasicBlock *BB, const Use &U) const

Return true if the (end of the) basic block BB dominates the use U.

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

This implementation of LoopSafetyInfo use ImplicitControlFlowTracking to give precise answers on "may...

bool doesNotWriteMemoryBefore(const BasicBlock *BB, const Loop *CurLoop) const

Returns true if we could not execute a memory-modifying instruction before we enter BB under assumpti...

void removeInstruction(const Instruction *Inst)

Inform safety info that we are planning to remove the instruction Inst from its block.

bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop) const override

Returns true if the instruction in a loop is guaranteed to execute at least once (under the assumptio...

bool anyBlockMayThrow() const override

Returns true iff any block of the loop for which this info is contains an instruction that may throw ...

void computeLoopSafetyInfo(const Loop *CurLoop) override

Computes safety information for a loop checks loop body & header for the possibility of may throw exc...

void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB)

Inform the safety info that we are planning to insert a new instruction Inst into the basic block BB.

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

static bool isGE(Predicate P)

Return true if the predicate is SGE or UGE.

static bool isLT(Predicate P)

Return true if the predicate is SLT or ULT.

static bool isGT(Predicate P)

Return true if the predicate is SGT or UGT.

bool isRelational() const

Return true if the predicate is relational (not EQ or NE).

static bool isLE(Predicate P)

Return true if the predicate is SLE or ULE.

Value * CreateFreeze(Value *V, const Twine &Name="")

Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())

Value * CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, FMFSource FMFSource={}, const Twine &Name="")

Create a call to intrinsic ID with 2 operands which is mangled on the first type.

Value * CreateSub(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

Value * CreateBinOp(Instruction::BinaryOps Opc, Value *LHS, Value *RHS, const Twine &Name="", MDNode *FPMathTag=nullptr)

void SetInsertPoint(BasicBlock *TheBB)

This specifies that created instructions should be appended to the end of the specified block.

Value * CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name="")

Value * CreateFMulFMF(Value *L, Value *R, FMFSource FMFSource, const Twine &Name="", MDNode *FPMD=nullptr)

Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

void mergeDIAssignID(ArrayRef< const Instruction * > SourceInstructions)

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

void insertBefore(Instruction *InsertPos)

Insert an unlinked instruction into a basic block immediately before the specified instruction.

void setAAMetadata(const AAMDNodes &N)

Sets the AA metadata on this instruction from the AAMDNodes structure.

bool isEHPad() const

Return true if the instruction is a variety of EH-block.

Instruction * user_back()

Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...

MDNode * getMetadata(unsigned KindID) const

Get the metadata of given kind attached to this Instruction.

void setMetadata(unsigned KindID, MDNode *Node)

Set the metadata of the specified kind to the specified node.

AAMDNodes getAAMetadata() const

Returns the AA metadata for this instruction.

void setDebugLoc(DebugLoc Loc)

Set the debug location information for this instruction.

const DataLayout & getDataLayout() const

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

A wrapper class for inspecting calls to intrinsic functions.

void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)

PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)

This is an important class for using LLVM in a threaded context.

PreservedAnalyses run(LoopNest &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)

void printPipeline(raw_ostream &OS, function_ref< StringRef(StringRef)> MapClassName2PassName)

This class provides an interface for updating the loop pass manager based on mutations to the loop ne...

This is an alternative analysis pass to BlockFrequencyInfoWrapperPass.

static void getLazyBFIAnalysisUsage(AnalysisUsage &AU)

Helper for client passes to set up the analysis usage on behalf of this pass.

This is an alternative analysis pass to BranchProbabilityInfoWrapperPass.

An instruction for reading from memory.

void setAlignment(Align Align)

Value * getPointerOperand()

void setOrdering(AtomicOrdering Ordering)

Sets the ordering constraint of this load instruction.

Analysis pass that exposes the LoopInfo for a function.

bool contains(const LoopT *L) const

Return true if the specified loop is contained within in this loop.

BlockT * getHeader() const

void addBasicBlockToLoop(BlockT *NewBB, LoopInfoBase< BlockT, LoopT > &LI)

This method is used by other analyses to update loop information.

BlockT * getLoopPreheader() const

If there is a preheader for this loop, return it.

ArrayRef< BlockT * > getBlocks() const

Get a list of the basic blocks which make up this loop.

void getUniqueExitBlocks(SmallVectorImpl< BlockT * > &ExitBlocks) const

Return all unique successor blocks of this loop.

LoopT * getParentLoop() const

Return the parent loop if it exists or nullptr for top level loops.

Wrapper class to LoopBlocksDFS that provides a standard begin()/end() interface for the DFS reverse p...

void perform(const LoopInfo *LI)

Traverse the loop blocks and store the DFS result.

void verify(const DominatorTreeBase< BlockT, false > &DomTree) const

LoopT * getLoopFor(const BlockT *BB) const

Return the inner most loop that BB lives in.

The legacy pass manager's analysis pass to compute loop information.

bool wouldBeOutOfLoopUseRequiringLCSSA(const Value *V, const BasicBlock *ExitBB) const

This class represents a loop nest and can be used to query its properties.

Function * getParent() const

Return the function to which the loop-nest belongs.

Loop & getOutermostLoop() const

Return the outermost loop in the loop nest.

Captures loop safety information.

void copyColors(BasicBlock *New, BasicBlock *Old)

Copy colors of block Old into the block New.

const DenseMap< BasicBlock *, ColorVector > & getBlockColors() const

Returns block colors map that is used to update funclet operand bundles.

virtual bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop) const =0

Returns true if the instruction in a loop is guaranteed to execute at least once (under the assumptio...

Represents a single loop in the control flow graph.

bool hasLoopInvariantOperands(const Instruction *I) const

Return true if all the operands of the specified instruction are loop invariant.

bool isLoopInvariant(const Value *V) const

Return true if the specified value is loop invariant.

BasicBlock * getBlock() const

bool doesNotAccessMemory() const

Whether this function accesses no memory.

bool onlyAccessesArgPointees() const

Whether this function only (at most) accesses argument memory.

bool onlyReadsMemory() const

Whether this function only (at most) reads memory.

static MemoryLocation get(const LoadInst *LI)

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

An analysis that produces MemorySSA for a function.

MemorySSA * getMemorySSA() const

Get handle on MemorySSA.

void insertDef(MemoryDef *Def, bool RenameUses=false)

Insert a definition into the MemorySSA IR.

void insertUse(MemoryUse *Use, bool RenameUses=false)

MemoryAccess * createMemoryAccessInBB(Instruction *I, MemoryAccess *Definition, const BasicBlock *BB, MemorySSA::InsertionPlace Point, bool CreationMustSucceed=true)

Create a MemoryAccess in MemorySSA at a specified point in a block.

void removeMemoryAccess(MemoryAccess *, bool OptimizePhis=false)

Remove a MemoryAccess from MemorySSA, including updating all definitions and uses.

MemoryUseOrDef * createMemoryAccessAfter(Instruction *I, MemoryAccess *Definition, MemoryAccess *InsertPt)

Create a MemoryAccess in MemorySSA after an existing MemoryAccess.

void moveToPlace(MemoryUseOrDef *What, BasicBlock *BB, MemorySSA::InsertionPlace Where)

void wireOldPredecessorsToNewImmediatePredecessor(BasicBlock *Old, BasicBlock *New, ArrayRef< BasicBlock * > Preds, bool IdenticalEdgesWereMerged=true)

A new empty BasicBlock (New) now branches directly to Old.

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

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

Legacy analysis pass which computes MemorySSA.

Encapsulates MemorySSA, including all data associated with memory accesses.

const AccessList * getBlockAccesses(const BasicBlock *BB) const

Return the list of MemoryAccess's for a given basic block.

MemorySSAWalker * getSkipSelfWalker()

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

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

void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const

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

MemoryUseOrDef * getMemoryAccess(const Instruction *I) const

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

const DefsList * getBlockDefs(const BasicBlock *BB) const

Return the list of MemoryDef's and MemoryPhi's for a given basic block.

bool locallyDominates(const MemoryAccess *A, const MemoryAccess *B) const

Given two memory accesses in the same basic block, determine whether MemoryAccess A dominates MemoryA...

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.

Represents read-only accesses to memory.

void addIncoming(Value *V, BasicBlock *BB)

Add an incoming value to the end of the PHI list.

op_range incoming_values()

void setIncomingBlock(unsigned i, BasicBlock *BB)

BasicBlock * getIncomingBlock(unsigned i) const

Return incoming basic block number i.

int getBasicBlockIndex(const BasicBlock *BB) const

Return the first index of the specified basic block in the value list for this PHI.

unsigned getNumIncomingValues() const

Return the number of incoming edges.

static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)

Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...

static PassRegistry * getPassRegistry()

getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...

Pass interface - Implemented by all 'passes'.

PointerIntPair - This class implements a pair of a pointer and small integer.

static PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

PredIteratorCache - This class is an extremely trivial cache for predecessor iterator queries.

size_t size(BasicBlock *BB)

ArrayRef< BasicBlock * > get(BasicBlock *BB)

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.

bool empty() const

Determine if the PriorityWorklist is empty or not.

bool insert(const T &X)

Insert a new element into the PriorityWorklist.

Helper class for SSA formation on a set of values defined in multiple blocks.

The main scalar evolution driver.

void forgetBlockAndLoopDispositions(Value *V=nullptr)

Called when the client has changed the disposition of values in a loop or block.

void forgetLoopDispositions()

Called when the client has changed the disposition of values in this loop.

bool remove(const value_type &X)

Remove an item from the set vector.

bool empty() const

Determine if the SetVector is empty or not.

iterator begin()

Get an iterator to the beginning of the SetVector.

bool insert(const value_type &X)

Insert a new element into the SetVector.

Flags controlling how much is checked when sinking or hoisting instructions.

SinkAndHoistLICMFlags(unsigned LicmMssaOptCap, unsigned LicmMssaNoAccForPromotionCap, bool IsSink, Loop &L, MemorySSA &MSSA)

unsigned LicmMssaNoAccForPromotionCap

A version of PriorityWorklist that selects small size optimized data structures for the vector and ma...

bool erase(PtrType Ptr)

Remove pointer from the set.

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

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

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

bool contains(ConstPtrType Ptr) const

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

A SetVector that performs no allocations if smaller than a certain size.

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

reference emplace_back(ArgTypes &&... Args)

void reserve(size_type N)

void push_back(const T &Elt)

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

An instruction for storing to memory.

void setAlignment(Align Align)

void setOrdering(AtomicOrdering Ordering)

Sets the ordering constraint of this store instruction.

static unsigned getPointerOperandIndex()

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

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

Wrapper pass for TargetTransformInfo.

This pass provides access to the codegen interfaces that are needed for IR-level transformations.

bool isSingleThreaded() const

@ TCK_SizeAndLatency

The weighted sum of size and latency.

@ TCC_Free

Expected to fold away in lowering.

InstructionCost getInstructionCost(const User *U, ArrayRef< const Value * > Operands, TargetCostKind CostKind) const

Estimate the cost of a given IR user when lowered.

TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...

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

bool isIntegerTy() const

True if this is an instance of IntegerType.

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

const Use & getOperandUse(unsigned i) const

void setOperand(unsigned i, Value *Val)

Value * getOperand(unsigned i) const

unsigned getNumOperands() const

LLVM Value Representation.

Type * getType() const

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

bool hasOneUser() const

Return true if there is exactly one user of this value.

std::string getNameOrAsOperand() const

bool hasOneUse() const

Return true if there is exactly one use of this value.

void replaceAllUsesWith(Value *V)

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

user_iterator_impl< User > user_iterator

StringRef getName() const

Return a constant reference to the value's name.

void takeName(Value *V)

Transfer the name from V to this value.

constexpr ScalarTy getFixedValue() const

constexpr bool isScalable() const

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

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

const ParentTy * getParent() const

self_iterator getIterator()

This class implements an extremely fast bulk output stream that can only output to a stream.

@ C

The default llvm calling convention, compatible with C.

unsigned ID

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

OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWAdd(const LHS &L, const RHS &R)

OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoSignedWrap > m_NSWSub(const LHS &L, const RHS &R)

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

OneUse_match< T > m_OneUse(const T &SubPattern)

auto m_LogicalOr()

Matches L || R where L and R are arbitrary values.

OverflowingBinaryOp_match< LHS, RHS, Instruction::Sub, OverflowingBinaryOperator::NoUnsignedWrap > m_NUWSub(const LHS &L, const RHS &R)

class_match< Value > m_Value()

Match an arbitrary value and ignore it.

OverflowingBinaryOp_match< LHS, RHS, Instruction::Add, OverflowingBinaryOperator::NoSignedWrap > m_NSWAdd(const LHS &L, const RHS &R)

CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)

auto m_LogicalAnd()

Matches L && R where L and R are arbitrary values.

initializer< Ty > init(const Ty &Val)

DiagnosticInfoOptimizationBase::Argument NV

This is an optimization pass for GlobalISel generic memory operations.

void ReplaceInstWithInst(BasicBlock *BB, BasicBlock::iterator &BI, Instruction *I)

Replace the instruction specified by BI with the instruction specified by I.

@ NeverOverflows

Never overflows.

bool all_of(R &&range, UnaryPredicate P)

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

bool canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, Loop *CurLoop, MemorySSAUpdater &MSSAU, bool TargetExecutesOncePerLoop, SinkAndHoistLICMFlags &LICMFlags, OptimizationRemarkEmitter *ORE=nullptr)

Returns true if is legal to hoist or sink this instruction disregarding the possible introduction of ...

auto pred_end(const MachineBasicBlock *BB)

void set_intersect(S1Ty &S1, const S2Ty &S2)

set_intersect(A, B) - Compute A := A ^ B Identical to set_intersection, except that it works on set<>...

void salvageDebugInfo(const MachineRegisterInfo &MRI, MachineInstr &MI)

Assuming the instruction MI is going to be deleted, attempt to salvage debug users of MI by writing t...

void initializeLegacyLICMPassPass(PassRegistry &)

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.

bool formLCSSARecursively(Loop &L, const DominatorTree &DT, const LoopInfo *LI, ScalarEvolution *SE)

Put a loop nest into LCSSA form.

bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures, bool StoreCaptures, 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...

const Value * getUnderlyingObject(const Value *V, unsigned MaxLookup=6)

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

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

auto pred_size(const MachineBasicBlock *BB)

SmallVector< BasicBlock *, 16 > collectChildrenInLoop(DominatorTree *DT, DomTreeNode *N, const Loop *CurLoop)

Does a BFS from a given node to all of its children inside a given loop.

bool hoistRegion(DomTreeNode *, AAResults *, LoopInfo *, DominatorTree *, AssumptionCache *, TargetLibraryInfo *, Loop *, MemorySSAUpdater &, ScalarEvolution *, ICFLoopSafetyInfo *, SinkAndHoistLICMFlags &, OptimizationRemarkEmitter *, bool, bool AllowSpeculation)

Walk the specified region of the CFG (defined by all blocks dominated by the specified block,...

bool any_of(R &&range, UnaryPredicate P)

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

bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)

Return true if the result produced by the instruction is not used, and the instruction will return.

bool isGuard(const User *U)

Returns true iff U has semantics of a guard expressed in a form of call of llvm.experimental....

auto reverse(ContainerTy &&C)

OverflowResult computeOverflowForSignedSub(const Value *LHS, const Value *RHS, const SimplifyQuery &SQ)

bool isModSet(const ModRefInfo MRI)

raw_ostream & dbgs()

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

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

bool isModOrRefSet(const ModRefInfo MRI)

bool isSafeToSpeculativelyExecute(const Instruction *I, const Instruction *CtxI=nullptr, AssumptionCache *AC=nullptr, const DominatorTree *DT=nullptr, const TargetLibraryInfo *TLI=nullptr, bool UseVariableInfo=true)

Return true if the instruction does not have any effects besides calculating the result and does not ...

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

void getLoopAnalysisUsage(AnalysisUsage &AU)

Helper to consistently add the set of standard passes to a loop pass's AnalysisUsage.

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

BasicBlock * SplitBlockPredecessors(BasicBlock *BB, ArrayRef< BasicBlock * > Preds, const char *Suffix, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool PreserveLCSSA=false)

This method introduces at least one new basic block into the function and moves some of the predecess...

ModRefInfo

Flags indicating whether a memory access modifies or references memory.

bool VerifyMemorySSA

Enables verification of MemorySSA.

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

bool salvageKnowledge(Instruction *I, AssumptionCache *AC=nullptr, DominatorTree *DT=nullptr)

Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert if before I.

bool hasDisableLICMTransformsHint(const Loop *L)

Look for the loop attribute that disables the LICM transformation heuristics.

OverflowResult computeOverflowForSignedAdd(const WithCache< const Value * > &LHS, const WithCache< const Value * > &RHS, const SimplifyQuery &SQ)

@ Mul

Product of integers.

void appendLoopsToWorklist(RangeT &&, SmallPriorityWorklist< Loop *, 4 > &)

Utility that implements appending of loops onto a worklist given a range.

bool isIdentifiedFunctionLocal(const Value *V)

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

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

Return true if this is always a dereferenceable pointer.

OutputIt move(R &&Range, OutputIt Out)

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

OverflowResult computeOverflowForUnsignedSub(const Value *LHS, const Value *RHS, const SimplifyQuery &SQ)

auto pred_begin(const MachineBasicBlock *BB)

PreservedAnalyses getLoopPassPreservedAnalyses()

Returns the minimum set of Analyses that all loop passes must preserve.

auto find_if(R &&Range, UnaryPredicate P)

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

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

auto predecessors(const MachineBasicBlock *BB)

Type * getLoadStoreType(const Value *I)

A helper function that returns the type of a load or store instruction.

bool sinkRegion(DomTreeNode *, AAResults *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, TargetTransformInfo *, Loop *CurLoop, MemorySSAUpdater &, ICFLoopSafetyInfo *, SinkAndHoistLICMFlags &, OptimizationRemarkEmitter *, Loop *OutermostLoop=nullptr)

Walk the specified region of the CFG (defined by all blocks dominated by the specified block,...

OverflowResult computeOverflowForUnsignedAdd(const WithCache< const Value * > &LHS, const WithCache< const Value * > &RHS, const SimplifyQuery &SQ)

cl::opt< unsigned > SetLicmMssaNoAccForPromotionCap

bool isKnownNonNegative(const Value *V, const SimplifyQuery &SQ, unsigned Depth=0)

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

bool promoteLoopAccessesToScalars(const SmallSetVector< Value *, 8 > &, SmallVectorImpl< BasicBlock * > &, SmallVectorImpl< BasicBlock::iterator > &, SmallVectorImpl< MemoryAccess * > &, PredIteratorCache &, LoopInfo *, DominatorTree *, AssumptionCache *AC, const TargetLibraryInfo *, TargetTransformInfo *, Loop *, MemorySSAUpdater &, ICFLoopSafetyInfo *, OptimizationRemarkEmitter *, bool AllowSpeculation, bool HasReadsOutsideSet)

Try to promote memory values to scalars by sinking stores out of the loop and moving loads to before ...

cl::opt< unsigned > SetLicmMssaOptCap

bool sinkRegionForLoopNest(DomTreeNode *, AAResults *, LoopInfo *, DominatorTree *, TargetLibraryInfo *, TargetTransformInfo *, Loop *, MemorySSAUpdater &, ICFLoopSafetyInfo *, SinkAndHoistLICMFlags &, OptimizationRemarkEmitter *)

Call sinkRegion on loops contained within the specified loop in order from innermost to outermost.

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

Implement std::hash so that hash_code can be used in STL containers.

void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)

Implement std::swap in terms of BitVector swap.

A collection of metadata nodes that might be associated with a memory access used by the alias-analys...

AAMDNodes merge(const AAMDNodes &Other) const

Given two sets of AAMDNodes applying to potentially different locations, determine the best AAMDNodes...

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

unsigned MssaNoAccForPromotionCap

The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...

TargetTransformInfo & TTI

A lightweight accessor for an operand bundle meant to be passed around by value.

uint32_t getTagID() const

Return the tag of this operand bundle as an integer.

A CRTP mix-in to automatically provide informational APIs needed for passes.