LLVM: lib/Transforms/Scalar/MergeICmps.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

39

40

41

42

43

61#include

62#include

63#include

64#include

65

66using namespace llvm;

67

68#define DEBUG_TYPE "mergeicmps"

69

70namespace llvm {

72}

73namespace {

74

75

76

77

78struct BCEAtom {

79 BCEAtom() = default;

80 BCEAtom(GetElementPtrInst *GEP, LoadInst *LoadI, int BaseId, APInt Offset)

81 : GEP(GEP), LoadI(LoadI), BaseId(BaseId), Offset(std::move(Offset)) {}

82

83 BCEAtom(const BCEAtom &) = delete;

84 BCEAtom &operator=(const BCEAtom &) = delete;

85

86 BCEAtom(BCEAtom &&that) = default;

87 BCEAtom &operator=(BCEAtom &&that) {

88 if (this == &that)

89 return *this;

90 GEP = that.GEP;

91 LoadI = that.LoadI;

92 BaseId = that.BaseId;

93 Offset = std::move(that.Offset);

94 return *this;

95 }

96

97

98

99

100

101

102

103

104

105

106

107 bool operator<(const BCEAtom &O) const {

108 return BaseId != O.BaseId ? BaseId < O.BaseId : Offset.slt(O.Offset);

109 }

110

111 GetElementPtrInst *GEP = nullptr;

112 LoadInst *LoadI = nullptr;

113 unsigned BaseId = 0;

114 APInt Offset;

115};

116

117

118

119class BaseIdentifier {

120public:

121

122

123 int getBaseId(const Value *Base) {

125 const auto Insertion = BaseToIndex.try_emplace(Base, Order);

126 if (Insertion.second)

127 ++Order;

128 return Insertion.first->second;

129 }

130

131private:

132 unsigned Order = 1;

133 DenseMap<const Value*, int> BaseToIndex;

134};

135}

136

137

138

139

142 if (!LoadI)

143 return {};

145 if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) {

147 return {};

148 }

149

150 if (!LoadI->isSimple()) {

152 return {};

153 }

154 Value *Addr = LoadI->getOperand(0);

156 LLVM_DEBUG(dbgs() << "from non-zero AddressSpace\n");

157 return {};

158 }

159 const auto &DL = LoadI->getDataLayout();

162

163

164 return {};

165 }

166

170 if (GEP) {

172 if (GEP->isUsedOutsideOfBlock(LoadI->getParent())) {

174 return {};

175 }

176 if (GEP->accumulateConstantOffset(DL, Offset))

177 return {};

178 Base = GEP->getPointerOperand();

179 }

180 return BCEAtom(GEP, LoadI, BaseId.getBaseId(Base), Offset);

181}

182

183namespace {

184

185

186

187

188

189

190struct BCECmp {

191 BCEAtom Lhs;

192 BCEAtom Rhs;

193 int SizeBits;

194 const ICmpInst *CmpI;

195

196 BCECmp(BCEAtom L, BCEAtom R, int SizeBits, const ICmpInst *CmpI)

197 : Lhs(std::move(L)), Rhs(std::move(R)), SizeBits(SizeBits), CmpI(CmpI) {

198 if (Rhs < Lhs) std::swap(Rhs, Lhs);

199 }

200};

201

202

203

204

205

206

207class BCECmpBlock {

208 public:

209 typedef SmallDenseSet<const Instruction *, 8> InstructionSet;

210

211 BCECmpBlock(BCECmp Cmp, BasicBlock *BB, InstructionSet BlockInsts)

212 : BB(BB), BlockInsts(std::move(BlockInsts)), Cmp(std::move(Cmp)) {}

213

214 const BCEAtom &Lhs() const { return Cmp.Lhs; }

215 const BCEAtom &Rhs() const { return Cmp.Rhs; }

216 int SizeBits() const { return Cmp.SizeBits; }

217

218

219 bool doesOtherWork() const;

220

221

222

224

225

226

227

228

229 bool canSinkBCECmpInst(const Instruction *, AliasAnalysis &AA) const;

230

231

232

233

235

236

238

239 InstructionSet BlockInsts;

240

241 bool RequireSplit = false;

242

243 unsigned OrigOrder = 0;

244

245private:

246 BCECmp Cmp;

247};

248}

249

