69#define DEBUG_TYPE "mergeicmps"
79 BCEAtom(
const BCEAtom &) =
delete;
80 BCEAtom &operator=(
const BCEAtom &) =
delete;
82 BCEAtom(BCEAtom &&that) =
default;
83 BCEAtom &operator=(BCEAtom &&that) {
89 Offset = std::move(that.Offset);
104 return BaseId != O.BaseId ? BaseId < O.BaseId :
Offset.slt(O.Offset);
115class BaseIdentifier {
121 const auto Insertion = BaseToIndex.try_emplace(
Base, Order);
122 if (Insertion.second)
124 return Insertion.first->second;
129 DenseMap<const Value*, int> BaseToIndex;
135BCEAtom visitICmpLoadOperand(
Value *
const Val, BaseIdentifier &BaseId) {
140 if (LoadI->isUsedOutsideOfBlock(LoadI->getParent())) {
145 if (!LoadI->isSimple()) {
149 Value *Addr = LoadI->getOperand(0);
154 const auto &
DL = LoadI->getDataLayout();
167 if (
GEP->isUsedOutsideOfBlock(LoadI->getParent())) {
173 Base =
GEP->getPointerOperand();
188 const ICmpInst *CmpI;
190 BCECmp(BCEAtom L, BCEAtom R,
int SizeBits,
const ICmpInst *CmpI)
191 : Lhs(std::
move(
L)), Rhs(std::
move(
R)), SizeBits(SizeBits), CmpI(CmpI) {
203 typedef SmallDenseSet<const Instruction *, 8> InstructionSet;
205 BCECmpBlock(BCECmp Cmp, BasicBlock *BB, InstructionSet BlockInsts)
206 : BB(BB), BlockInsts(std::
move(BlockInsts)), Cmp(std::
move(Cmp)) {}
208 const BCEAtom &Lhs()
const {
return Cmp.Lhs; }
209 const BCEAtom &Rhs()
const {
return Cmp.Rhs; }
210 int SizeBits()
const {
return Cmp.SizeBits; }
213 bool doesOtherWork()
const;
223 bool canSinkBCECmpInst(
const Instruction *,
AliasAnalysis &AA)
const;
233 InstructionSet BlockInsts;
235 bool RequireSplit =
false;
237 unsigned OrigOrder = 0;
243bool BCECmpBlock::canSinkBCECmpInst(
const Instruction *Inst,
248 auto MayClobber = [&](LoadInst *LI) {
254 if (MayClobber(Cmp.Lhs.LoadI) || MayClobber(Cmp.Rhs.LoadI))
260 const Instruction *OpI = dyn_cast<Instruction>(Op);
261 return OpI && BlockInsts.contains(OpI);
265void BCECmpBlock::split(BasicBlock *NewParent,
AliasAnalysis &AA)
const {
266 llvm::SmallVector<Instruction *, 4> OtherInsts;
267 for (Instruction &Inst : *BB) {
268 if (BlockInsts.
count(&Inst))
270 assert(canSinkBCECmpInst(&Inst, AA) &&
"Split unsplittable block");
277 for (Instruction *Inst :
reverse(OtherInsts))
282 for (Instruction &Inst : *BB) {
283 if (!BlockInsts.
count(&Inst)) {
284 if (!canSinkBCECmpInst(&Inst, AA))
291bool BCECmpBlock::doesOtherWork()
const {
296 for (
const Instruction &Inst : *BB) {
297 if (!BlockInsts.
count(&Inst))
305std::optional<BCECmp> visitICmp(
const ICmpInst *
const CmpI,
306 const ICmpInst::Predicate ExpectedPredicate,
307 BaseIdentifier &BaseId) {
320 << (ExpectedPredicate == ICmpInst::ICMP_EQ ?
"eq" :
"ne")
322 auto Lhs = visitICmpLoadOperand(CmpI->
getOperand(0), BaseId);
325 auto Rhs = visitICmpLoadOperand(CmpI->
getOperand(1), BaseId);
329 return BCECmp(std::move(Lhs), std::move(Rhs),
335std::optional<BCECmpBlock> visitCmpBlock(
Value *
const Val,
336 BasicBlock *
const Block,
337 const BasicBlock *
const PhiBlock,
338 BaseIdentifier &BaseId) {
346 ICmpInst::Predicate ExpectedPredicate;
347 if (BranchI->isUnconditional()) {
353 ExpectedPredicate = ICmpInst::ICMP_EQ;
359 if (!
Const->isZero())
362 assert(BranchI->getNumSuccessors() == 2 &&
"expecting a cond branch");
363 BasicBlock *
const FalseBlock = BranchI->getSuccessor(1);
364 Cond = BranchI->getCondition();
366 FalseBlock == PhiBlock ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE;
374 std::optional<BCECmp>
Result = visitICmp(CmpI, ExpectedPredicate, BaseId);
378 BCECmpBlock::InstructionSet BlockInsts(
381 BlockInsts.insert(
Result->Lhs.GEP);
383 BlockInsts.insert(
Result->Rhs.GEP);
384 return BCECmpBlock(std::move(*Result),
Block, BlockInsts);
387static inline void enqueueBlock(std::vector<BCECmpBlock> &Comparisons,
388 BCECmpBlock &&Comparison) {
390 <<
"': Found cmp of " <<
Comparison.SizeBits()
391 <<
" bits between " <<
Comparison.Lhs().BaseId <<
" + "
397 Comparisons.push_back(std::move(Comparison));
403 using ContiguousBlocks = std::vector<BCECmpBlock>;
405 BCECmpChain(
const std::vector<BasicBlock *> &Blocks, PHINode &Phi,
409 DomTreeUpdater &DTU);
411 bool atLeastOneMerged()
const {
412 return any_of(MergedBlocks_,
413 [](
const auto &Blocks) {
return Blocks.size() > 1; });
419 std::vector<ContiguousBlocks> MergedBlocks_;
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;
431static unsigned getMinOrigOrder(
const BCECmpChain::ContiguousBlocks &Blocks) {
432 unsigned MinOrigOrder = std::numeric_limits<unsigned>::max();
433 for (
const BCECmpBlock &
Block : Blocks)
434 MinOrigOrder = std::min(MinOrigOrder,
Block.OrigOrder);
440static std::vector<BCECmpChain::ContiguousBlocks>
441mergeBlocks(std::vector<BCECmpBlock> &&Blocks) {
442 std::vector<BCECmpChain::ContiguousBlocks> MergedBlocks;
446 [](
const BCECmpBlock &LhsBlock,
const BCECmpBlock &RhsBlock) {
447 return std::tie(LhsBlock.Lhs(), LhsBlock.Rhs()) <
448 std::tie(RhsBlock.Lhs(), RhsBlock.Rhs());
451 BCECmpChain::ContiguousBlocks *LastMergedBlock =
nullptr;
452 for (BCECmpBlock &
Block : Blocks) {
453 if (!LastMergedBlock || !areContiguous(LastMergedBlock->back(),
Block)) {
454 MergedBlocks.emplace_back();
455 LastMergedBlock = &MergedBlocks.back();
458 << LastMergedBlock->back().BB->getName() <<
"\n");
460 LastMergedBlock->push_back(std::move(
Block));
465 llvm::sort(MergedBlocks, [](
const BCECmpChain::ContiguousBlocks &LhsBlocks,
466 const BCECmpChain::ContiguousBlocks &RhsBlocks) {
467 return getMinOrigOrder(LhsBlocks) < getMinOrigOrder(RhsBlocks);
473BCECmpChain::BCECmpChain(
const std::vector<BasicBlock *> &Blocks, PHINode &Phi,
476 assert(!Blocks.empty() &&
"a chain should have at least one block");
478 std::vector<BCECmpBlock> Comparisons;
479 BaseIdentifier BaseId;
482 if (
Block->hasAddressTaken()) {
486 std::optional<BCECmpBlock> Comparison = visitCmpBlock(
489 LLVM_DEBUG(
dbgs() <<
"chain with invalid BCECmpBlock, no merge.\n");
492 if (Comparison->doesOtherWork()) {
494 <<
"' does extra work besides compare\n");
495 if (Comparisons.empty()) {
509 if (Comparison->canSplit(
AA)) {
511 <<
"Split initial block '" << Comparison->BB->getName()
512 <<
"' that does extra work besides compare\n");
513 Comparison->RequireSplit =
true;
514 enqueueBlock(Comparisons, std::move(*Comparison));
517 <<
"ignoring initial block '" << Comparison->BB->getName()
518 <<
"' that does extra work besides compare\n");
547 enqueueBlock(Comparisons, std::move(*Comparison));
551 if (Comparisons.empty()) {
552 LLVM_DEBUG(
dbgs() <<
"chain with no BCE basic blocks, no merge\n");
555 EntryBlock_ = Comparisons[0].BB;
556 MergedBlocks_ = mergeBlocks(std::move(Comparisons));
563class MergedBlockName {
565 SmallString<16> Scratch;
569 :
Name(makeName(Comparisons)) {}
570 const StringRef
Name;
576 if (Comparisons.
size() == 1)
577 return Comparisons[0].BB->getName();
578 const int size = std::accumulate(Comparisons.
begin(), Comparisons.
end(), 0,
579 [](
int i,
const BCECmpBlock &Cmp) {
580 return i + Cmp.BB->getName().size();
583 return StringRef(
"", 0);
590 const auto append = [
this](StringRef str) {
591 Scratch.
append(str.begin(), str.end());
593 append(Comparisons[0].BB->getName());
594 for (
int I = 1,
E = Comparisons.
size();
I <
E; ++
I) {
601 return Scratch.
str();
612 assert(!Comparisons.
empty() &&
"merging zero comparisons");
614 const BCECmpBlock &FirstCmp = Comparisons[0];
619 NextCmpBlock->
getParent(), InsertBefore);
623 if (FirstCmp.Lhs().GEP)
624 Lhs = Builder.Insert(FirstCmp.Lhs().GEP->clone());
626 Lhs = FirstCmp.Lhs().LoadI->getPointerOperand();
627 if (FirstCmp.Rhs().GEP)
628 Rhs = Builder.Insert(FirstCmp.Rhs().GEP->clone());
630 Rhs = FirstCmp.Rhs().LoadI->getPointerOperand();
632 Value *IsEqual =
nullptr;
640 Comparisons, [](
const BCECmpBlock &
B) {
return B.RequireSplit; });
641 if (ToSplit != Comparisons.
end()) {
643 ToSplit->split(BB,
AA);
646 if (Comparisons.
size() == 1) {
649 Instruction *
const LhsLoad = Builder.Insert(FirstCmp.Lhs().LoadI->clone());
650 Instruction *
const RhsLoad = Builder.Insert(FirstCmp.Rhs().LoadI->clone());
654 IsEqual = Builder.CreateICmpEQ(LhsLoad, RhsLoad);
656 const unsigned TotalSizeBits = std::accumulate(
657 Comparisons.
begin(), Comparisons.
end(), 0u,
658 [](
int Size,
const BCECmpBlock &
C) { return Size + C.SizeBits(); });
665 const auto &
DL =
Phi.getDataLayout();
668 ConstantInt::get(Builder.getIntNTy(SizeTBits), TotalSizeBits / 8),
670 IsEqual = Builder.CreateICmpEQ(
671 MemCmpCall, ConstantInt::get(Builder.getIntNTy(IntBits), 0));
676 if (NextCmpBlock == PhiBB) {
678 Builder.CreateBr(PhiBB);
679 Phi.addIncoming(IsEqual, BB);
683 Builder.CreateCondBr(IsEqual, NextCmpBlock, PhiBB);
693 assert(atLeastOneMerged() &&
"simplifying trivial BCECmpChain");
694 LLVM_DEBUG(
dbgs() <<
"Simplifying comparison chain starting at block "
695 << EntryBlock_->
getName() <<
"\n");
701 for (
const auto &Blocks :
reverse(MergedBlocks_)) {
702 InsertBefore = NextCmpBlock = mergeComparisons(
703 Blocks, InsertBefore, NextCmpBlock, Phi_, TLI, AA, DTU);
714 DTU.
applyUpdates({{DominatorTree::Delete, Pred, EntryBlock_},
715 {DominatorTree::Insert, Pred, NextCmpBlock}});
720 const bool ChainEntryIsFnEntry = EntryBlock_->
isEntryBlock();
721 if (ChainEntryIsFnEntry && DTU.
hasDomTree()) {
723 << EntryBlock_->
getName() <<
" to "
724 << NextCmpBlock->
getName() <<
"\n");
726 DTU.
applyUpdates({{DominatorTree::Delete, NextCmpBlock, EntryBlock_}});
728 EntryBlock_ =
nullptr;
731 SmallVector<BasicBlock *, 16> DeadBlocks;
732 for (
const auto &Blocks : MergedBlocks_) {
733 for (
const BCECmpBlock &
Block : Blocks) {
741 MergedBlocks_.clear();
745std::vector<BasicBlock *> getOrderedBlocks(PHINode &Phi,
746 BasicBlock *
const LastBlock,
749 std::vector<BasicBlock *> Blocks(NumBlocks);
750 assert(LastBlock &&
"invalid last block");
752 for (
int BlockIndex = NumBlocks - 1; BlockIndex > 0; --BlockIndex) {
757 <<
" has its address taken\n");
760 Blocks[BlockIndex] = CurBlock;
762 if (!SinglePredecessor) {
765 <<
" has two or more predecessors\n");
768 if (
Phi.getBasicBlockIndex(SinglePredecessor) < 0) {
771 <<
" does not link back to the phi\n");
774 CurBlock = SinglePredecessor;
776 Blocks[0] = CurBlock;
780bool processPhi(PHINode &Phi,
const TargetLibraryInfo &TLI,
AliasAnalysis &AA,
781 DomTreeUpdater &DTU) {
783 if (
Phi.getNumIncomingValues() <= 1) {
804 for (
unsigned I = 0;
I <
Phi.getNumIncomingValues(); ++
I) {
813 Phi.getIncomingBlock(
I)) {
821 <<
"skip: non-constant value not from cmp or not from last block.\n");
824 LastBlock =
Phi.getIncomingBlock(
I);
837 getOrderedBlocks(Phi, LastBlock,
Phi.getNumIncomingValues());
838 if (Blocks.empty())
return false;
839 BCECmpChain CmpChain(Blocks, Phi, AA);
841 if (!CmpChain.atLeastOneMerged()) {
846 return CmpChain.simplify(TLI, AA, DTU);
849static bool runImpl(Function &
F,
const TargetLibraryInfo &TLI,
860 if (!TLI.
has(LibFunc_memcmp))
863 DomTreeUpdater DTU(DT,
nullptr,
864 DomTreeUpdater::UpdateStrategy::Eager);
866 bool MadeChange =
false;
871 MadeChange |= processPhi(*Phi, TLI, AA, DTU);
877class MergeICmpsLegacyPass :
public FunctionPass {
881 MergeICmpsLegacyPass() : FunctionPass(
ID) {
886 if (skipFunction(
F))
return false;
887 const auto &TLI = getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(
F);
888 const auto &
TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(
F);
891 auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>();
892 auto &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
893 return runImpl(
F, TLI,
TTI, AA, DTWP ? &DTWP->getDomTree() :
nullptr);
897 void getAnalysisUsage(AnalysisUsage &AU)
const override {
908char MergeICmpsLegacyPass::ID = 0;
910 "Merge contiguous icmps into a memcmp",
false,
false)
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, AssumptionCache *AC)
This is the interface for a simple mod/ref and alias analysis over globals.
#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
This file defines the SmallString class.
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 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
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
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.
An instruction for reading from memory.
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 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)
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.
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<X> - Return the argument parameter cast to the specified type.
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.
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<X> - 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()
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.
auto pred_begin(const MachineBasicBlock *BB)
decltype(auto) cast(const From &Val)
cast<X> - 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.
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)