57#define DEBUG_TYPE "mem2reg"
59STATISTIC(NumLocalPromoted,
"Number of alloca's promoted within one block");
60STATISTIC(NumSingleStore,
"Number of alloca's promoted with a single store");
61STATISTIC(NumDeadAlloca,
"Number of dead alloca's removed");
62STATISTIC(NumPHIInsert,
"Number of PHI nodes inserted");
67 if (
const LoadInst *LI = dyn_cast<LoadInst>(U)) {
72 }
else if (
const StoreInst *SI = dyn_cast<StoreInst>(U)) {
73 if (SI->getValueOperand() == AI ||
81 if (!
II->isLifetimeStartOrEnd() && !
II->isDroppable())
83 }
else if (
const BitCastInst *BCI = dyn_cast<BitCastInst>(U)) {
87 if (!GEPI->hasAllZeroIndices())
119 DIB.insertDbgValueIntrinsic(NewValue, Variable,
Expression, DI, InsertBefore);
123class AssignmentTrackingInfo {
145 void updateForDeletedStore(
161 auto InsertValueForAssign = [&](
auto *DbgAssign,
auto *&AssignList) {
163 AssignList->insert(DbgAssign);
164 createDebugValue(DIB, DbgAssign->getValue(), DbgAssign->getVariable(),
165 DbgAssign->getExpression(), DbgAssign->getDebugLoc(),
169 InsertValueForAssign(Assign, DbgAssignsToDelete);
171 InsertValueForAssign(Assign, DVRAssignsToDelete);
181 auto ConvertUnlinkedAssignToValue = [&](
auto *
Assign) {
186 for_each(DbgAssigns, ConvertUnlinkedAssignToValue);
187 for_each(DVRAssigns, ConvertUnlinkedAssignToValue);
196 for (
auto *DAI : DbgAssigns)
198 for (
auto *DVR : DVRAssigns)
206 bool empty() {
return DbgAssigns.empty() && DVRAssigns.
empty(); }
218 bool OnlyUsedInOneBlock;
224 AssignmentTrackingInfo AssignmentTracking;
227 DefiningBlocks.
clear();
231 OnlyUsedInOneBlock =
true;
234 AssignmentTracking.clear();
259 if (OnlyUsedInOneBlock) {
261 OnlyBlock =
User->getParent();
262 else if (OnlyBlock !=
User->getParent())
263 OnlyUsedInOneBlock =
false;
266 DbgUserVec AllDbgUsers;
269 std::copy_if(AllDbgUsers.begin(), AllDbgUsers.end(),
271 return !isa<DbgAssignIntrinsic>(DII);
273 std::copy_if(AllDPUsers.
begin(), AllDPUsers.
end(),
274 std::back_inserter(DPUsers),
276 AssignmentTracking.init(AI);
281struct RenamePassData {
282 using ValVector = std::vector<Value *>;
283 using LocationVector = std::vector<DebugLoc>;
299class LargeBlockInfo {
310 static bool isInterestingInstruction(
const Instruction *
I) {
311 return (isa<LoadInst>(
I) && isa<AllocaInst>(
I->getOperand(0))) ||
312 (isa<StoreInst>(
I) && isa<AllocaInst>(
I->getOperand(1)));
317 assert(isInterestingInstruction(
I) &&
318 "Not a load/store to/from an alloca?");
322 if (It != InstNumbers.
end())
331 if (isInterestingInstruction(&BBI))
332 InstNumbers[&BBI] = InstNo++;
333 It = InstNumbers.
find(
I);
335 assert(It != InstNumbers.
end() &&
"Didn't insert instruction?");
344struct PromoteMem2Reg {
346 std::vector<AllocaInst *> Allocas;
398 : Allocas(Allocas.
begin(), Allocas.
end()), DT(DT),
400 AC(AC), SQ(DT.getRoot()->getDataLayout(),
406 void RemoveFromAllocasList(
unsigned &AllocaIdx) {
407 Allocas[AllocaIdx] = Allocas.back();
413 unsigned &NP = BBNumPreds[BB];
423 RenamePassData::ValVector &IncVals,
424 RenamePassData::LocationVector &IncLocs,
425 std::vector<RenamePassData> &Worklist);
426 bool QueuePhiNode(
BasicBlock *BB,
unsigned AllocaIdx,
unsigned &Version);
429 void cleanUpDbgAssigns() {
430 for (
auto *DAI : DbgAssignsToDelete)
431 DAI->eraseFromParent();
432 DbgAssignsToDelete.clear();
433 for (
auto *DVR : DVRAssignsToDelete)
434 DVR->eraseFromParent();
435 DVRAssignsToDelete.clear();
456 if (isa<UndefValue>(Val) && LI->
hasMetadata(LLVMContext::MD_noundef)) {
461 false,
Align(1), LI);
469 if (AC && LI->
getMetadata(LLVMContext::MD_nonnull) &&
481 if (isa<LoadInst>(
I) || isa<StoreInst>(
I))
485 if (
I->isDroppable()) {
486 I->dropDroppableUse(U);
490 if (!
I->getType()->isVoidTy()) {
495 Instruction *Inst = cast<Instruction>(UU.getUser());
505 I->eraseFromParent();
524 bool StoringGlobalVal = !isa<Instruction>(OnlyStore->
getOperand(0));
529 Info.UsingBlocks.clear();
533 if (UserInst == OnlyStore)
535 LoadInst *LI = cast<LoadInst>(UserInst);
541 if (!StoringGlobalVal) {
546 if (StoreIndex == -1)
547 StoreIndex = LBI.getInstructionIndex(OnlyStore);
549 if (
unsigned(StoreIndex) > LBI.getInstructionIndex(LI)) {
551 Info.UsingBlocks.push_back(StoreBB);
577 if (!
Info.UsingBlocks.empty())
582 Info.AssignmentTracking.updateForDeletedStore(
583 Info.OnlyStore, DIB, DbgAssignsToDelete, DVRAssignsToDelete);
587 auto ConvertDebugInfoForStore = [&](
auto &Container) {
588 for (
auto *DbgItem : Container) {
589 if (DbgItem->isAddressOfVariable()) {
591 DbgItem->eraseFromParent();
592 }
else if (DbgItem->getExpression()->startsWithDeref()) {
593 DbgItem->eraseFromParent();
597 ConvertDebugInfoForStore(
Info.DbgUsers);
598 ConvertDebugInfoForStore(
Info.DPUsers);
604 Info.OnlyStore->eraseFromParent();
605 LBI.deleteValue(
Info.OnlyStore);
640 StoresByIndexTy StoresByIndex;
643 if (
StoreInst *SI = dyn_cast<StoreInst>(U))
644 StoresByIndex.
push_back(std::make_pair(LBI.getInstructionIndex(SI), SI));
653 LoadInst *LI = dyn_cast<LoadInst>(U);
657 unsigned LoadIdx = LBI.getInstructionIndex(LI);
662 std::make_pair(LoadIdx,
static_cast<StoreInst *
>(
nullptr)),
665 if (
I == StoresByIndex.begin()) {
666 if (StoresByIndex.empty())
676 ReplVal = std::prev(
I)->second->getOperand(0);
696 Info.AssignmentTracking.updateForDeletedStore(SI, DIB, DbgAssignsToDelete,
699 auto DbgUpdateForStore = [&](
auto &Container) {
700 for (
auto *DbgItem : Container) {
701 if (DbgItem->isAddressOfVariable()) {
706 DbgUpdateForStore(
Info.DbgUsers);
707 DbgUpdateForStore(
Info.DPUsers);
709 SI->eraseFromParent();
718 auto DbgUpdateForAlloca = [&](
auto &Container) {
719 for (
auto *DbgItem : Container)
720 if (DbgItem->isAddressOfVariable() ||
721 DbgItem->getExpression()->startsWithDeref())
722 DbgItem->eraseFromParent();
724 DbgUpdateForAlloca(
Info.DbgUsers);
725 DbgUpdateForAlloca(
Info.DPUsers);
731void PromoteMem2Reg::run() {
734 AllocaDbgUsers.
resize(Allocas.size());
735 AllocaATInfo.
resize(Allocas.size());
736 AllocaDPUsers.
resize(Allocas.size());
742 for (
unsigned AllocaNum = 0; AllocaNum != Allocas.size(); ++AllocaNum) {
747 "All allocas should be in the same function, which is same as DF!");
756 RemoveFromAllocasList(AllocaNum);
763 Info.AnalyzeAlloca(AI);
767 if (
Info.DefiningBlocks.size() == 1) {
769 &DbgAssignsToDelete, &DVRAssignsToDelete)) {
771 RemoveFromAllocasList(AllocaNum);
779 if (
Info.OnlyUsedInOneBlock &&
781 &DbgAssignsToDelete, &DVRAssignsToDelete)) {
783 RemoveFromAllocasList(AllocaNum);
789 if (BBNumbers.
empty()) {
792 BBNumbers[&BB] =
ID++;
796 if (!
Info.DbgUsers.empty())
797 AllocaDbgUsers[AllocaNum] =
Info.DbgUsers;
798 if (!
Info.AssignmentTracking.empty())
799 AllocaATInfo[AllocaNum] =
Info.AssignmentTracking;
800 if (!
Info.DPUsers.empty())
801 AllocaDPUsers[AllocaNum] =
Info.DPUsers;
804 AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
808 Info.DefiningBlocks.end());
819 IDF.setLiveInBlocks(LiveInBlocks);
820 IDF.setDefiningBlocks(DefBlocks);
822 IDF.calculate(PHIBlocks);
824 return BBNumbers.
find(
A)->second < BBNumbers.
find(
B)->second;
829 QueuePhiNode(BB, AllocaNum, CurrentVersion);
832 if (Allocas.empty()) {
841 RenamePassData::ValVector Values(Allocas.size());
842 for (
unsigned i = 0, e = Allocas.size(); i != e; ++i)
847 RenamePassData::LocationVector
Locations(Allocas.size());
851 std::vector<RenamePassData> RenamePassWorkList;
852 RenamePassWorkList.emplace_back(&
F.front(),
nullptr, std::move(Values),
853 std::move(Locations));
855 RenamePassData RPD = std::move(RenamePassWorkList.back());
856 RenamePassWorkList.pop_back();
858 RenamePass(RPD.BB, RPD.Pred, RPD.Values, RPD.Locations, RenamePassWorkList);
859 }
while (!RenamePassWorkList.empty());
873 A->eraseFromParent();
877 auto RemoveDbgDeclares = [&](
auto &Container) {
878 for (
auto &DbgUsers : Container) {
879 for (
auto *DbgItem : DbgUsers)
880 if (DbgItem->isAddressOfVariable() ||
881 DbgItem->getExpression()->startsWithDeref())
882 DbgItem->eraseFromParent();
885 RemoveDbgDeclares(AllocaDbgUsers);
886 RemoveDbgDeclares(AllocaDPUsers);
892 bool EliminatedAPHI =
true;
893 while (EliminatedAPHI) {
894 EliminatedAPHI =
false;
902 E = NewPhiNodes.
end();
911 EliminatedAPHI =
true;
925 E = NewPhiNodes.
end();
931 if (&BB->
front() != SomePHI)
947 return BBNumbers.
find(
A)->second < BBNumbers.
find(
B)->second;
958 "PHI node has entry for a block which is not a predecessor!");
970 while ((SomePHI = dyn_cast<PHINode>(BBI++)) &&
987void PromoteMem2Reg::ComputeLiveInBlocks(
995 Info.UsingBlocks.end());
1000 for (
unsigned i = 0, e = LiveInBlockWorklist.size(); i != e; ++i) {
1002 if (!DefBlocks.
count(BB))
1008 if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
1009 if (
SI->getOperand(1) != AI)
1014 LiveInBlockWorklist[i] = LiveInBlockWorklist.
back();
1015 LiveInBlockWorklist.pop_back();
1021 if (
LoadInst *LI = dyn_cast<LoadInst>(
I))
1031 while (!LiveInBlockWorklist.empty()) {
1032 BasicBlock *BB = LiveInBlockWorklist.pop_back_val();
1036 if (!LiveInBlocks.
insert(BB).second)
1048 LiveInBlockWorklist.push_back(
P);
1056bool PromoteMem2Reg::QueuePhiNode(
BasicBlock *BB,
unsigned AllocaNo,
1057 unsigned &Version) {
1059 PHINode *&PN = NewPhiNodes[std::make_pair(BBNumbers[BB], AllocaNo)];
1067 PN =
PHINode::Create(Allocas[AllocaNo]->getAllocatedType(), getNumPreds(BB),
1068 Allocas[AllocaNo]->
getName() +
"." +
Twine(Version++));
1071 PhiToAllocaMap[PN] = AllocaNo;
1078 bool ApplyMergedLoc) {
1091 RenamePassData::ValVector &IncomingVals,
1092 RenamePassData::LocationVector &IncomingLocs,
1093 std::vector<RenamePassData> &Worklist) {
1100 if (PhiToAllocaMap.
count(APN)) {
1107 unsigned NewPHINumOperands = APN->getNumOperands();
1110 assert(NumEdges &&
"Must be at least one edge from Pred to BB!");
1115 unsigned AllocaNo = PhiToAllocaMap[APN];
1119 APN->getNumIncomingValues() > 0);
1122 for (
unsigned i = 0; i != NumEdges; ++i)
1123 APN->addIncoming(IncomingVals[AllocaNo], Pred);
1126 IncomingVals[AllocaNo] = APN;
1127 AllocaATInfo[AllocaNo].updateForNewPhi(APN, DIB);
1128 auto ConvertDbgDeclares = [&](
auto &Container) {
1129 for (
auto *DbgItem : Container)
1130 if (DbgItem->isAddressOfVariable())
1133 ConvertDbgDeclares(AllocaDbgUsers[AllocaNo]);
1134 ConvertDbgDeclares(AllocaDPUsers[AllocaNo]);
1138 APN = dyn_cast<PHINode>(PNI);
1144 }
while (APN->getNumOperands() == NewPHINumOperands);
1149 if (!Visited.
insert(BB).second)
1155 if (
LoadInst *LI = dyn_cast<LoadInst>(
I)) {
1161 if (AI == AllocaLookup.
end())
1164 Value *
V = IncomingVals[AI->second];
1170 }
else if (
StoreInst *SI = dyn_cast<StoreInst>(
I)) {
1173 AllocaInst *Dest = dyn_cast<AllocaInst>(
SI->getPointerOperand());
1178 if (ai == AllocaLookup.
end())
1182 unsigned AllocaNo = ai->second;
1183 IncomingVals[AllocaNo] =
SI->getOperand(0);
1186 IncomingLocs[AllocaNo] =
SI->getDebugLoc();
1187 AllocaATInfo[AllocaNo].updateForDeletedStore(SI, DIB, &DbgAssignsToDelete,
1188 &DVRAssignsToDelete);
1189 auto ConvertDbgDeclares = [&](
auto &Container) {
1190 for (
auto *DbgItem : Container)
1191 if (DbgItem->isAddressOfVariable())
1194 ConvertDbgDeclares(AllocaDbgUsers[ai->second]);
1195 ConvertDbgDeclares(AllocaDPUsers[ai->second]);
1196 SI->eraseFromParent();
1215 if (VisitedSuccs.
insert(*I).second)
1216 Worklist.emplace_back(*
I, Pred, IncomingVals, IncomingLocs);
1224 if (Allocas.
empty())
1227 PromoteMem2Reg(Allocas, DT, AC).run();
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Analysis containing CSE Info
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static void clear(coro::Shape &Shape)
This file defines the DenseMap class.
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void ComputeLiveInBlocks(const SmallPtrSetImpl< BasicBlock * > &UsingBlocks, const SmallPtrSetImpl< BasicBlock * > &DefBlocks, SmallPtrSetImpl< BasicBlock * > &LiveInBlocks, PredIteratorCache &PredCache)
Given sets of UsingBlocks and DefBlocks, compute the set of LiveInBlocks.
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
This class represents a conversion between pointers from one address space to another.
an instruction to allocate memory on the stack
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool empty() const
empty - Check if the array is empty.
A cache of @llvm.assume calls within a function.
void registerAssumption(AssumeInst *CI)
Add an @llvm.assume intrinsic to this function's cache.
LLVM Basic Block Representation.
iterator begin()
Instruction iterator methods.
const Instruction & front() const
const Function * getParent() const
Return the enclosing method, or null if none.
InstListType::iterator iterator
Instruction iterators...
const Instruction & back() const
This class represents a no-op cast from one type to another.
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)
static ConstantInt * getTrue(LLVMContext &Context)
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
A parsed version of the target data layout string in and methods for querying it.
This represents the llvm.dbg.assign instruction.
This is the common base class for debug info intrinsics for variables.
Record of a variable value-assignment, aka a non instruction representation of the dbg....
static DbgVariableRecord * createDbgVariableRecord(Value *Location, DILocalVariable *DV, DIExpression *Expr, const DILocation *DI)
Identifies a unique instance of a whole variable (discards/ignores fragment information).
Identifies a unique instance of a variable.
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
Class representing an expression and its matching format.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
This instruction compares its operands according to the predicate given to the constructor.
void insertBefore(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified instruction.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
bool hasMetadata() const
Return true if this instruction has any metadata attached to it.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
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 applyMergedLocation(DILocation *LocA, DILocation *LocB)
Merge 2 debug locations and apply it to the Instruction.
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
void insertAfter(Instruction *InsertPos)
Insert an unlinked instruction into a basic block immediately after the specified instruction.
A wrapper class for inspecting calls to intrinsic functions.
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
Value * getPointerOperand()
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
BasicBlock * getIncomingBlock(unsigned i) const
Return incoming basic block number i.
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 PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
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.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
bool contains(const T &V) const
Check if the SmallSet contains the given element.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
typename SuperClass::iterator iterator
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
static UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) const
bool isDroppable() const
A droppable user is a user for which uses can be dropped without affecting correctness and should be ...
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
static void dropDroppableUse(Use &U)
Remove the droppable use U.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< use_iterator > uses()
const ParentTy * getParent() const
Function * getDeclaration(Module *M, ID id, ArrayRef< Type * > Tys=std::nullopt)
Create or insert an LLVM Function declaration for an intrinsic, and return it.
AssignmentMarkerRange getAssignmentMarkers(DIAssignID *ID)
Return a range of dbg.assign intrinsics which use \ID as an operand.
SmallVector< DbgVariableRecord * > getDVRAssignmentMarkers(const Instruction *Inst)
void deleteAssignmentMarkers(const Instruction *Inst)
Delete the llvm.dbg.assign intrinsics linked to Inst.
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
const_iterator end(StringRef path)
Get end iterator over path.
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
void PromoteMemToReg(ArrayRef< AllocaInst * > Allocas, DominatorTree &DT, AssumptionCache *AC=nullptr)
Promote the specified list of alloca instructions into scalar registers, inserting PHI nodes as appro...
void findDbgUsers(SmallVectorImpl< DbgVariableIntrinsic * > &DbgInsts, Value *V, SmallVectorImpl< DbgVariableRecord * > *DbgVariableRecords=nullptr)
Finds the debug info intrinsics describing a value.
auto successors(const MachineBasicBlock *BB)
bool onlyUsedByLifetimeMarkersOrDroppableInsts(const Value *V)
Return true if the only users of this pointer are lifetime markers or droppable instructions.
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...
bool isAllocaPromotable(const AllocaInst *AI)
Return true if this alloca is legal for promotion.
Value * simplifyInstruction(Instruction *I, const SimplifyQuery &Q)
See if we can compute a simplified version of this instruction.
void sort(IteratorTy Start, IteratorTy End)
void ConvertDebugDeclareToDebugValue(DbgVariableIntrinsic *DII, StoreInst *SI, DIBuilder &Builder)
===------------------------------------------------------------------—===// Dbg Intrinsic utilities
bool isKnownNonZero(const Value *V, const SimplifyQuery &Q, unsigned Depth=0)
Return true if the given value is known to be non-zero when defined.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
bool onlyUsedByLifetimeMarkers(const Value *V)
Return true if the only users of this pointer are lifetime markers.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
auto predecessors(const MachineBasicBlock *BB)
unsigned pred_size(const MachineBasicBlock *BB)
Implement std::hash so that hash_code can be used in STL containers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
Function object to check whether the first component of a container supported by std::get (like std::...