250bool BCECmpBlock::canSinkBCECmpInst(const Instruction *Inst,

252

253

255 auto MayClobber = [&](LoadInst *LI) {

256

257

260 };

261 if (MayClobber(Cmp.Lhs.LoadI) || MayClobber(Cmp.Rhs.LoadI))

262 return false;

263 }

264

265

267 const Instruction *OpI = dyn_cast(Op);

268 return OpI && BlockInsts.contains(OpI);

269 });

270}

271

272void BCECmpBlock::split(BasicBlock *NewParent, AliasAnalysis &AA) const {

273 llvm::SmallVector<Instruction *, 4> OtherInsts;

274 for (Instruction &Inst : *BB) {

275 if (BlockInsts.count(&Inst))

276 continue;

277 assert(canSinkBCECmpInst(&Inst, AA) && "Split unsplittable block");

278

279

281 }

282

283

284 for (Instruction *Inst : reverse(OtherInsts))

286}

287

288bool BCECmpBlock::canSplit(AliasAnalysis &AA) const {

289 for (Instruction &Inst : *BB) {

290 if (!BlockInsts.count(&Inst)) {

291 if (!canSinkBCECmpInst(&Inst, AA))

292 return false;

293 }

294 }

295 return true;

296}

297

298bool BCECmpBlock::doesOtherWork() const {

299

300

301

302

303 for (const Instruction &Inst : *BB) {

304 if (!BlockInsts.count(&Inst))

305 return true;

306 }

307 return false;

308}

309

310

311

312static std::optional

315

316

317

318

319

322 return std::nullopt;

323 }

324 if (CmpI->getPredicate() != ExpectedPredicate)

325 return std::nullopt;

328 << "\n");

330 if (!Lhs.BaseId)

331 return std::nullopt;

333 if (!Rhs.BaseId)

334 return std::nullopt;

336 return BCECmp(std::move(Lhs), std::move(Rhs),

338}

339

340

341

342static std::optional

344 const BasicBlock *const PhiBlock, BaseIdentifier &BaseId) {

345 if (Block->empty())

346 return std::nullopt;

348 if (!BranchI)

349 return std::nullopt;

353 if (BranchI->isUnconditional()) {

354

355

356

357

360 } else {

361

362

365 if (!Const->isZero())

366 return std::nullopt;

368 assert(BranchI->getNumSuccessors() == 2 && "expecting a cond branch");

369 BasicBlock *const FalseBlock = BranchI->getSuccessor(1);

370 Cond = BranchI->getCondition();

371 ExpectedPredicate =

373 }

374

376 if (!CmpI)

377 return std::nullopt;

379

380 std::optional Result = visitICmp(CmpI, ExpectedPredicate, BaseId);

381 if (!Result)

382 return std::nullopt;

383

384 BCECmpBlock::InstructionSet BlockInsts(

385 {Result->Lhs.LoadI, Result->Rhs.LoadI, Result->CmpI, BranchI});

386 if (Result->Lhs.GEP)

387 BlockInsts.insert(Result->Lhs.GEP);

388 if (Result->Rhs.GEP)

389 BlockInsts.insert(Result->Rhs.GEP);

390 return BCECmpBlock(std::move(*Result), Block, BlockInsts);

391}

392

393static inline void enqueueBlock(std::vector &Comparisons,

394 BCECmpBlock &&Comparison) {

395 LLVM_DEBUG(dbgs() << "Block '" << Comparison.BB->getName()

396 << "': Found cmp of " << Comparison.SizeBits()

397 << " bits between " << Comparison.Lhs().BaseId << " + "

398 << Comparison.Lhs().Offset << " and "

399 << Comparison.Rhs().BaseId << " + "

400 << Comparison.Rhs().Offset << "\n");

402 Comparison.OrigOrder = Comparisons.size();

403 Comparisons.push_back(std::move(Comparison));

404}

405

406namespace {

407

408class BCECmpChain {

409public:

410 using ContiguousBlocks = std::vector;

411

412 BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi,

414

416 DomTreeUpdater &DTU);

417

418 bool atLeastOneMerged() const {

419 return any_of(MergedBlocks_,

420 [](const auto &Blocks) { return Blocks.size() > 1; });

421 }

422

423private:

424 PHINode &Phi_;

425

426 std::vector MergedBlocks_;

427

429};

430}

431

