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

60#include

61#include

62#include

63#include

64

65using namespace llvm;

66

67namespace {

68

69#define DEBUG_TYPE "mergeicmps"

70

71

72

73

74struct BCEAtom {

75 BCEAtom() = default;

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

78

79 BCEAtom(const BCEAtom &) = delete;

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

81

82 BCEAtom(BCEAtom &&that) = default;

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

84 if (this == &that)

85 return *this;

86 GEP = that.GEP;

87 LoadI = that.LoadI;

88 BaseId = that.BaseId;

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

90 return *this;

91 }

92

93

94

95

96

97

98

99

100

101

102

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

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

105 }

106

109 unsigned BaseId = 0;

111};

112

113

114

115class BaseIdentifier {

116public:

117

118

119 int getBaseId(const Value *Base) {

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

122 if (Insertion.second)

123 ++Order;

124 return Insertion.first->second;

125 }

126

127private:

128 unsigned Order = 1;

130};

131

132

133

134

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

136 auto *const LoadI = dyn_cast(Val);

137 if (!LoadI)

138 return {};

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

142 return {};

143 }

144

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

147 return {};

148 }

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

150 if (Addr->getType()->getPointerAddressSpace() != 0) {

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

152 return {};

153 }

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

157

158

159 return {};

160 }

161

164 auto *GEP = dyn_cast(Addr);

165 if (GEP) {

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

169 return {};

170 }

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

172 return {};

173 Base = GEP->getPointerOperand();

174 }

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

176}

177

178

179

180

181

182

183

184struct BCECmp {

185 BCEAtom Lhs;

186 BCEAtom Rhs;

187 int SizeBits;

189

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

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

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

193 }

194};

195

196

197

198

199

200

201class BCECmpBlock {

202 public:

204

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

207

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

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

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

211

212

213 bool doesOtherWork() const;

214

215

216

218

219

220

221

222

224

225

226

227

229

230

232

233 InstructionSet BlockInsts;

234

235 bool RequireSplit = false;

236

237 unsigned OrigOrder = 0;

238

239private:

240 BCECmp Cmp;

241};

242

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

245

246

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

249

250

253 };

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

255 return false;

256 }

257

258

260 const Instruction *OpI = dyn_cast(Op);

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

262 });

263}

264

268 if (BlockInsts.count(&Inst))

269 continue;

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

271

272

274 }

275

276

279}

280

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

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

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

285 return false;

286 }

287 }

288 return true;

289}

290

291bool BCECmpBlock::doesOtherWork() const {

292

293

294

295

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

298 return true;

299 }

300 return false;

301}

302

303

304

305std::optional visitICmp(const ICmpInst *const CmpI,

307 BaseIdentifier &BaseId) {

308

309

310

311

312

315 return std::nullopt;

316 }

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

318 return std::nullopt;

320 << (ExpectedPredicate == ICmpInst::ICMP_EQ ? "eq" : "ne")

321 << "\n");

322 auto Lhs = visitICmpLoadOperand(CmpI->getOperand(0), BaseId);

323 if (!Lhs.BaseId)

324 return std::nullopt;

325 auto Rhs = visitICmpLoadOperand(CmpI->getOperand(1), BaseId);

326 if (!Rhs.BaseId)

327 return std::nullopt;

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

331}

332

333

334

335std::optional visitCmpBlock(Value *const Val,

338 BaseIdentifier &BaseId) {

339 if (Block->empty())

340 return std::nullopt;

341 auto *const BranchI = dyn_cast(Block->getTerminator());

342 if (!BranchI)

343 return std::nullopt;

347 if (BranchI->isUnconditional()) {

348

349

350

351

353 ExpectedPredicate = ICmpInst::ICMP_EQ;

354 } else {

355

356

357 const auto *const Const = cast(Val);

359 if (Const->isZero())

360 return std::nullopt;

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

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

364 Cond = BranchI->getCondition();

365 ExpectedPredicate =

366 FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;

367 }

368

369 auto *CmpI = dyn_cast(Cond);

370 if (!CmpI)

371 return std::nullopt;

373

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

375 if (!Result)

376 return std::nullopt;

377

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

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

385}

386

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

388 BCECmpBlock &&Comparison) {

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

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

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

396 Comparison.OrigOrder = Comparisons.size();

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

398}

399

400

