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);
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;
367 if (isHandledGepForm(UserG))
370 Us.insert(&UI.getUse());
381 GepNode *Nx =
new (*Mem) GepNode;
383 Nx->Flags |= GepNode::Internal | InBounds;
395 PN->Flags |= GepNode::Used;
396 Uses[PN].insert_range(Us);
401 NM.insert(std::make_pair(GepI, PN));
404void HexagonCommonGEP::collect() {
407 getBlockTraversalOrder(&Fn->
front(), BO);
415 for (Instruction &J : *
B)
417 if (isHandledGepForm(GepI))
418 processGepInst(GepI, NM);
421 LLVM_DEBUG(
dbgs() <<
"Gep nodes after initial collection:\n" << Nodes);
426 for (GepNode *
N : Nodes) {
427 if (
N->Flags & GepNode::Root) {
431 GepNode *PN =
N->Parent;
432 NCM[PN].push_back(
N);
439 Work.push_back(Root);
442 while (!Work.empty()) {
443 NodeVect::iterator
First = Work.begin();
446 NodeChildrenMap::iterator CF = NCM.find(
N);
447 if (CF != NCM.end()) {
449 Nodes.
insert(CF->second.begin(), CF->second.end());
456 using NodeSymRel = std::set<NodeSet>;
457 using NodePair = std::pair<GepNode *, GepNode *>;
458 using NodePairSet = std::set<NodePair>;
476 return std::make_pair(N1, N2);
477 return std::make_pair(N2, N1);
484 ID.AddPointer(
N->PTy);
485 return ID.computeHash();
488static bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq,
496 NodePairSet::iterator FEq = Eq.find(NP);
499 NodePairSet::iterator FNe = Ne.find(NP);
503 bool Root1 = N1->Flags & GepNode::Root;
504 uint32_t CmpFlags = GepNode::Root | GepNode::Pointer;
505 bool Different = (N1->Flags & CmpFlags) != (N2->Flags & CmpFlags);
511 if (Different || (Root1 && N1->BaseVal != N2->BaseVal)) {
518 if (Root1 ||
node_eq(N1->Parent, N2->Parent, Eq, Ne)) {
525void HexagonCommonGEP::common() {
530 using NodeSetMap = std::map<unsigned, NodeSet>;
533 for (GepNode *
N : Nodes) {
535 MaybeEq[
H].insert(
N);
542 for (
auto &
I : MaybeEq) {
561 std::pair<NodeSymRel::iterator, bool> Ins = EqRel.insert(
C);
563 assert(Ins.second &&
"Cannot add a class");
569 dbgs() <<
"Gep node equality:\n";
570 for (NodePairSet::iterator
I = Eq.begin(),
E = Eq.end();
I !=
E; ++
I)
571 dbgs() <<
"{ " <<
I->first <<
", " <<
I->second <<
" }\n";
573 dbgs() <<
"Gep equivalence classes:\n";
574 for (
const NodeSet &S : EqRel) {
576 for (NodeSet::const_iterator J = S.
begin(),
F = S.
end(); J !=
F; ++J) {
586 using ProjMap = std::map<const NodeSet *, GepNode *>;
588 for (
const NodeSet &S : EqRel) {
590 std::pair<ProjMap::iterator,bool> Ins = PM.insert(std::make_pair(&S, Min));
592 assert(Ins.second &&
"Cannot add minimal element");
596 UseSet &MinUs =
Uses[Min];
597 for (GepNode *
N : S) {
598 uint32_t NF =
N->Flags;
601 if (NF & GepNode::Used) {
603 MinUs.insert_range(U);
611 assert((Min->Flags & Flags) == Min->Flags);
619 for (GepNode *
N : Nodes) {
620 if (
N->Flags & GepNode::Root)
625 ProjMap::iterator
F = PM.find(PC);
629 GepNode *Rep =
F->second;
637 for (GepNode *
N : Nodes) {
641 ProjMap::iterator
F = PM.find(PC);
651 LLVM_DEBUG(
dbgs() <<
"Gep nodes after post-commoning cleanup:\n" << Nodes);
657 dbgs() <<
"NCD of {";
658 for (
typename T::iterator
I = Blocks.begin(),
E = Blocks.end();
I !=
E;
663 dbgs() <<
' ' <<
B->getName();
669 typename T::iterator
I = Blocks.begin(),
E = Blocks.end();
687 typename T::iterator
I = Blocks.begin(),
E = Blocks.end();
689 while (
I !=
E && !*
I)
713 using iterator =
typename T::iterator;
727 if (In->getParent() !=
B)
730 if (std::distance(FirstUse, BEnd) < std::distance(It, BEnd))
737 return B->empty() || (&*
B->begin() ==
B->getTerminator());
740BasicBlock *HexagonCommonGEP::recalculatePlacement(GepNode *Node,
741 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
753 if (
Node->Flags & GepNode::Used) {
756 NodeToUsesMap::iterator
UF =
Uses.find(Node);
757 assert(UF !=
Uses.end() &&
"Used node with no use information");
758 UseSet &Us =
UF->second;
770 NodeChildrenMap::iterator CF = NCM.find(Node);
771 if (CF != NCM.end()) {
772 NodeVect &Cs = CF->second;
773 for (GepNode *CN : Cs) {
774 NodeToValueMap::iterator LF = Loc.find(CN);
780 Bs.push_back(LF->second);
797 DomB =
N->getBlock();
805BasicBlock *HexagonCommonGEP::recalculatePlacementRec(GepNode *Node,
806 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
810 NodeChildrenMap::iterator CF = NCM.find(Node);
811 if (CF != NCM.end()) {
812 NodeVect &Cs = CF->second;
813 for (GepNode *
C : Cs)
814 recalculatePlacementRec(
C, NCM, Loc);
816 BasicBlock *LB = recalculatePlacement(Node, NCM, Loc);
821bool HexagonCommonGEP::isInvariantIn(
Value *Val,
Loop *L) {
831bool HexagonCommonGEP::isInvariantIn(GepNode *Node,
Loop *L) {
832 if (
Node->Flags & GepNode::Root)
833 if (!isInvariantIn(
Node->BaseVal, L))
835 return isInvariantIn(
Node->Idx, L);
838bool HexagonCommonGEP::isInMainPath(BasicBlock *
B,
Loop *L) {
860BasicBlock *HexagonCommonGEP::adjustForInvariance(GepNode *Node,
861 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
866 if (
Node->Flags & GepNode::Root) {
868 Bs.push_back(PIn->getParent());
870 Bs.push_back(Loc[
Node->Parent]);
873 Bs.push_back(IIn->getParent());
888 if (!isInvariantIn(Node, Lp) || !isInMainPath(LocB, Lp))
891 if (!NewLoc || !DT->
dominates(TopB, NewLoc))
900 NodeChildrenMap::iterator CF = NCM.find(Node);
901 if (CF != NCM.end()) {
902 NodeVect &Cs = CF->second;
903 for (GepNode *
C : Cs)
904 adjustForInvariance(
C, NCM, Loc);
911 struct LocationAsBlock {
912 LocationAsBlock(
const NodeToValueMap &L) : Map(
L) {}
914 const NodeToValueMap ⤅
917 [[maybe_unused]] raw_ostream &
operator<<(raw_ostream &OS,
918 const LocationAsBlock &Loc) {
919 for (
const auto &
I : Loc.Map) {
920 OS <<
I.first <<
" -> ";
922 OS <<
B->getName() <<
'(' <<
B <<
')';
924 OS <<
"<null-block>";
930 inline bool is_constant(GepNode *
N) {
936void HexagonCommonGEP::separateChainForNode(GepNode *Node, Use *U,
937 NodeToValueMap &Loc) {
939 LLVM_DEBUG(
dbgs() <<
"Separating chain for node (" << Node <<
") user: " << *R
944 GepNode *
C =
nullptr, *NewNode =
nullptr;
945 while (is_constant(
N) && !(
N->Flags & GepNode::Root)) {
947 GepNode *NewN =
new (*Mem) GepNode(
N);
948 Nodes.push_back(NewN);
953 NewN->Flags &= ~GepNode::Used;
963 NodeToUsesMap::iterator
UF =
Uses.find(Node);
965 UseSet &Us =
UF->second;
968 if (
U->getUser() == R)
975 Node->Flags &= ~GepNode::Used;
980 NewNode->Flags |= GepNode::Used;
981 LLVM_DEBUG(
dbgs() <<
"new node: " << NewNode <<
" " << *NewNode <<
'\n');
983 Uses[NewNode] = NewUs;
986void HexagonCommonGEP::separateConstantChains(GepNode *Node,
987 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
992 LLVM_DEBUG(
dbgs() <<
"Separating constant chains for node: " << Node <<
'\n');
996 for (GepNode *
N : Ns) {
997 if (!(
N->Flags & GepNode::Used))
999 NodeToUsesMap::iterator
UF =
Uses.find(
N);
1001 UseSet &Us =
UF->second;
1011 if (&Ld->getOperandUse(PtrX) == U)
1015 if (&St->getOperandUse(PtrX) == U)
1024 FNs.insert(std::make_pair(
N, LSs));
1029 for (
auto &FN : FNs) {
1030 GepNode *
N = FN.first;
1031 UseSet &Us = FN.second;
1033 separateChainForNode(
N, U, Loc);
1037void HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
1040 NodeChildrenMap NCM;
1046 for (GepNode *Root : Roots)
1047 recalculatePlacementRec(Root, NCM, Loc);
1049 LLVM_DEBUG(
dbgs() <<
"Initial node placement:\n" << LocationAsBlock(Loc));
1052 for (GepNode *Root : Roots)
1053 adjustForInvariance(Root, NCM, Loc);
1055 LLVM_DEBUG(
dbgs() <<
"Node placement after adjustment for invariance:\n"
1056 << LocationAsBlock(Loc));
1059 for (GepNode *Root : Roots)
1060 separateConstantChains(Root, NCM, Loc);
1068 LLVM_DEBUG(
dbgs() <<
"Final node placement:\n" << LocationAsBlock(Loc));
1076 unsigned Num = NA.size();
1077 GepNode *
RN = NA[0];
1078 assert((
RN->Flags & GepNode::Root) &&
"Creating GEP for non-root");
1080 GetElementPtrInst *NewInst =
nullptr;
1086 SmallVector<Value*, 4> IdxList;
1090 if (!(NA[Idx]->Flags & GepNode::Pointer)) {
1091 Type *Int32Ty = Type::getInt32Ty(*Ctx);
1092 IdxList.
push_back(ConstantInt::get(Int32Ty, 0));
1097 while (++Idx <= Num) {
1098 GepNode *
N = NA[Idx-1];
1102 if (NA[Idx]->Flags & GepNode::Pointer)
1111 InpTy = NA[Idx]->PTy;
1113 }
while (Idx <= Num);
1118void HexagonCommonGEP::getAllUsersForNode(GepNode *Node, ValueVect &
Values,
1119 NodeChildrenMap &NCM) {
1121 Work.push_back(Node);
1123 while (!Work.empty()) {
1124 NodeVect::iterator
First = Work.begin();
1127 if (
N->Flags & GepNode::Used) {
1128 NodeToUsesMap::iterator
UF =
Uses.find(
N);
1129 assert(UF !=
Uses.end() &&
"No use information for used node");
1130 UseSet &Us =
UF->second;
1131 for (
const auto &U : Us)
1132 Values.push_back(
U->getUser());
1134 NodeChildrenMap::iterator CF = NCM.find(
N);
1135 if (CF != NCM.end()) {
1136 NodeVect &Cs = CF->second;
1142void HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
1143 LLVM_DEBUG(
dbgs() <<
"Nodes before materialization:\n" << Nodes <<
'\n');
1144 NodeChildrenMap NCM;
1150 while (!Roots.empty()) {
1151 NodeVect::iterator
First = Roots.begin();
1161 bool LastUsed =
false;
1162 unsigned LastCN = 0;
1171 LastUsed = (
Last->Flags & GepNode::Used);
1174 NodeChildrenMap::iterator CF = NCM.find(
Last);
1175 LastCN = (CF != NCM.end()) ? CF->second.size() : 0;
1178 GepNode *Child = CF->second.front();
1180 if (ChildB !=
nullptr && LastB != ChildB)
1186 if (LastUsed || LastCN > 0) {
1188 getAllUsersForNode(Root, Urs, NCM);
1190 if (FirstUse != LastB->
end())
1191 InsertAt = FirstUse;
1195 Value *NewInst = fabricateGEP(NA, InsertAt, LastB);
1200 NodeVect &Cs = NCM[
Last];
1201 for (GepNode *CN : Cs) {
1203 CN->Flags |= GepNode::Root;
1204 CN->BaseVal = NewInst;
1205 Roots.push_back(CN);
1212 NodeToUsesMap::iterator
UF =
Uses.find(
Last);
1213 assert(UF !=
Uses.end() &&
"No use information found");
1214 UseSet &Us =
UF->second;
1221void HexagonCommonGEP::removeDeadCode() {
1223 BO.push_back(&Fn->
front());
1225 for (
unsigned i = 0; i < BO.size(); ++i) {
1228 BO.push_back(DTN->getBlock());
1239 In->eraseFromParent();
1244bool HexagonCommonGEP::runOnFunction(
Function &
F) {
1245 if (skipFunction(
F))
1249 for (
const BasicBlock &BB :
F)
1250 for (
const Instruction &
I : BB)
1255 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1256 PDT = &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
1257 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1258 Ctx = &
F.getContext();
1264 SpecificBumpPtrAllocator<GepNode>
Allocator;
1271 computeNodePlacement(Loc);
1275#ifdef EXPENSIVE_CHECKS
1286 return new HexagonCommonGEP();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
This class is used to gather all the unique data bits of a node.
void AddPointer(const void *Ptr)
Add* - Add various data types to Bit data.
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
user_iterator_impl< Instruction > user_iterator
Specialize the methods defined in Value, as we know that an instruction can only be used by other ins...
user_iterator user_begin()
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.
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)
@ 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.
auto min_element(R &&Range)
Provide wrappers to std::min_element which take ranges instead of having to pass begin/end explicitly...
RelativeUniformCounterPtr Values
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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)