433 return First.Lhs().BaseId == Second.Lhs().BaseId &&

434 First.Rhs().BaseId == Second.Rhs().BaseId &&

435 First.Lhs().Offset + First.SizeBits() / 8 == Second.Lhs().Offset &&

436 First.Rhs().Offset + First.SizeBits() / 8 == Second.Rhs().Offset;

437}

438

439static unsigned getMinOrigOrder(const BCECmpChain::ContiguousBlocks &Blocks) {

440 unsigned MinOrigOrder = std::numeric_limits::max();

441 for (const BCECmpBlock &Block : Blocks)

442 MinOrigOrder = std::min(MinOrigOrder, Block.OrigOrder);

443 return MinOrigOrder;

444}

445

446

447

448static std::vectorBCECmpChain::ContiguousBlocks

450 std::vectorBCECmpChain::ContiguousBlocks MergedBlocks;

451

452

454 [](const BCECmpBlock &LhsBlock, const BCECmpBlock &RhsBlock) {

455 return std::tie(LhsBlock.Lhs(), LhsBlock.Rhs()) <

456 std::tie(RhsBlock.Lhs(), RhsBlock.Rhs());

457 });

458

459 BCECmpChain::ContiguousBlocks *LastMergedBlock = nullptr;

460 for (BCECmpBlock &Block : Blocks) {

461 if (!LastMergedBlock || areContiguous(LastMergedBlock->back(), Block)) {

462 MergedBlocks.emplace_back();

463 LastMergedBlock = &MergedBlocks.back();

464 } else {

466 << LastMergedBlock->back().BB->getName() << "\n");

467 }

468 LastMergedBlock->push_back(std::move(Block));

469 }

470

471

472

473 llvm::sort(MergedBlocks, [](const BCECmpChain::ContiguousBlocks &LhsBlocks,

474 const BCECmpChain::ContiguousBlocks &RhsBlocks) {

476 });

477

478 return MergedBlocks;

479}

480

481BCECmpChain::BCECmpChain(const std::vector<BasicBlock *> &Blocks, PHINode &Phi,

483 : Phi_(Phi) {

484 assert(!Blocks.empty() && "a chain should have at least one block");

485

486 std::vector Comparisons;

487 BaseIdentifier BaseId;

490 if (Block->hasAddressTaken()) {

491 LLVM_DEBUG(dbgs() << "cannot merge blocks with blockaddress\n");

492 return;

493 }

494 std::optional Comparison = visitCmpBlock(

495 Phi.getIncomingValueForBlock(Block), Block, Phi.getParent(), BaseId);

496 if (!Comparison) {

497 LLVM_DEBUG(dbgs() << "chain with invalid BCECmpBlock, no merge.\n");

498 return;

499 }

500 if (Comparison->doesOtherWork()) {

501 LLVM_DEBUG(dbgs() << "block '" << Comparison->BB->getName()

502 << "' does extra work besides compare\n");

503 if (Comparisons.empty()) {

504

505

506

507

508

509

510

511

512

513

514

515

516

517 if (Comparison->canSplit(AA)) {

519 << "Split initial block '" << Comparison->BB->getName()

520 << "' that does extra work besides compare\n");

521 Comparison->RequireSplit = true;

522 enqueueBlock(Comparisons, std::move(*Comparison));

523 } else {

525 << "ignoring initial block '" << Comparison->BB->getName()

526 << "' that does extra work besides compare\n");

527 }

528 continue;

529 }

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553 return;

554 }

555 enqueueBlock(Comparisons, std::move(*Comparison));

556 }

557

558

559 if (Comparisons.empty()) {

560 LLVM_DEBUG(dbgs() << "chain with no BCE basic blocks, no merge\n");

561 return;

562 }

563 EntryBlock_ = Comparisons[0].BB;

564 MergedBlocks_ = mergeBlocks(std::move(Comparisons));

565}

566