401class BCECmpChain {

402public:

403 using ContiguousBlocks = std::vector;

404

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

407

410

411 bool atLeastOneMerged() const {

412 return any_of(MergedBlocks_,

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

414 }

415

416private:

418

419 std::vector MergedBlocks_;

420

422};

423

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

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

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

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

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

429}

430

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

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

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

435 return MinOrigOrder;

436}

437

438

439

440static std::vectorBCECmpChain::ContiguousBlocks

441mergeBlocks(std::vector &&Blocks) {

442 std::vectorBCECmpChain::ContiguousBlocks MergedBlocks;

443

444

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

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

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

449 });

450

451 BCECmpChain::ContiguousBlocks *LastMergedBlock = nullptr;

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

454 MergedBlocks.emplace_back();

455 LastMergedBlock = &MergedBlocks.back();

456 } else {

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

459 }

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

461 }

462

463

464

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

466 const BCECmpChain::ContiguousBlocks &RhsBlocks) {

467 return getMinOrigOrder(LhsBlocks) < getMinOrigOrder(RhsBlocks);

468 });

469

470 return MergedBlocks;

471}

472

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

475 : Phi_(Phi) {

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

477

478 std::vector Comparisons;

479 BaseIdentifier BaseId;

482 std::optional Comparison = visitCmpBlock(

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

484 if (!Comparison) {

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

486 return;

487 }

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

491 if (Comparisons.empty()) {

492

493

494

495

496

497

498

499

500

501

502

503

504

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

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

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

511 } else {

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

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

515 }

516 continue;

517 }

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541 return;

542 }

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

544 }

545

546

547 if (Comparisons.empty()) {

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

549 return;

550 }

551 EntryBlock_ = Comparisons[0].BB;

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

553}

554

555namespace {

556

557

558

559class MergedBlockName {

560

562

563public:

565 : Name(makeName(Comparisons)) {}

567

568private:

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

571

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

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

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

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

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

577 });

578 if (size == 0)

580

581

583

584

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

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

588 };

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

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

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

595 }

596 }

597 return Scratch.str();

598 }

599};

600}

601

602

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

610 const BCECmpBlock &FirstCmp = Comparisons[0];

611

612

615 NextCmpBlock->getParent(), InsertBefore);

617

618 Value *Lhs, *Rhs;

619 if (FirstCmp.Lhs().GEP)

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

621 else

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

623 if (FirstCmp.Rhs().GEP)

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

625 else

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

627

628 Value *IsEqual = nullptr;

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

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

631

632

633

634

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

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

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

639 ToSplit->split(BB, AA);

640 }

641

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

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

644

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

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

649

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

651 } else {

652 const unsigned TotalSizeBits = std::accumulate(

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

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

655

656

659

660

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

663 Lhs, Rhs,

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

665 Builder, DL, &TLI);

666 IsEqual = Builder.CreateICmpEQ(

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

668 }

669

671

672 if (NextCmpBlock == PhiBB) {

673

674 Builder.CreateBr(PhiBB);

675 Phi.addIncoming(IsEqual, BB);

676 DTU.applyUpdates({{DominatorTree::Insert, BB, PhiBB}});

677 } else {

678

679 Builder.CreateCondBr(IsEqual, NextCmpBlock, PhiBB);

681 DTU.applyUpdates({{DominatorTree::Insert, BB, NextCmpBlock},

682 {DominatorTree::Insert, BB, PhiBB}});

683 }

684 return BB;

685}

686

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

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

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

692

693

694

695 BasicBlock *InsertBefore = EntryBlock_;

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

698 InsertBefore = NextCmpBlock = mergeComparisons(

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

700 }

701

702

703

704

708 << "\n");

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

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

712 }

713

714

715

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

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

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

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

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

723 }

724 EntryBlock_ = nullptr;

725

726

728 for (const auto &Blocks : MergedBlocks_) {

729 for (const BCECmpBlock &Block : Blocks) {

731 << "\n");

733 }

734 }

736

737 MergedBlocks_.clear();

738 return true;

739}

740

741std::vector<BasicBlock *> getOrderedBlocks(PHINode &Phi,

743 int NumBlocks) {

744

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

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

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

750

751

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

754 return {};

755 }

756 Blocks[BlockIndex] = CurBlock;

758 if (!SinglePredecessor) {

759

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

762 return {};

763 }

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

765

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

768 return {};

769 }

770 CurBlock = SinglePredecessor;

771 }

772 Blocks[0] = CurBlock;

