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);
84 return F1->second < F2->second;
88 std::map<const GepNode *, unsigned>
Map;
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);
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);
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();
157char HexagonCommonGEP::ID = 0;
203 BaseVal =
N->BaseVal;
214 if (GN.
Flags & GepNode::Root) {
218 if (GN.
Flags & GepNode::Internal) {
224 if (GN.
Flags & GepNode::Used) {
229 if (GN.
Flags & GepNode::InBounds) {
234 if (GN.
Flags & GepNode::Pointer) {
240 if (GN.
Flags & GepNode::Root)
247 OS << CI->getValue().getSExtValue();
251 OS <<
"<anon> =" << *GN.
Idx;
259 OS <<
"<anon-struct>:" << *STy;
267 template <
typename NodeContainer>
269 using const_iterator =
typename NodeContainer::const_iterator;
271 for (const_iterator
I = S.begin(), E = S.end();
I != E; ++
I)
272 OS << *
I <<
' ' << **
I <<
'\n';
285 for (
const auto &
I : M) {
286 const UseSet &Us =
I.second;
287 OS <<
I.first <<
" -> #" << Us.size() <<
'{';
288 for (
const Use *U : Us) {
289 User *R = U->getUser();
291 OS <<
' ' << R->getName();
293 OS <<
" <?>(" << *R <<
')';
304 return NS.find(
N) != NS.end();
317void HexagonCommonGEP::getBlockTraversalOrder(
BasicBlock *Root,
323 Order.push_back(Root);
324 for (
auto *DTN : children<DomTreeNode*>(DT->
getNode(Root)))
325 getBlockTraversalOrder(DTN->getBlock(), Order);
339 ValueToNodeMap &NM) {
341 GepNode *
N =
new (*Mem) GepNode;
344 ValueToNodeMap::iterator
F = NM.find(PtrOp);
347 N->Flags |= GepNode::Root | InBounds;
352 N->Parent =
F->second;
355 N->Flags |= GepNode::Pointer;
365 if (isa<GetElementPtrInst>(*UI)) {
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);
416 if (
auto *GepI = dyn_cast<GetElementPtrInst>(&J))
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>;
473 uintptr_t P1 =
reinterpret_cast<uintptr_t
>(N1);
474 uintptr_t P2 =
reinterpret_cast<uintptr_t
>(N2);
476 return std::make_pair(N1, N2);
477 return std::make_pair(N2, N1);
483 ID.AddPointer(
N->Idx);
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) {
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();
689 while (
I != E && !*
I)
713 using iterator =
typename T::iterator;
715 for (iterator
I = Values.begin(), E = Values.end();
I != E; ++
I) {
724 if (!isa<Instruction>(V))
727 if (In->getParent() !=
B)
730 if (std::distance(FirstUse, BEnd) < std::distance(It, BEnd))
737 return B->empty() || (&*
B->begin() ==
B->getTerminator());
741 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
753 if (
Node->Flags & GepNode::Used) {
757 assert(UF !=
Uses.end() &&
"Used node with no use information");
758 UseSet &Us =
UF->second;
761 if (!isa<Instruction>(R))
764 ? cast<PHINode>(R)->getIncomingBlock(*U)
765 : cast<Instruction>(R)->getParent();
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);
821bool HexagonCommonGEP::isInvariantIn(
Value *Val,
Loop *L) {
822 if (isa<Constant>(Val) || isa<Argument>(Val))
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);
842 if (PDT->dominates(
B, HB))
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());
886 Loop *Lp = LI->getLoopFor(LocB);
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 &
Map;
920 for (
const auto &
I : Loc.Map) {
921 OS <<
I.first <<
" -> ";
923 OS <<
B->getName() <<
'(' <<
B <<
')';
925 OS <<
"<null-block>";
931 inline bool is_constant(GepNode *
N) {
932 return isa<ConstantInt>(
N->Idx);
937void HexagonCommonGEP::separateChainForNode(GepNode *
Node,
Use *U,
938 NodeToValueMap &Loc) {
945 GepNode *
C =
nullptr, *NewNode =
nullptr;
946 while (is_constant(
N) && !(
N->Flags & GepNode::Root)) {
948 GepNode *NewN =
new (*Mem) GepNode(
N);
949 Nodes.push_back(NewN);
954 NewN->Flags &= ~GepNode::Used;
966 UseSet &Us =
UF->second;
969 if (
U->getUser() == R)
976 Node->Flags &= ~GepNode::Used;
981 NewNode->Flags |= GepNode::Used;
982 LLVM_DEBUG(
dbgs() <<
"new node: " << NewNode <<
" " << *NewNode <<
'\n');
984 Uses[NewNode] = NewUs;
987void HexagonCommonGEP::separateConstantChains(GepNode *
Node,
988 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
997 for (GepNode *
N : Ns) {
998 if (!(
N->Flags & GepNode::Used))
1000 NodeToUsesMap::iterator
UF =
Uses.find(
N);
1002 UseSet &Us =
UF->second;
1010 if (
LoadInst *Ld = dyn_cast<LoadInst>(R)) {
1012 if (&Ld->getOperandUse(PtrX) == U)
1014 }
else if (
StoreInst *St = dyn_cast<StoreInst>(R)) {
1016 if (&St->getOperandUse(PtrX) == U)
1025 FNs.insert(std::make_pair(
N, LSs));
1030 for (
auto &FN : FNs) {
1031 GepNode *
N = FN.first;
1032 UseSet &Us = FN.second;
1034 separateChainForNode(
N, U, Loc);
1038void HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
1041 NodeChildrenMap NCM;
1047 for (GepNode *Root : Roots)
1048 recalculatePlacementRec(Root, NCM, Loc);
1050 LLVM_DEBUG(
dbgs() <<
"Initial node placement:\n" << LocationAsBlock(Loc));
1053 for (GepNode *Root : Roots)
1054 adjustForInvariance(Root, NCM, Loc);
1056 LLVM_DEBUG(
dbgs() <<
"Node placement after adjustment for invariance:\n"
1057 << LocationAsBlock(Loc));
1060 for (GepNode *Root : Roots)
1061 separateConstantChains(Root, NCM, Loc);
1069 LLVM_DEBUG(
dbgs() <<
"Final node placement:\n" << LocationAsBlock(Loc));
1077 unsigned Num = NA.size();
1078 GepNode *
RN = NA[0];
1079 assert((
RN->Flags & GepNode::Root) &&
"Creating GEP for non-root");
1091 if (!(NA[
Idx]->Flags & GepNode::Pointer)) {
1093 IdxList.
push_back(ConstantInt::get(Int32Ty, 0));
1098 while (++
Idx <= Num) {
1099 GepNode *
N = NA[
Idx-1];
1103 if (NA[
Idx]->Flags & GepNode::Pointer)
1112 InpTy = NA[
Idx]->PTy;
1114 }
while (
Idx <= Num);
1119void HexagonCommonGEP::getAllUsersForNode(GepNode *
Node, ValueVect &Values,
1120 NodeChildrenMap &NCM) {
1122 Work.push_back(
Node);
1124 while (!Work.empty()) {
1125 NodeVect::iterator
First = Work.begin();
1128 if (
N->Flags & GepNode::Used) {
1129 NodeToUsesMap::iterator
UF =
Uses.find(
N);
1130 assert(UF !=
Uses.end() &&
"No use information for used node");
1131 UseSet &Us =
UF->second;
1132 for (
const auto &U : Us)
1133 Values.push_back(
U->getUser());
1135 NodeChildrenMap::iterator CF = NCM.find(
N);
1136 if (CF != NCM.end()) {
1137 NodeVect &Cs = CF->second;
1143void HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
1144 LLVM_DEBUG(
dbgs() <<
"Nodes before materialization:\n" << Nodes <<
'\n');
1145 NodeChildrenMap NCM;
1151 while (!Roots.empty()) {
1152 NodeVect::iterator
First = Roots.begin();
1162 bool LastUsed =
false;
1163 unsigned LastCN = 0;
1172 LastUsed = (
Last->Flags & GepNode::Used);
1175 NodeChildrenMap::iterator CF = NCM.find(
Last);
1176 LastCN = (CF != NCM.end()) ? CF->second.size() : 0;
1179 GepNode *Child = CF->second.front();
1180 BasicBlock *ChildB = cast_or_null<BasicBlock>(Loc[Child]);
1181 if (ChildB !=
nullptr && LastB != ChildB)
1187 if (LastUsed || LastCN > 0) {
1189 getAllUsersForNode(Root, Urs, NCM);
1191 if (FirstUse != LastB->
end())
1192 InsertAt = FirstUse;
1196 Value *NewInst = fabricateGEP(NA, InsertAt, LastB);
1201 NodeVect &Cs = NCM[
Last];
1202 for (GepNode *CN : Cs) {
1203 CN->Flags &= ~GepNode::Internal;
1204 CN->Flags |= GepNode::Root;
1205 CN->BaseVal = NewInst;
1206 Roots.push_back(CN);
1213 NodeToUsesMap::iterator
UF =
Uses.find(
Last);
1214 assert(UF !=
Uses.end() &&
"No use information found");
1215 UseSet &Us =
UF->second;
1222void HexagonCommonGEP::removeDeadCode() {
1224 BO.push_back(&Fn->front());
1226 for (
unsigned i = 0; i < BO.size(); ++i) {
1228 for (
auto *DTN : children<DomTreeNode *>(DT->
getNode(
B)))
1229 BO.push_back(DTN->getBlock());
1240 In->eraseFromParent();
1245bool HexagonCommonGEP::runOnFunction(
Function &
F) {
1246 if (skipFunction(
F))
1252 if (isa<InvokeInst>(
I) || isa<LandingPadInst>(
I))
1256 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1257 PDT = &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
1258 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1259 Ctx = &
F.getContext();
1272 computeNodePlacement(Loc);
1276#ifdef EXPENSIVE_CHECKS
1287 return new HexagonCommonGEP();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the BumpPtrAllocator interface.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_ATTRIBUTE_UNUSED
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
DenseMap< Block *, BlockRelaxAux > Blocks
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.
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.
LLVM Basic Block Representation.
InstListType::iterator iterator
Instruction iterators...
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...
This is the shared class of boolean and integer constants.
This class represents an Operation in the Expression.
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.
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
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
This is an important class for using LLVM in a threaded context.
An instruction for reading from memory.
static unsigned getPointerOperandIndex()
LoopT * getParentLoop() const
Return the parent loop if it exists or nullptr for top level loops.
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
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
A vector that has set insertion semantics.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
A BumpPtrAllocator that allows only elements of a specific type to be allocated.
An instruction for storing to memory.
static unsigned getPointerOperandIndex()
StringRef - Represent a constant reference to a string, i.e.
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.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
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()
user_iterator_impl< User > user_iterator
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.
initializer< Ty > init(const Ty &Val)
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...
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.
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)
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
FunctionPass * createHexagonCommonGEP()
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
GepNode(const GepNode *N)