567namespace {

568

569

570

571class MergedBlockName {

572

573 SmallString<16> Scratch;

574

575public:

577 : Name(makeName(Comparisons)) {}

578 const StringRef Name;

579

580private:

582 assert(!Comparisons.empty() && "no basic block");

583

584 if (Comparisons.size() == 1)

585 return Comparisons[0].BB->getName();

586 const int size = std::accumulate(Comparisons.begin(), Comparisons.end(), 0,

587 [](int i, const BCECmpBlock &Cmp) {

588 return i + Cmp.BB->getName().size();

589 });

590 if (size == 0)

591 return StringRef("", 0);

592

593

594 Scratch.clear();

595

596

597 Scratch.reserve(size + Comparisons.size() - 1);

598 const auto append = [this](StringRef str) {

599 Scratch.append(str.begin(), str.end());

600 };

601 append(Comparisons[0].BB->getName());

602 for (int I = 1, E = Comparisons.size(); I < E; ++I) {

603 const BasicBlock *const BB = Comparisons[I].BB;

607 }

608 }

609 return Scratch.str();

610 }

611};

612}

613

614

615

616static std::optional<SmallVector<uint32_t, 2>>

620 return std::nullopt;

621 if (Comparisons.size() == 1) {

624 return std::nullopt;

625 return Weights;

626 }

627

628

629

630

632

633 for (const auto &C : Comparisons) {

636 return std::nullopt;

637

640 }

641 std::swap(Weights[0], Weights[1]);

643}

644

645

651 assert(!Comparisons.empty() && "merging zero comparisons");

653 const BCECmpBlock &FirstCmp = Comparisons[0];

654

655

658 NextCmpBlock->getParent(), InsertBefore);

660

661 Value *Lhs, *Rhs;

662 if (FirstCmp.Lhs().GEP)

663 Lhs = Builder.Insert(FirstCmp.Lhs().GEP->clone());

664 else

665 Lhs = FirstCmp.Lhs().LoadI->getPointerOperand();

666 if (FirstCmp.Rhs().GEP)

667 Rhs = Builder.Insert(FirstCmp.Rhs().GEP->clone());

668 else

669 Rhs = FirstCmp.Rhs().LoadI->getPointerOperand();

670

671 Value *IsEqual = nullptr;

672 LLVM_DEBUG(dbgs() << "Merging " << Comparisons.size() << " comparisons -> "

673 << BB->getName() << "\n");

674

675

676

677

679 Comparisons, [](const BCECmpBlock &B) { return B.RequireSplit; });

680 if (ToSplit != Comparisons.end()) {

681 LLVM_DEBUG(dbgs() << "Splitting non_BCE work to header\n");

682 ToSplit->split(BB, AA);

683 }

684

685 if (Comparisons.size() == 1) {

686 LLVM_DEBUG(dbgs() << "Only one comparison, updating branches\n");

687

688 Instruction *const LhsLoad = Builder.Insert(FirstCmp.Lhs().LoadI->clone());

689 Instruction *const RhsLoad = Builder.Insert(FirstCmp.Rhs().LoadI->clone());

692

693

694 IsEqual = Builder.CreateICmpEQ(LhsLoad, RhsLoad);

695 } else {

696 const unsigned TotalSizeBits = std::accumulate(

697 Comparisons.begin(), Comparisons.end(), 0u,

698 [](int Size, const BCECmpBlock &C) { return Size + C.SizeBits(); });

699

700

701 unsigned SizeTBits = TLI.getSizeTSize(*Phi.getModule());

703

704

705 const auto &DL = Phi.getDataLayout();

707 Lhs, Rhs,

708 ConstantInt::get(Builder.getIntNTy(SizeTBits), TotalSizeBits / 8),

709 Builder, DL, &TLI);

710 IsEqual = Builder.CreateICmpEQ(

711 MemCmpCall, ConstantInt::get(Builder.getIntNTy(IntBits), 0));

712 }

713

714 BasicBlock *const PhiBB = Phi.getParent();

715

716 if (NextCmpBlock == PhiBB) {

717

718 Builder.CreateBr(PhiBB);

719 Phi.addIncoming(IsEqual, BB);

721 } else {

722

723 auto *BI = Builder.CreateCondBr(IsEqual, NextCmpBlock, PhiBB);

725 setBranchWeights(*BI, BranchWeights.value(), false);

729 }

730 return BB;

731}

732

735 assert(atLeastOneMerged() && "simplifying trivial BCECmpChain");

736 LLVM_DEBUG(dbgs() << "Simplifying comparison chain starting at block "

737 << EntryBlock_->getName() << "\n");

738

739

740

741 BasicBlock *InsertBefore = EntryBlock_;