774}

775

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

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

781 return false;

782 }

783

784

785

786

787

788

789

790

791

792

793

794

795

796

797

798

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

801 if (isa(Phi.getIncomingValue(I))) continue;

802 if (LastBlock) {

803

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

805 return false;

806 }

807 if (!isa(Phi.getIncomingValue(I)) ||

808 cast(Phi.getIncomingValue(I))->getParent() !=

809 Phi.getIncomingBlock(I)) {

810

811

812

813

814

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

818 return false;

819 }

820 LastBlock = Phi.getIncomingBlock(I);

821 }

822 if (!LastBlock) {

823

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

825 return false;

826 }

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

829 return false;

830 }

831

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

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

835 BCECmpChain CmpChain(Blocks, Phi, AA);

836

837 if (!CmpChain.atLeastOneMerged()) {

839 return false;

840 }

841

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

843}

844

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

849

850

851

853 return false;

854

855

856 if (!TLI.has(LibFunc_memcmp))

857 return false;

858

859 DomTreeUpdater DTU(DT, nullptr,

860 DomTreeUpdater::UpdateStrategy::Eager);

861

862 bool MadeChange = false;

863

865

866 if (auto *const Phi = dyn_cast(&*BB.begin()))

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

868 }

869

870 return MadeChange;

871}

872

873class MergeICmpsLegacyPass : public FunctionPass {

874public:

875 static char ID;

876

879 }

880

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

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

885

886

887 auto *DTWP = getAnalysisIfAvailable();

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

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

890 }

891

892 private:

899 }

900};

901

902}

903

904char MergeICmpsLegacyPass::ID = 0;

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

912

914

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

922 if (!MadeChanges)

926 return PA;

927}

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

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

DenseMap< Block *, BlockRelaxAux > Blocks

static bool runImpl(Function &F, const TargetLowering &TLI)

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

Merge contiguous icmps into a memcmp

#define INITIALIZE_PASS_DEPENDENCY(depName)

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

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

const SmallVectorImpl< MachineOperand > & Cond

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

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.

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

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.

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

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.

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.

const BasicBlock * getSinglePredecessor() const

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

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.

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 ConstantInt * getFalse(LLVMContext &Context)

This class represents an Operation in the Expression.

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.

Legacy analysis pass which computes a DominatorTree.

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

FunctionPass class - This class is used to implement most global optimizations.

virtual bool runOnFunction(Function &F)=0

runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.

bool skipFunction(const Function &F) const

Optional passes call this function to check whether the pass should be skipped.

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.

an instruction for type-safe pointer arithmetic to access elements of arrays and structs

Legacy wrapper pass to provide the GlobalsAAResult object.

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

void moveBeforePreserving(Instruction *MovePos)

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

bool mayWriteToMemory() const LLVM_READONLY

Return true if this instruction may modify memory.

bool comesBefore(const Instruction *Other) const

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

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.

An instruction for reading from memory.

static MemoryLocation get(const LoadInst *LI)

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

static PassRegistry * getPassRegistry()

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

Pass interface - Implemented by all 'passes'.

virtual void getAnalysisUsage(AnalysisUsage &) const

getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...

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.

void preserve()

Mark an analysis as preserved.

Implements a dense probed hash-table based set with some number of buckets stored inline.

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

void append(StringRef RHS)

Append from a StringRef.

StringRef str() const

Explicit conversion to StringRef.

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.

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

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.

MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const

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.

StringRef getName() const

Return a constant reference to the value's name.

std::pair< iterator, bool > insert(const ValueT &V)

const ParentTy * getParent() const

@ C

The default llvm calling convention, compatible with C.

unsigned ID

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

NodeAddr< PhiNode * > Phi

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)

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.

void initializeMergeICmpsLegacyPassPass(PassRegistry &)

bool any_of(R &&range, UnaryPredicate P)

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

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

Emit a call to the memcmp function.

auto reverse(ContainerTy &&C)

bool isModSet(const ModRefInfo MRI)

void sort(IteratorTy Start, IteratorTy End)

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.

@ First

Helpers to iterate all locations in the MemoryEffectsBase class.

Pass * createMergeICmpsLegacyPass()

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.

auto pred_begin(const MachineBasicBlock *BB)

auto find_if(R &&Range, UnaryPredicate P)

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

bool pred_empty(const BasicBlock *BB)

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

Delete the specified blocks from BB.

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.

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)