51#define DEBUG_TYPE "commgep"
66 using NodeSet = std::set<GepNode *>;
67 using NodeToValueMap = std::map<GepNode *, Value *>;
68 using NodeVect = std::vector<GepNode *>;
69 using NodeChildrenMap = std::map<GepNode *, NodeVect>;
71 using NodeToUsesMap = std::map<GepNode *, UseSet>;
76 NodeOrdering() =
default;
78 void insert(
const GepNode *
N) { Map.insert(std::make_pair(
N, ++LastNum)); }
79 void clear() { Map.clear(); }
81 bool operator()(
const GepNode *N1,
const GepNode *N2)
const {
82 auto F1 = Map.find(N1), F2 = Map.find(N2);
83 assert(F1 != Map.end() && F2 != Map.end());
84 return F1->second < F2->second;
88 std::map<const GepNode *, unsigned> Map;
96 HexagonCommonGEP() : FunctionPass(ID) {}
99 StringRef getPassName()
const override {
return "Hexagon Common GEP"; }
101 void getAnalysisUsage(AnalysisUsage &AU)
const override {
108 FunctionPass::getAnalysisUsage(AU);
112 using ValueToNodeMap = std::map<Value *, GepNode *>;
113 using ValueVect = std::vector<Value *>;
114 using NodeToValuesMap = std::map<GepNode *, ValueVect>;
116 void getBlockTraversalOrder(BasicBlock *Root, ValueVect &Order);
117 bool isHandledGepForm(GetElementPtrInst *GepI);
118 void processGepInst(GetElementPtrInst *GepI, ValueToNodeMap &NM);
122 BasicBlock *recalculatePlacement(GepNode *Node, NodeChildrenMap &NCM,
123 NodeToValueMap &Loc);
124 BasicBlock *recalculatePlacementRec(GepNode *Node, NodeChildrenMap &NCM,
125 NodeToValueMap &Loc);
126 bool isInvariantIn(
Value *Val, Loop *L);
127 bool isInvariantIn(GepNode *Node, Loop *L);
128 bool isInMainPath(BasicBlock *
B, Loop *L);
129 BasicBlock *adjustForInvariance(GepNode *Node, NodeChildrenMap &NCM,
130 NodeToValueMap &Loc);
131 void separateChainForNode(GepNode *Node, Use *U, NodeToValueMap &Loc);
132 void separateConstantChains(GepNode *Node, NodeChildrenMap &NCM,
133 NodeToValueMap &Loc);
134 void computeNodePlacement(NodeToValueMap &Loc);
138 void getAllUsersForNode(GepNode *Node, ValueVect &Values,
139 NodeChildrenMap &NCM);
140 void materialize(NodeToValueMap &Loc);
142 void removeDeadCode();
146 NodeOrdering NodeOrder;
147 SpecificBumpPtrAllocator<GepNode> *Mem;
151 PostDominatorTree *PDT;
157char HexagonCommonGEP::ID = 0;
243 OS <<
"Parent:" << GN.
Parent;
247 OS << CI->getValue().getSExtValue();
251 OS <<
"<anon> =" << *GN.
Idx;
259 OS <<
"<anon-struct>:" << *STy;
267 template <
typename NodeContainer>
272 OS << *
I <<
' ' << **
I <<
'\n';
282 const NodeToUsesMap &M);
284 for (
const auto &
I : M) {
285 const UseSet &Us =
I.second;
286 OS <<
I.first <<
" -> #" << Us.size() <<
'{';
287 for (
const Use *U : Us) {
288 User *R = U->getUser();
290 OS <<
' ' << R->getName();
292 OS <<
" <?>(" << *R <<
')';
303 return NS.find(
N) != NS.end();
316void HexagonCommonGEP::getBlockTraversalOrder(
BasicBlock *Root,
322 Order.push_back(Root);
324 getBlockTraversalOrder(DTN->getBlock(), Order);
327bool HexagonCommonGEP::isHandledGepForm(GetElementPtrInst *GepI) {
337void HexagonCommonGEP::processGepInst(GetElementPtrInst *GepI,
338 ValueToNodeMap &NM) {
340 GepNode *
N =
new (*Mem) GepNode;
342 uint32_t InBounds = GepI->
isInBounds() ? GepNode::InBounds : 0;
343 ValueToNodeMap::iterator
F = NM.find(PtrOp);
346 N->Flags |= GepNode::Root | InBounds;
351 N->Parent =
F->second;
354 N->Flags |= GepNode::Pointer;
366 if (isHandledGepForm(UserG))
369 Us.insert(&UI.getUse());
380 GepNode *Nx =
new (*Mem) GepNode;
382 Nx->Flags |= GepNode::Internal | InBounds;
394 PN->Flags |= GepNode::Used;
395 Uses[PN].insert_range(Us);
400 NM.insert(std::make_pair(GepI, PN));
403void HexagonCommonGEP::collect() {
406 getBlockTraversalOrder(&Fn->
front(), BO);
414 for (Instruction &J : *
B)
416 if (isHandledGepForm(GepI))
417 processGepInst(GepI, NM);
420 LLVM_DEBUG(
dbgs() <<
"Gep nodes after initial collection:\n" << Nodes);
425 for (GepNode *
N : Nodes) {
426 if (
N->Flags & GepNode::Root) {
430 GepNode *PN =
N->Parent;
431 NCM[PN].push_back(
N);
438 Work.push_back(Root);
441 while (!Work.empty()) {
442 NodeVect::iterator
First = Work.begin();
445 NodeChildrenMap::iterator CF = NCM.find(
N);
446 if (CF != NCM.end()) {
448 Nodes.
insert(CF->second.begin(), CF->second.end());
455 using NodeSymRel = std::set<NodeSet>;
456 using NodePair = std::pair<GepNode *, GepNode *>;
457 using NodePairSet = std::set<NodePair>;
472 uintptr_t P1 =
reinterpret_cast<uintptr_t
>(N1);
473 uintptr_t P2 =
reinterpret_cast<uintptr_t
>(N2);
475 return std::make_pair(N1, N2);
476 return std::make_pair(N2, N1);
482 ID.AddPointer(
N->Idx);
483 ID.AddPointer(
N->PTy);
484 return ID.ComputeHash();
487static bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq,
495 NodePairSet::iterator FEq = Eq.find(NP);
498 NodePairSet::iterator FNe = Ne.find(NP);
502 bool Root1 = N1->Flags & GepNode::Root;
503 uint32_t CmpFlags = GepNode::Root | GepNode::Pointer;
504 bool Different = (N1->Flags & CmpFlags) != (N2->Flags & CmpFlags);
510 if (Different || (Root1 && N1->BaseVal != N2->BaseVal)) {
517 if (Root1 ||
node_eq(N1->Parent, N2->Parent, Eq, Ne)) {
524void HexagonCommonGEP::common() {
529 using NodeSetMap = std::map<unsigned, NodeSet>;
532 for (GepNode *
N : Nodes) {
534 MaybeEq[
H].insert(
N);
541 for (
auto &
I : MaybeEq) {
560 std::pair<NodeSymRel::iterator, bool> Ins = EqRel.insert(
C);
562 assert(Ins.second &&
"Cannot add a class");
568 dbgs() <<
"Gep node equality:\n";
569 for (NodePairSet::iterator
I = Eq.begin(),
E = Eq.end();
I !=
E; ++
I)
570 dbgs() <<
"{ " <<
I->first <<
", " <<
I->second <<
" }\n";
572 dbgs() <<
"Gep equivalence classes:\n";
573 for (
const NodeSet &S : EqRel) {
575 for (NodeSet::const_iterator J = S.
begin(),
F = S.
end(); J !=
F; ++J) {
585 using ProjMap = std::map<const NodeSet *, GepNode *>;
587 for (
const NodeSet &S : EqRel) {
589 std::pair<ProjMap::iterator,bool> Ins = PM.insert(std::make_pair(&S, Min));
591 assert(Ins.second &&
"Cannot add minimal element");
595 UseSet &MinUs =
Uses[Min];
596 for (GepNode *
N : S) {
597 uint32_t NF =
N->Flags;
600 if (NF & GepNode::Used) {
602 MinUs.insert_range(U);
610 assert((Min->Flags & Flags) == Min->Flags);
618 for (GepNode *
N : Nodes) {
619 if (
N->Flags & GepNode::Root)
624 ProjMap::iterator
F = PM.find(PC);
628 GepNode *Rep =
F->second;
636 for (GepNode *
N : Nodes) {
640 ProjMap::iterator
F = PM.find(PC);
650 LLVM_DEBUG(
dbgs() <<
"Gep nodes after post-commoning cleanup:\n" << Nodes);
656 dbgs() <<
"NCD of {";
657 for (
typename T::iterator
I = Blocks.begin(),
E = Blocks.end();
I !=
E;
662 dbgs() <<
' ' <<
B->getName();
668 typename T::iterator
I = Blocks.begin(),
E = Blocks.end();
686 typename T::iterator
I = Blocks.begin(),
E = Blocks.end();
688 while (
I !=
E && !*
I)
712 using iterator =
typename T::iterator;
714 for (
iterator I = Values.begin(),
E = Values.end();
I !=
E; ++
I) {
726 if (In->getParent() !=
B)
729 if (std::distance(FirstUse, BEnd) < std::distance(It, BEnd))
736 return B->empty() || (&*
B->begin() ==
B->getTerminator());
739BasicBlock *HexagonCommonGEP::recalculatePlacement(GepNode *Node,
740 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
752 if (
Node->Flags & GepNode::Used) {
755 NodeToUsesMap::iterator
UF =
Uses.find(Node);
756 assert(UF !=
Uses.end() &&
"Used node with no use information");
757 UseSet &Us =
UF->second;
769 NodeChildrenMap::iterator CF = NCM.find(Node);
770 if (CF != NCM.end()) {
771 NodeVect &Cs = CF->second;
772 for (GepNode *CN : Cs) {
773 NodeToValueMap::iterator LF = Loc.find(CN);
779 Bs.push_back(LF->second);
796 DomB =
N->getBlock();
804BasicBlock *HexagonCommonGEP::recalculatePlacementRec(GepNode *Node,
805 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
809 NodeChildrenMap::iterator CF = NCM.find(Node);
810 if (CF != NCM.end()) {
811 NodeVect &Cs = CF->second;
812 for (GepNode *
C : Cs)
813 recalculatePlacementRec(
C, NCM, Loc);
815 BasicBlock *LB = recalculatePlacement(Node, NCM, Loc);
820bool HexagonCommonGEP::isInvariantIn(
Value *Val, Loop *L) {
830bool HexagonCommonGEP::isInvariantIn(GepNode *Node, Loop *L) {
831 if (
Node->Flags & GepNode::Root)
832 if (!isInvariantIn(
Node->BaseVal, L))
834 return isInvariantIn(
Node->Idx, L);
837bool HexagonCommonGEP::isInMainPath(BasicBlock *
B, Loop *L) {
859BasicBlock *HexagonCommonGEP::adjustForInvariance(GepNode *Node,
860 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
865 if (
Node->Flags & GepNode::Root) {
867 Bs.push_back(PIn->getParent());
869 Bs.push_back(Loc[
Node->Parent]);
872 Bs.push_back(IIn->getParent());
887 if (!isInvariantIn(Node, Lp) || !isInMainPath(LocB, Lp))
890 if (!NewLoc || !DT->
dominates(TopB, NewLoc))
899 NodeChildrenMap::iterator CF = NCM.find(Node);
900 if (CF != NCM.end()) {
901 NodeVect &Cs = CF->second;
902 for (GepNode *
C : Cs)
903 adjustForInvariance(
C, NCM, Loc);
910 struct LocationAsBlock {
911 LocationAsBlock(
const NodeToValueMap &L) : Map(
L) {}
913 const NodeToValueMap ⤅
916 [[maybe_unused]] raw_ostream &
operator<<(raw_ostream &OS,
917 const LocationAsBlock &Loc) {
918 for (
const auto &
I : Loc.Map) {
919 OS <<
I.first <<
" -> ";
921 OS <<
B->getName() <<
'(' <<
B <<
')';
923 OS <<
"<null-block>";
929 inline bool is_constant(GepNode *
N) {
935void HexagonCommonGEP::separateChainForNode(GepNode *Node, Use *U,
936 NodeToValueMap &Loc) {
938 LLVM_DEBUG(
dbgs() <<
"Separating chain for node (" << Node <<
") user: " << *R
943 GepNode *
C =
nullptr, *NewNode =
nullptr;
944 while (is_constant(
N) && !(
N->Flags & GepNode::Root)) {
946 GepNode *NewN =
new (*Mem) GepNode(
N);
947 Nodes.push_back(NewN);
952 NewN->Flags &= ~GepNode::Used;
962 NodeToUsesMap::iterator
UF =
Uses.find(Node);
964 UseSet &Us =
UF->second;
967 if (
U->getUser() == R)
974 Node->Flags &= ~GepNode::Used;
979 NewNode->Flags |= GepNode::Used;
980 LLVM_DEBUG(
dbgs() <<
"new node: " << NewNode <<
" " << *NewNode <<
'\n');
982 Uses[NewNode] = NewUs;
985void HexagonCommonGEP::separateConstantChains(GepNode *Node,
986 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
991 LLVM_DEBUG(
dbgs() <<
"Separating constant chains for node: " << Node <<
'\n');
995 for (GepNode *
N : Ns) {
996 if (!(
N->Flags & GepNode::Used))
998 NodeToUsesMap::iterator
UF =
Uses.find(
N);
1000 UseSet &Us =
UF->second;
1010 if (&Ld->getOperandUse(PtrX) == U)
1014 if (&St->getOperandUse(PtrX) == U)
1023 FNs.insert(std::make_pair(
N, LSs));
1028 for (
auto &FN : FNs) {
1029 GepNode *
N = FN.first;
1030 UseSet &Us = FN.second;
1032 separateChainForNode(
N, U, Loc);
1036void HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
1039 NodeChildrenMap NCM;
1045 for (GepNode *Root : Roots)
1046 recalculatePlacementRec(Root, NCM, Loc);
1048 LLVM_DEBUG(
dbgs() <<
"Initial node placement:\n" << LocationAsBlock(Loc));
1051 for (GepNode *Root : Roots)
1052 adjustForInvariance(Root, NCM, Loc);
1054 LLVM_DEBUG(
dbgs() <<
"Node placement after adjustment for invariance:\n"
1055 << LocationAsBlock(Loc));
1058 for (GepNode *Root : Roots)
1059 separateConstantChains(Root, NCM, Loc);
1067 LLVM_DEBUG(
dbgs() <<
"Final node placement:\n" << LocationAsBlock(Loc));
1075 unsigned Num = NA.size();
1076 GepNode *
RN = NA[0];
1077 assert((
RN->Flags & GepNode::Root) &&
"Creating GEP for non-root");
1079 GetElementPtrInst *NewInst =
nullptr;
1085 SmallVector<Value*, 4> IdxList;
1089 if (!(NA[Idx]->Flags & GepNode::Pointer)) {
1096 while (++Idx <= Num) {
1097 GepNode *
N = NA[Idx-1];
1101 if (NA[Idx]->Flags & GepNode::Pointer)
1110 InpTy = NA[Idx]->PTy;
1112 }
while (Idx <= Num);
1117void HexagonCommonGEP::getAllUsersForNode(GepNode *Node, ValueVect &Values,
1118 NodeChildrenMap &NCM) {
1120 Work.push_back(Node);
1122 while (!Work.empty()) {
1123 NodeVect::iterator
First = Work.begin();
1126 if (
N->Flags & GepNode::Used) {
1127 NodeToUsesMap::iterator
UF =
Uses.find(
N);
1128 assert(UF !=
Uses.end() &&
"No use information for used node");
1129 UseSet &Us =
UF->second;
1130 for (
const auto &U : Us)
1131 Values.push_back(
U->getUser());
1133 NodeChildrenMap::iterator CF = NCM.find(
N);
1134 if (CF != NCM.end()) {
1135 NodeVect &Cs = CF->second;
1141void HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
1142 LLVM_DEBUG(
dbgs() <<
"Nodes before materialization:\n" << Nodes <<
'\n');
1143 NodeChildrenMap NCM;
1149 while (!Roots.empty()) {
1150 NodeVect::iterator
First = Roots.begin();
1160 bool LastUsed =
false;
1161 unsigned LastCN = 0;
1170 LastUsed = (
Last->Flags & GepNode::Used);
1173 NodeChildrenMap::iterator CF = NCM.find(
Last);
1174 LastCN = (CF != NCM.end()) ? CF->second.size() : 0;
1177 GepNode *Child = CF->second.front();
1179 if (ChildB !=
nullptr && LastB != ChildB)
1185 if (LastUsed || LastCN > 0) {
1187 getAllUsersForNode(Root, Urs, NCM);
1189 if (FirstUse != LastB->
end())
1190 InsertAt = FirstUse;
1194 Value *NewInst = fabricateGEP(NA, InsertAt, LastB);
1199 NodeVect &Cs = NCM[
Last];
1200 for (GepNode *CN : Cs) {
1202 CN->Flags |= GepNode::Root;
1203 CN->BaseVal = NewInst;
1204 Roots.push_back(CN);
1211 NodeToUsesMap::iterator
UF =
Uses.find(
Last);
1212 assert(UF !=
Uses.end() &&
"No use information found");
1213 UseSet &Us =
UF->second;
1220void HexagonCommonGEP::removeDeadCode() {
1222 BO.push_back(&Fn->
front());
1224 for (
unsigned i = 0; i < BO.size(); ++i) {
1227 BO.push_back(DTN->getBlock());
1238 In->eraseFromParent();
1243bool HexagonCommonGEP::runOnFunction(Function &
F) {
1244 if (skipFunction(
F))
1248 for (
const BasicBlock &BB :
F)
1249 for (
const Instruction &
I : BB)
1254 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1255 PDT = &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
1256 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1257 Ctx = &
F.getContext();
1263 SpecificBumpPtrAllocator<GepNode>
Allocator;
1270 computeNodePlacement(Loc);
1274#ifdef EXPENSIVE_CHECKS
1285 return new HexagonCommonGEP();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
This file defines a hash set that can be used to remove duplication of nodes in a graph.
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
static unsigned node_hash(GepNode *N)
static cl::opt< bool > OptEnableInv("commgep-inv", cl::init(true), cl::Hidden)
static NodePair node_pair(GepNode *N1, GepNode *N2)
static bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq, NodePairSet &Ne)
static const NodeSet * node_class(GepNode *N, NodeSymRel &Rel)
static cl::opt< bool > OptEnableConst("commgep-const", cl::init(true), cl::Hidden)
static BasicBlock * nearest_common_dominatee(DominatorTree *DT, T &Blocks)
static cl::opt< bool > OptSpeculate("commgep-speculate", cl::init(true), cl::Hidden)
static void invert_find_roots(const NodeVect &Nodes, NodeChildrenMap &NCM, NodeVect &Roots)
static BasicBlock * nearest_common_dominator(DominatorTree *DT, T &Blocks)
static bool is_empty(const BasicBlock *B)
static void nodes_for_root(GepNode *Root, NodeChildrenMap &NCM, NodeSet &Nodes)
static BasicBlock * preheader(DominatorTree *DT, Loop *L)
static BasicBlock::iterator first_use_of_in_block(T &Values, BasicBlock *B)
This defines the Use class.
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Remove Loads Into Fake Uses
This file implements a set that has insertion order iteration characteristics.
This file defines the SmallVector class.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
LLVM_ABI BasicBlock::iterator erase(BasicBlock::iterator FromIt, BasicBlock::iterator ToIt)
Erases a range of instructions from FromIt to (not including) ToIt.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
This is the shared class of boolean and integer constants.
DomTreeNodeBase * getIDom() const
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
bool properlyDominates(const DomTreeNodeBase< NodeT > *A, const DomTreeNodeBase< NodeT > *B) const
properlyDominates - Returns true iff A dominates B and A != B.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI Instruction * findNearestCommonDominator(Instruction *I1, Instruction *I2) const
Find the nearest instruction I that dominates both I1 and I2, in the sense that a result produced bef...
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
FunctionPass class - This class is used to implement most global optimizations.
const BasicBlock & front() const
LLVM_ABI bool isInBounds() const
Determine whether the GEP has the inbounds flag.
static LLVM_ABI Type * getTypeAtIndex(Type *Ty, Value *Idx)
Return the type of the element at the given index of an indexable type.
Value * getPointerOperand()
iterator_range< op_iterator > indices()
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
LLVM_ABI void setIsInBounds(bool b=true)
Set or clear the inbounds flag on this GEP instruction.
Type * getSourceElementType() const
static unsigned getPointerOperandIndex()
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
The legacy pass manager's analysis pass to compute loop information.
Represents a single loop in the control flow graph.
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
SetVector< SUnit * >::const_iterator iterator
LLVM_ABI bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
A vector that has set insertion semantics.
void push_back(const T &Elt)
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
static unsigned getPointerOperandIndex()
Class to represent struct types.
bool isLiteral() const
Return true if this type is uniqued by structural equivalence, false if it is a struct definition.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isPointerTy() const
True if this is an instance of PointerType.
LLVM_ABI StringRef getStructName() const
bool isStructTy() const
True if this is an instance of StructType.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
user_iterator user_begin()
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
const ParentTy * getParent() const
self_iterator getIterator()
This class implements an extremely fast bulk output stream that can only output to a stream.
void dump_node_container(raw_ostream &OS, const NodeContainer &S)
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.
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< NodeBase * > Node
std::set< NodeId > NodeSet
friend class Instruction
Iterator for Instructions in a `BasicBlock.
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.
FunctionAddr VTableAddr Value
auto min_element(R &&Range)
Provide wrappers to std::min_element which take ranges instead of having to pass begin/end explicitly...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
FunctionAddr VTableAddr uintptr_t uintptr_t Int32Ty
LLVM_ABI bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
auto cast_or_null(const Y &Val)
DomTreeNodeBase< BasicBlock > DomTreeNode
LLVM_ABI bool isInstructionTriviallyDead(Instruction *I, const TargetLibraryInfo *TLI=nullptr)
Return true if the result produced by the instruction is not used, and the instruction will return.
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
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.
FunctionPass * createHexagonCommonGEP()
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)
GepNode(const GepNode *N)