743 for (const auto &Blocks : reverse(MergedBlocks_)) {

745 Blocks, InsertBefore, NextCmpBlock, Phi_, TLI, AA, DTU);

746 }

747

748

749

750

754 << "\n");

756 DTU.applyUpdates({{DominatorTree::Delete, Pred, EntryBlock_},

757 {DominatorTree::Insert, Pred, NextCmpBlock}});

758 }

759

760

761

762 const bool ChainEntryIsFnEntry = EntryBlock_->isEntryBlock();

763 if (ChainEntryIsFnEntry && DTU.hasDomTree()) {

765 << EntryBlock_->getName() << " to "

766 << NextCmpBlock->getName() << "\n");

768 DTU.applyUpdates({{DominatorTree::Delete, NextCmpBlock, EntryBlock_}});

769 }

770 EntryBlock_ = nullptr;

771

772

773 SmallVector<BasicBlock *, 16> DeadBlocks;

774 for (const auto &Blocks : MergedBlocks_) {

775 for (const BCECmpBlock &Block : Blocks) {

777 << "\n");

779 }

780 }

782

783 MergedBlocks_.clear();

784 return true;

785}

786

787static std::vector<BasicBlock *>

789

790 std::vector<BasicBlock *> Blocks(NumBlocks);

791 assert(LastBlock && "invalid last block");

793 for (int BlockIndex = NumBlocks - 1; BlockIndex > 0; --BlockIndex) {

795

796

798 << " has its address taken\n");

799 return {};

800 }

801 Blocks[BlockIndex] = CurBlock;

803 if (!SinglePredecessor) {

804

806 << " has two or more predecessors\n");

807 return {};

808 }

809 if (Phi.getBasicBlockIndex(SinglePredecessor) < 0) {

810

812 << " does not link back to the phi\n");

813 return {};

814 }

815 CurBlock = SinglePredecessor;

816 }

817 Blocks[0] = CurBlock;

818 return Blocks;

819}

820

824 if (Phi.getNumIncomingValues() <= 1) {

825 LLVM_DEBUG(dbgs() << "skip: only one incoming value in phi\n");

826 return false;

827 }

828

829

830

831

832

833

834

835

836

837

838

839

840

841

842

843

845 for (unsigned I = 0; I < Phi.getNumIncomingValues(); ++I) {

847 if (LastBlock) {

848

849 LLVM_DEBUG(dbgs() << "skip: several non-constant values\n");

850 return false;

851 }

854 Phi.getIncomingBlock(I)) {

855

856

857

858

859

862 << "skip: non-constant value not from cmp or not from last block.\n");

863 return false;

864 }

865 LastBlock = Phi.getIncomingBlock(I);

866 }

867 if (!LastBlock) {

868

869 LLVM_DEBUG(dbgs() << "skip: no non-constant block\n");

870 return false;

871 }

873 LLVM_DEBUG(dbgs() << "skip: last block non-phi successor\n");

874 return false;

875 }

876

877 const auto Blocks =

878 getOrderedBlocks(Phi, LastBlock, Phi.getNumIncomingValues());

879 if (Blocks.empty()) return false;

880 BCECmpChain CmpChain(Blocks, Phi, AA);

881

882 if (!CmpChain.atLeastOneMerged()) {

884 return false;

885 }

886

887 return CmpChain.simplify(TLI, AA, DTU);

888}

889

893 LLVM_DEBUG(dbgs() << "MergeICmpsLegacyPass: " << F.getName() << "\n");

894

895

896

897 if (TTI.enableMemCmpExpansion(F.hasOptSize(), true))

898 return false;

899

900

901 if (!TLI.has(LibFunc_memcmp))

902 return false;

903

904 DomTreeUpdater DTU(DT, nullptr,

905 DomTreeUpdater::UpdateStrategy::Eager);

906

907 bool MadeChange = false;

908

910

912 MadeChange |= processPhi(*Phi, TLI, AA, DTU);

913 }

914

915 return MadeChange;

916}

917

