49#define DEBUG_TYPE "commgep"
70 using NodeSet = std::set<GepNode *>;
71 using NodeToValueMap = std::map<GepNode *, Value *>;
72 using NodeVect = std::vector<GepNode *>;
73 using NodeChildrenMap = std::map<GepNode *, NodeVect>;
75 using NodeToUsesMap = std::map<GepNode *, UseSet>;
80 NodeOrdering() =
default;
82 void insert(
const GepNode *
N) { Map.insert(std::make_pair(
N, ++LastNum)); }
83 void clear() {
Map.clear(); }
85 bool operator()(
const GepNode *N1,
const GepNode *N2)
const {
86 auto F1 =
Map.find(N1), F2 =
Map.find(N2);
88 return F1->second < F2->second;
92 std::map<const GepNode *, unsigned>
Map;
118 using ValueToNodeMap = std::map<Value *, GepNode *>;
119 using ValueVect = std::vector<Value *>;
120 using NodeToValuesMap = std::map<GepNode *, ValueVect>;
122 void getBlockTraversalOrder(
BasicBlock *Root, ValueVect &Order);
128 BasicBlock *recalculatePlacement(GepNode *
Node, NodeChildrenMap &NCM,
129 NodeToValueMap &Loc);
130 BasicBlock *recalculatePlacementRec(GepNode *
Node, NodeChildrenMap &NCM,
131 NodeToValueMap &Loc);
133 bool isInvariantIn(GepNode *
Node,
Loop *L);
135 BasicBlock *adjustForInvariance(GepNode *
Node, NodeChildrenMap &NCM,
136 NodeToValueMap &Loc);
137 void separateChainForNode(GepNode *
Node,
Use *U, NodeToValueMap &Loc);
138 void separateConstantChains(GepNode *
Node, NodeChildrenMap &NCM,
139 NodeToValueMap &Loc);
140 void computeNodePlacement(NodeToValueMap &Loc);
144 void getAllUsersForNode(GepNode *
Node, ValueVect &Values,
145 NodeChildrenMap &NCM);
146 void materialize(NodeToValueMap &Loc);
148 void removeDeadCode();
163char HexagonCommonGEP::ID = 0;
209 BaseVal =
N->BaseVal;
220 if (GN.
Flags & GepNode::Root) {
224 if (GN.
Flags & GepNode::Internal) {
230 if (GN.
Flags & GepNode::Used) {
235 if (GN.
Flags & GepNode::InBounds) {
240 if (GN.
Flags & GepNode::Pointer) {
246 if (GN.
Flags & GepNode::Root)
253 OS << CI->getValue().getSExtValue();
257 OS <<
"<anon> =" << *GN.
Idx;
265 OS <<
"<anon-struct>:" << *STy;
273 template <
typename NodeContainer>
275 using const_iterator =
typename NodeContainer::const_iterator;
277 for (const_iterator
I = S.begin(), E = S.end();
I != E; ++
I)
278 OS << *
I <<
' ' << **
I <<
'\n';
291 for (
const auto &
I : M) {
292 const UseSet &Us =
I.second;
293 OS <<
I.first <<
" -> #" << Us.size() <<
'{';
294 for (
const Use *U : Us) {
295 User *R = U->getUser();
297 OS <<
' ' << R->getName();
299 OS <<
" <?>(" << *R <<
')';
310 return NS.find(
N) != NS.end();
323void HexagonCommonGEP::getBlockTraversalOrder(
BasicBlock *Root,
329 Order.push_back(Root);
330 for (
auto *DTN : children<DomTreeNode*>(DT->
getNode(Root)))
331 getBlockTraversalOrder(DTN->getBlock(), Order);
345 ValueToNodeMap &NM) {
347 GepNode *
N =
new (*Mem) GepNode;
350 ValueToNodeMap::iterator
F = NM.find(PtrOp);
353 N->Flags |= GepNode::Root | InBounds;
358 N->Parent =
F->second;
361 N->Flags |= GepNode::Pointer;
371 if (isa<GetElementPtrInst>(*UI)) {
373 if (isHandledGepForm(UserG))
376 Us.insert(&UI.getUse());
387 GepNode *Nx =
new (*Mem) GepNode;
389 Nx->Flags |= GepNode::Internal | InBounds;
401 PN->Flags |= GepNode::Used;
402 Uses[PN].insert(Us.begin(), Us.end());
407 NM.insert(std::make_pair(GepI, PN));
410void HexagonCommonGEP::collect() {
413 getBlockTraversalOrder(&Fn->front(), BO);
422 if (
auto *GepI = dyn_cast<GetElementPtrInst>(&J))
423 if (isHandledGepForm(GepI))
424 processGepInst(GepI, NM);
427 LLVM_DEBUG(
dbgs() <<
"Gep nodes after initial collection:\n" << Nodes);
432 for (GepNode *
N : Nodes) {
433 if (
N->Flags & GepNode::Root) {
437 GepNode *PN =
N->Parent;
438 NCM[PN].push_back(
N);
445 Work.push_back(Root);
448 while (!Work.empty()) {
449 NodeVect::iterator
First = Work.begin();
452 NodeChildrenMap::iterator CF = NCM.find(
N);
453 if (CF != NCM.end()) {
455 Nodes.
insert(CF->second.begin(), CF->second.end());
462 using NodeSymRel = std::set<NodeSet>;
463 using NodePair = std::pair<GepNode *, GepNode *>;
464 using NodePairSet = std::set<NodePair>;
479 uintptr_t P1 =
reinterpret_cast<uintptr_t
>(N1);
480 uintptr_t P2 =
reinterpret_cast<uintptr_t
>(N2);
482 return std::make_pair(N1, N2);
483 return std::make_pair(N2, N1);
489 ID.AddPointer(
N->Idx);
490 ID.AddPointer(
N->PTy);
491 return ID.ComputeHash();
494static bool node_eq(GepNode *N1, GepNode *N2, NodePairSet &Eq,
502 NodePairSet::iterator FEq = Eq.find(NP);
505 NodePairSet::iterator FNe = Ne.find(NP);
509 bool Root1 = N1->Flags & GepNode::Root;
510 uint32_t CmpFlags = GepNode::Root | GepNode::Pointer;
511 bool Different = (N1->Flags & CmpFlags) != (N2->Flags & CmpFlags);
517 if (Different || (Root1 && N1->BaseVal != N2->BaseVal)) {
524 if (Root1 ||
node_eq(N1->Parent, N2->Parent, Eq, Ne)) {
531void HexagonCommonGEP::common() {
536 using NodeSetMap = std::map<unsigned, NodeSet>;
539 for (GepNode *
N : Nodes) {
541 MaybeEq[
H].insert(
N);
548 for (
auto &
I : MaybeEq) {
567 std::pair<NodeSymRel::iterator, bool>
Ins = EqRel.insert(
C);
569 assert(
Ins.second &&
"Cannot add a class");
575 dbgs() <<
"Gep node equality:\n";
576 for (NodePairSet::iterator
I = Eq.begin(), E = Eq.end();
I != E; ++
I)
577 dbgs() <<
"{ " <<
I->first <<
", " <<
I->second <<
" }\n";
579 dbgs() <<
"Gep equivalence classes:\n";
580 for (
const NodeSet &S : EqRel) {
582 for (NodeSet::const_iterator J = S.
begin(),
F = S.
end(); J !=
F; ++J) {
592 using ProjMap = std::map<const NodeSet *, GepNode *>;
594 for (
const NodeSet &S : EqRel) {
596 std::pair<ProjMap::iterator,bool>
Ins = PM.insert(std::make_pair(&S, Min));
598 assert(
Ins.second &&
"Cannot add minimal element");
602 UseSet &MinUs =
Uses[Min];
603 for (GepNode *
N : S) {
607 if (NF & GepNode::Used)
615 assert((Min->Flags & Flags) == Min->Flags);
623 for (GepNode *
N : Nodes) {
624 if (
N->Flags & GepNode::Root)
629 ProjMap::iterator
F = PM.find(PC);
633 GepNode *Rep =
F->second;
641 for (GepNode *
N : Nodes) {
645 ProjMap::iterator
F = PM.find(PC);
655 LLVM_DEBUG(
dbgs() <<
"Gep nodes after post-commoning cleanup:\n" << Nodes);
661 dbgs() <<
"NCD of {";
662 for (
typename T::iterator
I =
Blocks.begin(), E =
Blocks.end();
I != E;
667 dbgs() <<
' ' <<
B->getName();
693 while (
I != E && !*
I)
717 using iterator =
typename T::iterator;
719 for (iterator
I = Values.begin(), E = Values.end();
I != E; ++
I) {
728 if (!isa<Instruction>(V))
731 if (In->getParent() !=
B)
734 if (std::distance(FirstUse, BEnd) < std::distance(It, BEnd))
741 return B->empty() || (&*
B->begin() ==
B->getTerminator());
745 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
757 if (
Node->Flags & GepNode::Used) {
760 NodeToUsesMap::iterator UF =
Uses.find(
Node);
761 assert(UF !=
Uses.end() &&
"Used node with no use information");
762 UseSet &Us = UF->second;
765 if (!isa<Instruction>(R))
768 ? cast<PHINode>(R)->getIncomingBlock(*U)
769 : cast<Instruction>(R)->getParent();
774 NodeChildrenMap::iterator CF = NCM.find(
Node);
775 if (CF != NCM.end()) {
776 NodeVect &Cs = CF->second;
777 for (GepNode *CN : Cs) {
778 NodeToValueMap::iterator LF = Loc.find(CN);
784 Bs.push_back(LF->second);
801 DomB =
N->getBlock();
809BasicBlock *HexagonCommonGEP::recalculatePlacementRec(GepNode *
Node,
810 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
814 NodeChildrenMap::iterator CF = NCM.find(
Node);
815 if (CF != NCM.end()) {
816 NodeVect &Cs = CF->second;
817 for (GepNode *
C : Cs)
818 recalculatePlacementRec(
C, NCM, Loc);
825bool HexagonCommonGEP::isInvariantIn(
Value *Val,
Loop *L) {
826 if (isa<Constant>(Val) || isa<Argument>(Val))
835bool HexagonCommonGEP::isInvariantIn(GepNode *
Node,
Loop *L) {
836 if (
Node->Flags & GepNode::Root)
837 if (!isInvariantIn(
Node->BaseVal, L))
839 return isInvariantIn(
Node->Idx, L);
846 if (PDT->dominates(
B, HB))
865 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
870 if (
Node->Flags & GepNode::Root) {
872 Bs.push_back(PIn->getParent());
874 Bs.push_back(Loc[
Node->Parent]);
877 Bs.push_back(IIn->getParent());
890 Loop *Lp = LI->getLoopFor(LocB);
892 if (!isInvariantIn(
Node, Lp) || !isInMainPath(LocB, Lp))
895 if (!NewLoc || !DT->
dominates(TopB, NewLoc))
904 NodeChildrenMap::iterator CF = NCM.find(
Node);
905 if (CF != NCM.end()) {
906 NodeVect &Cs = CF->second;
907 for (GepNode *
C : Cs)
908 adjustForInvariance(
C, NCM, Loc);
915 struct LocationAsBlock {
916 LocationAsBlock(
const NodeToValueMap &L) :
Map(
L) {}
918 const NodeToValueMap &
Map;
924 for (
const auto &
I : Loc.Map) {
925 OS <<
I.first <<
" -> ";
927 OS <<
B->getName() <<
'(' <<
B <<
')';
929 OS <<
"<null-block>";
935 inline bool is_constant(GepNode *
N) {
936 return isa<ConstantInt>(
N->Idx);
941void HexagonCommonGEP::separateChainForNode(GepNode *
Node,
Use *U,
942 NodeToValueMap &Loc) {
949 GepNode *
C =
nullptr, *NewNode =
nullptr;
950 while (is_constant(
N) && !(
N->Flags & GepNode::Root)) {
952 GepNode *NewN =
new (*Mem) GepNode(
N);
953 Nodes.push_back(NewN);
958 NewN->Flags &= ~GepNode::Used;
968 NodeToUsesMap::iterator UF =
Uses.find(
Node);
970 UseSet &Us = UF->second;
973 if (
U->getUser() == R)
980 Node->Flags &= ~GepNode::Used;
985 NewNode->Flags |= GepNode::Used;
986 LLVM_DEBUG(
dbgs() <<
"new node: " << NewNode <<
" " << *NewNode <<
'\n');
988 Uses[NewNode] = NewUs;
991void HexagonCommonGEP::separateConstantChains(GepNode *
Node,
992 NodeChildrenMap &NCM, NodeToValueMap &Loc) {
1001 for (GepNode *
N : Ns) {
1002 if (!(
N->Flags & GepNode::Used))
1004 NodeToUsesMap::iterator UF =
Uses.find(
N);
1006 UseSet &Us = UF->second;
1014 if (
LoadInst *Ld = dyn_cast<LoadInst>(R)) {
1016 if (&Ld->getOperandUse(PtrX) == U)
1018 }
else if (
StoreInst *St = dyn_cast<StoreInst>(R)) {
1020 if (&St->getOperandUse(PtrX) == U)
1029 FNs.insert(std::make_pair(
N, LSs));
1034 for (
auto &FN : FNs) {
1035 GepNode *
N = FN.first;
1036 UseSet &Us = FN.second;
1038 separateChainForNode(
N, U, Loc);
1042void HexagonCommonGEP::computeNodePlacement(NodeToValueMap &Loc) {
1045 NodeChildrenMap NCM;
1051 for (GepNode *Root : Roots)
1052 recalculatePlacementRec(Root, NCM, Loc);
1054 LLVM_DEBUG(
dbgs() <<
"Initial node placement:\n" << LocationAsBlock(Loc));
1057 for (GepNode *Root : Roots)
1058 adjustForInvariance(Root, NCM, Loc);
1060 LLVM_DEBUG(
dbgs() <<
"Node placement after adjustment for invariance:\n"
1061 << LocationAsBlock(Loc));
1064 for (GepNode *Root : Roots)
1065 separateConstantChains(Root, NCM, Loc);
1073 LLVM_DEBUG(
dbgs() <<
"Final node placement:\n" << LocationAsBlock(Loc));
1081 unsigned Num = NA.size();
1082 GepNode *
RN = NA[0];
1083 assert((
RN->Flags & GepNode::Root) &&
"Creating GEP for non-root");
1095 if (!(NA[
Idx]->Flags & GepNode::Pointer)) {
1097 IdxList.
push_back(ConstantInt::get(Int32Ty, 0));
1102 while (++
Idx <= Num) {
1103 GepNode *
N = NA[
Idx-1];
1107 if (NA[
Idx]->Flags & GepNode::Pointer)
1116 InpTy = NA[
Idx]->PTy;
1118 }
while (
Idx <= Num);
1123void HexagonCommonGEP::getAllUsersForNode(GepNode *
Node, ValueVect &Values,
1124 NodeChildrenMap &NCM) {
1126 Work.push_back(
Node);
1128 while (!Work.empty()) {
1129 NodeVect::iterator
First = Work.begin();
1132 if (
N->Flags & GepNode::Used) {
1133 NodeToUsesMap::iterator UF =
Uses.find(
N);
1134 assert(UF !=
Uses.end() &&
"No use information for used node");
1135 UseSet &Us = UF->second;
1136 for (
const auto &U : Us)
1137 Values.push_back(
U->getUser());
1139 NodeChildrenMap::iterator CF = NCM.find(
N);
1140 if (CF != NCM.end()) {
1141 NodeVect &Cs = CF->second;
1147void HexagonCommonGEP::materialize(NodeToValueMap &Loc) {
1148 LLVM_DEBUG(
dbgs() <<
"Nodes before materialization:\n" << Nodes <<
'\n');
1149 NodeChildrenMap NCM;
1155 while (!Roots.empty()) {
1156 NodeVect::iterator
First = Roots.begin();
1166 bool LastUsed =
false;
1167 unsigned LastCN = 0;
1176 LastUsed = (
Last->Flags & GepNode::Used);
1179 NodeChildrenMap::iterator CF = NCM.find(
Last);
1180 LastCN = (CF != NCM.end()) ? CF->second.size() : 0;
1183 GepNode *Child = CF->second.front();
1184 BasicBlock *ChildB = cast_or_null<BasicBlock>(Loc[Child]);
1185 if (ChildB !=
nullptr && LastB != ChildB)
1191 if (LastUsed || LastCN > 0) {
1193 getAllUsersForNode(Root, Urs, NCM);
1195 if (FirstUse != LastB->
end())
1196 InsertAt = FirstUse;
1200 Value *NewInst = fabricateGEP(NA, InsertAt, LastB);
1205 NodeVect &Cs = NCM[
Last];
1206 for (GepNode *CN : Cs) {
1207 CN->Flags &= ~GepNode::Internal;
1208 CN->Flags |= GepNode::Root;
1209 CN->BaseVal = NewInst;
1210 Roots.push_back(CN);
1217 NodeToUsesMap::iterator UF =
Uses.find(
Last);
1218 assert(UF !=
Uses.end() &&
"No use information found");
1219 UseSet &Us = UF->second;
1226void HexagonCommonGEP::removeDeadCode() {
1228 BO.push_back(&Fn->front());
1230 for (
unsigned i = 0; i < BO.size(); ++i) {
1232 for (
auto *DTN : children<DomTreeNode *>(DT->
getNode(
B)))
1233 BO.push_back(DTN->getBlock());
1244 In->eraseFromParent();
1249bool HexagonCommonGEP::runOnFunction(
Function &
F) {
1250 if (skipFunction(
F))
1256 if (isa<InvokeInst>(
I) || isa<LandingPadInst>(
I))
1260 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
1261 PDT = &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree();
1262 LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
1263 Ctx = &
F.getContext();
1276 computeNodePlacement(Loc);
1280#ifdef EXPENSIVE_CHECKS
1291 return new HexagonCommonGEP();
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
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...
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
bool isInBounds() const
Determine whether the GEP has the inbounds flag.
static 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)
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
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
StringRef getStructName() const
bool isStructTy() const
True if this is an instance of StructType.
static IntegerType * getInt32Ty(LLVMContext &C)
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
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)
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
initializer< Ty > init(const Ty &Val)
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.
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...
bool verifyFunction(const Function &F, raw_ostream *OS=nullptr)
Check a function for errors, useful for use when debugging a pass.
void initializeHexagonCommonGEPPass(PassRegistry &)
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
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)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ 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)