918namespace {

919class MergeICmpsLegacyPass : public FunctionPass {

920public:

921 static char ID;

922

923 MergeICmpsLegacyPass() : FunctionPass(ID) {

925 }

926

928 if (skipFunction(F)) return false;

929 const auto &TLI = getAnalysis().getTLI(F);

930 const auto &TTI = getAnalysis().getTTI(F);

931

932

933 auto *DTWP = getAnalysisIfAvailable();

934 auto &AA = getAnalysis().getAAResults();

935 return runImpl(F, TLI, TTI, AA, DTWP ? &DTWP->getDomTree() : nullptr);

936 }

937

938 private:

939 void getAnalysisUsage(AnalysisUsage &AU) const override {

940 AU.addRequired();

941 AU.addRequired();

945 }

946};

947

948}

949

950char MergeICmpsLegacyPass::ID = 0;

952 "Merge contiguous icmps into a memcmp", false, false)

957 "Merge contiguous icmps into a memcmp", false, false)

958

960

967 const bool MadeChanges = runImpl(F, TLI, TTI, AA, DT);

968 if (!MadeChanges)

972 return PA;

973}

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

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

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

static bool runOnFunction(Function &F, bool PostInlining)

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.

static void enqueueBlock(std::vector< BCECmpBlock > &Comparisons, BCECmpBlock &&Comparison)

Definition MergeICmps.cpp:393

static std::vector< BCECmpChain::ContiguousBlocks > mergeBlocks(std::vector< BCECmpBlock > &&Blocks)

Given a chain of comparison blocks, groups the blocks into contiguous ranges that can be merged toget...

Definition MergeICmps.cpp:449

static std::optional< SmallVector< uint32_t, 2 > > computeMergedBranchWeights(ArrayRef< BCECmpBlock > Comparisons)

Determine the branch weights for the resulting conditional branch, resulting after merging Comparison...

Definition MergeICmps.cpp:617

static std::optional< BCECmpBlock > visitCmpBlock(Value *const Val, BasicBlock *const Block, const BasicBlock *const PhiBlock, BaseIdentifier &BaseId)

Definition MergeICmps.cpp:343

static bool areContiguous(const BCECmpBlock &First, const BCECmpBlock &Second)

Definition MergeICmps.cpp:432

static std::vector< BasicBlock * > getOrderedBlocks(PHINode &Phi, BasicBlock *const LastBlock, int NumBlocks)

Definition MergeICmps.cpp:788

static unsigned getMinOrigOrder(const BCECmpChain::ContiguousBlocks &Blocks)

Definition MergeICmps.cpp:439

static BCEAtom visitICmpLoadOperand(Value *const Val, BaseIdentifier &BaseId)

Definition MergeICmps.cpp:140

static std::optional< BCECmp > visitICmp(const ICmpInst *const CmpI, const ICmpInst::Predicate ExpectedPredicate, BaseIdentifier &BaseId)

Definition MergeICmps.cpp:313

static BasicBlock * mergeComparisons(ArrayRef< BCECmpBlock > Comparisons, BasicBlock *const InsertBefore, BasicBlock *const NextCmpBlock, PHINode &Phi, const TargetLibraryInfo &TLI, AliasAnalysis &AA, DomTreeUpdater &DTU)

Definition MergeICmps.cpp:646

static bool processPhi(PHINode &Phi, const TargetLibraryInfo &TLI, AliasAnalysis &AA, DomTreeUpdater &DTU)

Definition MergeICmps.cpp:821

#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 contains the declarations for profiling metadata utility functions.

const SmallVectorImpl< MachineOperand > & Cond

This file defines the SmallString class.

This pass exposes codegen information to IR-level passes.

A manager for alias analyses.

A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.

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

Check whether or not an instruction may read or write the optionally specified memory location.

Class for arbitrary precision integers.

PassT::Result * getCachedResult(IRUnitT &IR) const

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

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

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

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

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

LLVM Basic Block Representation.

iterator begin()

Instruction iterator methods.

const Function * getParent() const

Return the enclosing method, or null if none.

bool hasAddressTaken() const

Returns true if there are any uses of this basic block other than direct branches,...

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

Creates a new BasicBlock.

LLVM_ABI bool isEntryBlock() const

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

LLVM_ABI const BasicBlock * getSinglePredecessor() const

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

LLVM_ABI const BasicBlock * getSingleSuccessor() const

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

LLVM_ABI LLVMContext & getContext() const

Get the context in which this basic block 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...

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

Predicate getPredicate() const

Return the predicate for this instruction.

static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)

Analysis pass which computes a DominatorTree.

DomTreeNodeBase< NodeT > * setNewRoot(NodeT *BB)

Add a new node to the forward dominator tree and make it a new root.

static constexpr UpdateKind Insert

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

DomTreeT & getDomTree()

Flush DomTree updates and return DomTree.

void applyUpdates(ArrayRef< UpdateT > Updates)

Submit updates to all available trees.

bool hasDomTree() const

Returns true if it holds a DomTreeT.

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

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

LLVM_ABI bool mayWriteToMemory() const LLVM_READONLY

Return true if this instruction may modify memory.

LLVM_ABI bool comesBefore(const Instruction *Other) const

Given an instruction Other in the same basic block as this instruction, return true if this instructi...

LLVM_ABI void moveBeforePreserving(InstListType::iterator MovePos)

Perform a moveBefore operation, while signalling that the caller intends to preserve the original ord...

LLVM_ABI const DataLayout & getDataLayout() const

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

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

static LLVM_ABI MemoryLocation get(const LoadInst *LI)

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

static LLVM_ABI PassRegistry * getPassRegistry()

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

Pass interface - Implemented by all 'passes'.

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

Mark an analysis as preserved.

void push_back(const T &Elt)

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

constexpr bool empty() const

empty - Check if the string is empty.

Analysis pass providing the TargetTransformInfo.

Analysis pass providing the TargetLibraryInfo.

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

bool has(LibFunc F) const

Tests whether a library function is available.

unsigned getSizeTSize(const Module &M) const

Returns the size of the size_t type in bits.

unsigned getIntSize() const

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

Wrapper pass for TargetTransformInfo.

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

LLVM_ABI unsigned getPointerAddressSpace() const

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

LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)

Replace uses of one Value with another.

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 StringRef getName() const

Return a constant reference to the value's name.

size_type count(const_arg_type_t< ValueT > V) const

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

const ParentTy * getParent() const

Abstract Attribute helper functions.

unsigned ID

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

@ C

The default llvm calling convention, compatible with C.

@ BasicBlock

Various leaf nodes.

NodeAddr< PhiNode * > Phi

LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")

Append to path.

This is an optimization pass for GlobalISel generic memory operations.

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

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

bool operator<(int64_t V1, const APSInt &V2)

FunctionAddr VTableAddr Value

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

decltype(auto) dyn_cast(const From &Val)

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

LLVM_ABI void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected, bool ElideAllZero=false)

Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...

bool any_of(R &&range, UnaryPredicate P)

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

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

Emit a call to the memcmp function.

LLVM_ABI SmallVector< uint32_t > fitWeights(ArrayRef< uint64_t > Weights)

Push the weights right to fit in uint32_t.

auto reverse(ContainerTy &&C)

bool isModSet(const ModRefInfo MRI)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

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

bool none_of(R &&Range, UnaryPredicate P)

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

iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)

Split the specified string over a separator and return a range-compatible iterable over its partition...

bool isa(const From &Val)

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

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

LLVM_ABI Pass * createMergeICmpsLegacyPass()

Definition MergeICmps.cpp:959

DWARFExpression::Operation Op

ArrayRef(const T &OneElt) -> ArrayRef< T >

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

LLVM_ABI bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)

Extract branch weights from MD_prof metadata.

auto pred_begin(const MachineBasicBlock *BB)

decltype(auto) cast(const From &Val)

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

auto find_if(R &&Range, UnaryPredicate P)

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

SmallVector< uint64_t, 2 > getDisjunctionWeights(const SmallVector< T1, 2 > &B1, const SmallVector< T2, 2 > &B2)

Get the branch weights of a branch conditioned on b1 || b2, where b1 and b2 are 2 booleans that are t...

cl::opt< bool > ProfcheckDisableMetadataFixes("profcheck-disable-metadata-fixes", cl::Hidden, cl::init(false), cl::desc("Disable metadata propagation fixes discovered through Issue #147390"))

bool pred_empty(const BasicBlock *BB)

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

LLVM_ABI void DeleteDeadBlocks(ArrayRef< BasicBlock * > BBs, DomTreeUpdater *DTU=nullptr, bool KeepOneInputPHIs=false)

Delete the specified blocks from BB.

LLVM_ABI void initializeMergeICmpsLegacyPassPass(PassRegistry &)

AAResults AliasAnalysis

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

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

Implement std::swap in terms of BitVector swap.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)

Definition MergeICmps.cpp:961