-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[SelectionDAG] Move SDNode::use_iterator::getOperandNo to SDUse. #120536
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-m68k @llvm/pr-subscribers-backend-risc-v Author: Craig Topper (topperc) ChangesThis allows to write more range based for loops because we no SDNode is declared after SDUse so I had to put the definition Stacked on #120531 Patch is 53.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120536.diff 18 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 77c04369f3e92d..63eb40718a10c7 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -310,6 +310,9 @@ class SDUse {
/// Get the next SDUse in the use list.
SDUse *getNext() const { return Next; }
+ /// Return the operand # of this use in its user.
+ inline unsigned getOperandNo() const;
+
/// Convenience function for get().getNode().
SDNode *getNode() const { return Val.getNode(); }
/// Convenience function for get().getResNo().
@@ -750,7 +753,7 @@ END_TWO_BYTE_PACK()
bool use_empty() const { return UseList == nullptr; }
/// Return true if there is exactly one use of this node.
- bool hasOneUse() const { return hasSingleElement(users()); }
+ bool hasOneUse() const { return hasSingleElement(uses()); }
/// Return the number of uses of this node. This method takes
/// time proportional to the number of uses.
@@ -821,20 +824,52 @@ END_TWO_BYTE_PACK()
}
/// Retrieve a pointer to the current user node.
- SDNode *operator*() const {
+ SDUse &operator*() const {
assert(Op && "Cannot dereference end iterator!");
- return Op->getUser();
+ return *Op;
}
- SDNode *operator->() const { return operator*(); }
+ SDUse *operator->() const { return &operator*(); }
+ };
+
+ class user_iterator {
+ friend class SDNode;
+ use_iterator UI;
- SDUse &getUse() const { return *Op; }
+ explicit user_iterator(SDUse *op) : UI(op) {};
- /// Retrieve the operand # of this use in its user.
- unsigned getOperandNo() const {
- assert(Op && "Cannot dereference end iterator!");
- return (unsigned)(Op - Op->getUser()->OperandList);
+ public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = SDNode *;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type *;
+ using reference = value_type &;
+
+ user_iterator() = default;
+
+ bool operator==(const user_iterator &x) const { return UI == x.UI; }
+ bool operator!=(const user_iterator &x) const { return !operator==(x); }
+
+ // /// Return true if this iterator is at the end of the uses list.
+ bool atEnd() const { return *this == user_iterator(); }
+
+ user_iterator &operator++() { // Preincrement
+ ++UI;
+ return *this;
+ }
+
+ user_iterator operator++(int) { // Postincrement
+ auto tmp = *this;
+ ++*this;
+ return tmp;
}
+
+ // Retrieve a pointer to the current User.
+ SDNode *operator*() const { return UI->getUser(); }
+
+ SDNode *operator->() const { return operator*(); }
+
+ SDUse &getUse() const { return *UI; }
};
/// Provide iteration support to walk over all uses of an SDNode.
@@ -844,22 +879,25 @@ END_TWO_BYTE_PACK()
static use_iterator use_end() { return use_iterator(nullptr); }
- /// Provide iteration support to walk over all users of an SDNode.
- /// For now, this should only be used to get a pointer to the first user.
- /// FIXME: Rename use_iterator to user_iterator. Add user_end().
- use_iterator user_begin() const { return use_iterator(UseList); }
-
- // Dereferencing use_iterator returns the user SDNode* making it closer to a
- // user_iterator thus this function is called users() to reflect that.
- // FIXME: Rename to user_iterator and introduce a use_iterator that returns
- // SDUse*.
- inline iterator_range<use_iterator> users() {
+ inline iterator_range<use_iterator> uses() {
return make_range(use_begin(), use_end());
}
- inline iterator_range<use_iterator> users() const {
+ inline iterator_range<use_iterator> uses() const {
return make_range(use_begin(), use_end());
}
+ /// Provide iteration support to walk over all users of an SDNode.
+ user_iterator user_begin() const { return user_iterator(UseList); }
+
+ static user_iterator user_end() { return user_iterator(nullptr); }
+
+ inline iterator_range<user_iterator> users() {
+ return make_range(user_begin(), user_end());
+ }
+ inline iterator_range<user_iterator> users() const {
+ return make_range(user_begin(), user_end());
+ }
+
/// Return true if there are exactly NUSES uses of the indicated value.
/// This method ignores uses of other values defined by this operation.
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const;
@@ -1019,9 +1057,9 @@ END_TWO_BYTE_PACK()
/// If this node has a glue value with a user, return
/// the user (there is at most one). Otherwise return NULL.
SDNode *getGluedUser() const {
- for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI)
- if (UI.getUse().get().getValueType() == MVT::Glue)
- return *UI;
+ for (SDUse &U : uses())
+ if (U.getValueType() == MVT::Glue)
+ return U.getUser();
return nullptr;
}
@@ -1268,6 +1306,9 @@ inline void SDValue::dumpr(const SelectionDAG *G) const {
}
// Define inline functions from the SDUse class.
+inline unsigned SDUse::getOperandNo() const {
+ return this - getUser()->op_begin();
+}
inline void SDUse::set(const SDValue &V) {
if (Val.getNode()) removeFromList();
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 85009439c37b3a..6cbfef2d238bbe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13229,12 +13229,11 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
const TargetLowering &TLI) {
bool HasCopyToRegUses = false;
bool isTruncFree = TLI.isTruncateFree(VT, N0.getValueType());
- for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end(); UI != UE;
- ++UI) {
- SDNode *User = *UI;
+ for (SDUse &Use : N0->uses()) {
+ SDNode *User = Use.getUser();
if (User == N)
continue;
- if (UI.getUse().getResNo() != N0.getResNo())
+ if (Use.getResNo() != N0.getResNo())
continue;
// FIXME: Only extend SETCC N, N and SETCC N, c for now.
if (ExtOpc != ISD::ANY_EXTEND && User->getOpcode() == ISD::SETCC) {
@@ -13266,9 +13265,7 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
if (HasCopyToRegUses) {
bool BothLiveOut = false;
- for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
- UI != UE; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : N->uses()) {
if (Use.getResNo() == 0 && Use.getUser()->getOpcode() == ISD::CopyToReg) {
BothLiveOut = true;
break;
@@ -13780,11 +13777,10 @@ SDValue DAGCombiner::foldSextSetcc(SDNode *N) {
// Non-chain users of this value must either be the setcc in this
// sequence or extends that can be folded into the new {z/s}ext-load.
- for (SDNode::use_iterator UI = V->use_begin(), UE = V->use_end();
- UI != UE; ++UI) {
+ for (SDUse &Use : V->uses()) {
// Skip uses of the chain and the setcc.
- SDNode *User = *UI;
- if (UI.getUse().getResNo() != 0 || User == N0.getNode())
+ SDNode *User = Use.getUser();
+ if (Use.getResNo() != 0 || User == N0.getNode())
continue;
// Extra users must have exactly the same cast we are about to create.
// TODO: This restriction could be eased if ExtendUsesToFormExtLoad()
@@ -18925,10 +18921,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
SmallVector<SDNode *, 16> OtherUses;
unsigned MaxSteps = SelectionDAG::getHasPredecessorMaxSteps();
if (isa<ConstantSDNode>(Offset))
- for (SDNode::use_iterator UI = BasePtr->use_begin(),
- UE = BasePtr->use_end();
- UI != UE; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : BasePtr->uses()) {
// Skip the use that is Ptr and uses of other results from BasePtr's
// node (important for nodes that return multiple results).
if (Use.getUser() == Ptr.getNode() || Use != BasePtr)
@@ -18944,7 +18937,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
break;
}
- SDValue Op1 = Use.getUser()->getOperand((UI.getOperandNo() + 1) & 1);
+ SDValue Op1 = Use.getUser()->getOperand((Use.getOperandNo() + 1) & 1);
if (!isa<ConstantSDNode>(Op1)) {
OtherUses.clear();
break;
@@ -20056,13 +20049,12 @@ bool DAGCombiner::SliceUpLoad(SDNode *N) {
// Check if this load is used as several smaller chunks of bits.
// Basically, look for uses in trunc or trunc(lshr) and record a new chain
// of computation for each trunc.
- for (SDNode::use_iterator UI = LD->use_begin(), UIEnd = LD->use_end();
- UI != UIEnd; ++UI) {
+ for (SDUse &U : LD->uses()) {
// Skip the uses of the chain.
- if (UI.getUse().getResNo() != 0)
+ if (U.getResNo() != 0)
continue;
- SDNode *User = *UI;
+ SDNode *User = U.getUser();
unsigned Shift = 0;
// Check if this is a trunc(lshr).
@@ -20936,11 +20928,11 @@ DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
RootCount->second.second > StoreMergeDependenceLimit;
};
- auto TryToAddCandidate = [&](SDNode::use_iterator UseIter) {
+ auto TryToAddCandidate = [&](SDUse &Use) {
// This must be a chain use.
- if (UseIter.getOperandNo() != 0)
+ if (Use.getOperandNo() != 0)
return;
- if (auto *OtherStore = dyn_cast<StoreSDNode>(*UseIter)) {
+ if (auto *OtherStore = dyn_cast<StoreSDNode>(Use.getUser())) {
BaseIndexOffset Ptr;
int64_t PtrDiff;
if (CandidateMatch(OtherStore, Ptr, PtrDiff) &&
@@ -20958,19 +20950,20 @@ DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
return nullptr;
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored) {
- if (I.getOperandNo() == 0 && isa<LoadSDNode>(*I)) { // walk down chain
- for (auto I2 = (*I)->use_begin(), E2 = (*I)->use_end(); I2 != E2; ++I2)
- TryToAddCandidate(I2);
+ SDNode *User = I->getUser();
+ if (I->getOperandNo() == 0 && isa<LoadSDNode>(User)) { // walk down chain
+ for (SDUse &U2 : User->uses())
+ TryToAddCandidate(U2);
}
// Check stores that depend on the root (e.g. Store 3 in the chart above).
- if (I.getOperandNo() == 0 && isa<StoreSDNode>(*I)) {
- TryToAddCandidate(I);
+ if (I->getOperandNo() == 0 && isa<StoreSDNode>(User)) {
+ TryToAddCandidate(*I);
}
}
} else {
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored)
- TryToAddCandidate(I);
+ TryToAddCandidate(*I);
}
return RootNode;
@@ -27320,8 +27313,7 @@ SDValue DAGCombiner::visitGET_FPENV_MEM(SDNode *N) {
// Check if the loaded value is used only in a store operation.
StoreSDNode *StNode = nullptr;
- for (auto I = LdNode->use_begin(), E = LdNode->use_end(); I != E; ++I) {
- SDUse &U = I.getUse();
+ for (SDUse &U : LdNode->uses()) {
if (U.getResNo() == 0) {
if (auto *St = dyn_cast<StoreSDNode>(U.getUser())) {
if (StNode)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
index c7d29ec1a836c1..b6abad830c371e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
@@ -88,10 +88,9 @@ void DAGTypeLegalizer::PerformExpensiveChecks() {
if (I != ReplacedValues.end()) {
Mapped |= 1;
// Check that remapped values are only used by nodes marked NewNode.
- for (SDNode::use_iterator UI = Node.use_begin(), UE = Node.use_end();
- UI != UE; ++UI)
- if (UI.getUse().getResNo() == i)
- assert(UI->getNodeId() == NewNode &&
+ for (SDUse &U : Node.uses())
+ if (U.getResNo() == i)
+ assert(U.getUser()->getNodeId() == NewNode &&
"Remapped value has non-trivial use!");
// Check that the final result of applying ReplacedValues is not
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 2e59dbf2f70280..26fc75c0578ec2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -236,7 +236,7 @@ void ScheduleDAGSDNodes::ClusterNeighboringLoads(SDNode *Node) {
// This algorithm requires a reasonably low use count before finding a match
// to avoid uselessly blowing up compile time in large blocks.
unsigned UseCount = 0;
- for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end();
+ for (SDNode::user_iterator I = Chain->user_begin(), E = Chain->user_end();
I != E && UseCount < 100; ++I, ++UseCount) {
if (I.getUse().getResNo() != Chain.getResNo())
continue;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index bd9e5d4dce8ec6..07749ec87d0b20 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -11611,7 +11611,7 @@ class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener {
void NodeDeleted(SDNode *N, SDNode *E) override {
// Increment the iterator as needed.
- while (UI != UE && N == *UI)
+ while (UI != UE && N == UI->getUser())
++UI;
}
@@ -11650,7 +11650,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11660,12 +11660,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
++UI;
Use.set(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
AddModifiedNodeToCSEMaps(User);
@@ -11708,7 +11708,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11718,12 +11718,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
++UI;
Use.setNode(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
@@ -11756,7 +11756,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, const SDValue *To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11767,12 +11767,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, const SDValue *To) {
// user that we can find this way.
bool To_IsDivergent = false;
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
const SDValue &ToOp = To[Use.getResNo()];
++UI;
Use.set(ToOp);
To_IsDivergent |= ToOp->isDivergent();
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
if (To_IsDivergent != From->isDivergent())
updateDivergence(User);
@@ -11810,7 +11810,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
UE = From.getNode()->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
bool UserRemovedFromCSEMaps = false;
// A user can appear in a use list multiple times, and when this
@@ -11818,7 +11818,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
// Skip uses of different values from the same node.
if (Use.getResNo() != From.getResNo()) {
@@ -11837,7 +11837,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
Use.set(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// We are iterating over all uses of the From node, so if a use
// doesn't use the specific value, no changes are made.
if (!UserRemovedFromCSEMaps)
@@ -11982,11 +11982,9 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
for (unsigned i = 0; i != Num; ++i) {
unsigned FromResNo = From[i].getResNo();
SDNode *FromNode = From[i].getNode();
- for (SDNode::use_iterator UI = FromNode->use_begin(),
- E = FromNode->use_end(); UI != E; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : FromNode->uses()) {
if (Use.getResNo() == FromResNo) {
- UseMemo Memo = { *UI, i, &Use };
+ UseMemo Memo = {Use.getUser(), i, &Use};
Uses.push_back(Memo);
}
}
@@ -12462,8 +12460,8 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
assert(Value < getNumValues() && "Bad value!");
// TODO: Only iterate over uses of a given value of the node
- for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) {
- if (UI.getUse().getResNo() == Value) {
+ for (SDUse &U : uses()) {
+ if (U.getResNo() == Value) {
if (NUses == 0)
return false;
--NUses;
@@ -12479,8 +12477,8 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
bool SDNode::hasAnyUseOfValue(unsigned Value) const {
assert(Value < getNumValues() && "Bad value!");
- for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI)
- if (UI.getUse().getResNo() == Value)
+ for (SDUse &U : uses())
+ if (U.getResNo() == Value)
return true;
return false;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index c4d0552ad55d39..c1dabe05452fb9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3792,8 +3792,8 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
for (unsigned i = 1, e = NodeStack.size()-1; i != e; ++i) {
unsigned NNonChainUses = 0;
SDNode *NS = NodeStack[i].getNode();
- for (auto UI = NS->use_begin(), UE = NS->use_end(); UI != UE; ++UI)
- if (UI.getUse().getValueType() != MVT::Other)
+ for (const SDUse &U : NS->uses())
+ if (U.getValueType() != MVT::Other)
if (++NNonChainUses > 1) {
HasMultipleUses = true;
break;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 494506def33a35..257cb716bae430 100644
--- a/l...
[truncated]
|
@llvm/pr-subscribers-backend-arm Author: Craig Topper (topperc) ChangesThis allows to write more range based for loops because we no SDNode is declared after SDUse so I had to put the definition Stacked on #120531 Patch is 53.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120536.diff 18 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 77c04369f3e92d..63eb40718a10c7 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -310,6 +310,9 @@ class SDUse {
/// Get the next SDUse in the use list.
SDUse *getNext() const { return Next; }
+ /// Return the operand # of this use in its user.
+ inline unsigned getOperandNo() const;
+
/// Convenience function for get().getNode().
SDNode *getNode() const { return Val.getNode(); }
/// Convenience function for get().getResNo().
@@ -750,7 +753,7 @@ END_TWO_BYTE_PACK()
bool use_empty() const { return UseList == nullptr; }
/// Return true if there is exactly one use of this node.
- bool hasOneUse() const { return hasSingleElement(users()); }
+ bool hasOneUse() const { return hasSingleElement(uses()); }
/// Return the number of uses of this node. This method takes
/// time proportional to the number of uses.
@@ -821,20 +824,52 @@ END_TWO_BYTE_PACK()
}
/// Retrieve a pointer to the current user node.
- SDNode *operator*() const {
+ SDUse &operator*() const {
assert(Op && "Cannot dereference end iterator!");
- return Op->getUser();
+ return *Op;
}
- SDNode *operator->() const { return operator*(); }
+ SDUse *operator->() const { return &operator*(); }
+ };
+
+ class user_iterator {
+ friend class SDNode;
+ use_iterator UI;
- SDUse &getUse() const { return *Op; }
+ explicit user_iterator(SDUse *op) : UI(op) {};
- /// Retrieve the operand # of this use in its user.
- unsigned getOperandNo() const {
- assert(Op && "Cannot dereference end iterator!");
- return (unsigned)(Op - Op->getUser()->OperandList);
+ public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = SDNode *;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type *;
+ using reference = value_type &;
+
+ user_iterator() = default;
+
+ bool operator==(const user_iterator &x) const { return UI == x.UI; }
+ bool operator!=(const user_iterator &x) const { return !operator==(x); }
+
+ // /// Return true if this iterator is at the end of the uses list.
+ bool atEnd() const { return *this == user_iterator(); }
+
+ user_iterator &operator++() { // Preincrement
+ ++UI;
+ return *this;
+ }
+
+ user_iterator operator++(int) { // Postincrement
+ auto tmp = *this;
+ ++*this;
+ return tmp;
}
+
+ // Retrieve a pointer to the current User.
+ SDNode *operator*() const { return UI->getUser(); }
+
+ SDNode *operator->() const { return operator*(); }
+
+ SDUse &getUse() const { return *UI; }
};
/// Provide iteration support to walk over all uses of an SDNode.
@@ -844,22 +879,25 @@ END_TWO_BYTE_PACK()
static use_iterator use_end() { return use_iterator(nullptr); }
- /// Provide iteration support to walk over all users of an SDNode.
- /// For now, this should only be used to get a pointer to the first user.
- /// FIXME: Rename use_iterator to user_iterator. Add user_end().
- use_iterator user_begin() const { return use_iterator(UseList); }
-
- // Dereferencing use_iterator returns the user SDNode* making it closer to a
- // user_iterator thus this function is called users() to reflect that.
- // FIXME: Rename to user_iterator and introduce a use_iterator that returns
- // SDUse*.
- inline iterator_range<use_iterator> users() {
+ inline iterator_range<use_iterator> uses() {
return make_range(use_begin(), use_end());
}
- inline iterator_range<use_iterator> users() const {
+ inline iterator_range<use_iterator> uses() const {
return make_range(use_begin(), use_end());
}
+ /// Provide iteration support to walk over all users of an SDNode.
+ user_iterator user_begin() const { return user_iterator(UseList); }
+
+ static user_iterator user_end() { return user_iterator(nullptr); }
+
+ inline iterator_range<user_iterator> users() {
+ return make_range(user_begin(), user_end());
+ }
+ inline iterator_range<user_iterator> users() const {
+ return make_range(user_begin(), user_end());
+ }
+
/// Return true if there are exactly NUSES uses of the indicated value.
/// This method ignores uses of other values defined by this operation.
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const;
@@ -1019,9 +1057,9 @@ END_TWO_BYTE_PACK()
/// If this node has a glue value with a user, return
/// the user (there is at most one). Otherwise return NULL.
SDNode *getGluedUser() const {
- for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI)
- if (UI.getUse().get().getValueType() == MVT::Glue)
- return *UI;
+ for (SDUse &U : uses())
+ if (U.getValueType() == MVT::Glue)
+ return U.getUser();
return nullptr;
}
@@ -1268,6 +1306,9 @@ inline void SDValue::dumpr(const SelectionDAG *G) const {
}
// Define inline functions from the SDUse class.
+inline unsigned SDUse::getOperandNo() const {
+ return this - getUser()->op_begin();
+}
inline void SDUse::set(const SDValue &V) {
if (Val.getNode()) removeFromList();
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 85009439c37b3a..6cbfef2d238bbe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13229,12 +13229,11 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
const TargetLowering &TLI) {
bool HasCopyToRegUses = false;
bool isTruncFree = TLI.isTruncateFree(VT, N0.getValueType());
- for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end(); UI != UE;
- ++UI) {
- SDNode *User = *UI;
+ for (SDUse &Use : N0->uses()) {
+ SDNode *User = Use.getUser();
if (User == N)
continue;
- if (UI.getUse().getResNo() != N0.getResNo())
+ if (Use.getResNo() != N0.getResNo())
continue;
// FIXME: Only extend SETCC N, N and SETCC N, c for now.
if (ExtOpc != ISD::ANY_EXTEND && User->getOpcode() == ISD::SETCC) {
@@ -13266,9 +13265,7 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
if (HasCopyToRegUses) {
bool BothLiveOut = false;
- for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
- UI != UE; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : N->uses()) {
if (Use.getResNo() == 0 && Use.getUser()->getOpcode() == ISD::CopyToReg) {
BothLiveOut = true;
break;
@@ -13780,11 +13777,10 @@ SDValue DAGCombiner::foldSextSetcc(SDNode *N) {
// Non-chain users of this value must either be the setcc in this
// sequence or extends that can be folded into the new {z/s}ext-load.
- for (SDNode::use_iterator UI = V->use_begin(), UE = V->use_end();
- UI != UE; ++UI) {
+ for (SDUse &Use : V->uses()) {
// Skip uses of the chain and the setcc.
- SDNode *User = *UI;
- if (UI.getUse().getResNo() != 0 || User == N0.getNode())
+ SDNode *User = Use.getUser();
+ if (Use.getResNo() != 0 || User == N0.getNode())
continue;
// Extra users must have exactly the same cast we are about to create.
// TODO: This restriction could be eased if ExtendUsesToFormExtLoad()
@@ -18925,10 +18921,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
SmallVector<SDNode *, 16> OtherUses;
unsigned MaxSteps = SelectionDAG::getHasPredecessorMaxSteps();
if (isa<ConstantSDNode>(Offset))
- for (SDNode::use_iterator UI = BasePtr->use_begin(),
- UE = BasePtr->use_end();
- UI != UE; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : BasePtr->uses()) {
// Skip the use that is Ptr and uses of other results from BasePtr's
// node (important for nodes that return multiple results).
if (Use.getUser() == Ptr.getNode() || Use != BasePtr)
@@ -18944,7 +18937,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
break;
}
- SDValue Op1 = Use.getUser()->getOperand((UI.getOperandNo() + 1) & 1);
+ SDValue Op1 = Use.getUser()->getOperand((Use.getOperandNo() + 1) & 1);
if (!isa<ConstantSDNode>(Op1)) {
OtherUses.clear();
break;
@@ -20056,13 +20049,12 @@ bool DAGCombiner::SliceUpLoad(SDNode *N) {
// Check if this load is used as several smaller chunks of bits.
// Basically, look for uses in trunc or trunc(lshr) and record a new chain
// of computation for each trunc.
- for (SDNode::use_iterator UI = LD->use_begin(), UIEnd = LD->use_end();
- UI != UIEnd; ++UI) {
+ for (SDUse &U : LD->uses()) {
// Skip the uses of the chain.
- if (UI.getUse().getResNo() != 0)
+ if (U.getResNo() != 0)
continue;
- SDNode *User = *UI;
+ SDNode *User = U.getUser();
unsigned Shift = 0;
// Check if this is a trunc(lshr).
@@ -20936,11 +20928,11 @@ DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
RootCount->second.second > StoreMergeDependenceLimit;
};
- auto TryToAddCandidate = [&](SDNode::use_iterator UseIter) {
+ auto TryToAddCandidate = [&](SDUse &Use) {
// This must be a chain use.
- if (UseIter.getOperandNo() != 0)
+ if (Use.getOperandNo() != 0)
return;
- if (auto *OtherStore = dyn_cast<StoreSDNode>(*UseIter)) {
+ if (auto *OtherStore = dyn_cast<StoreSDNode>(Use.getUser())) {
BaseIndexOffset Ptr;
int64_t PtrDiff;
if (CandidateMatch(OtherStore, Ptr, PtrDiff) &&
@@ -20958,19 +20950,20 @@ DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
return nullptr;
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored) {
- if (I.getOperandNo() == 0 && isa<LoadSDNode>(*I)) { // walk down chain
- for (auto I2 = (*I)->use_begin(), E2 = (*I)->use_end(); I2 != E2; ++I2)
- TryToAddCandidate(I2);
+ SDNode *User = I->getUser();
+ if (I->getOperandNo() == 0 && isa<LoadSDNode>(User)) { // walk down chain
+ for (SDUse &U2 : User->uses())
+ TryToAddCandidate(U2);
}
// Check stores that depend on the root (e.g. Store 3 in the chart above).
- if (I.getOperandNo() == 0 && isa<StoreSDNode>(*I)) {
- TryToAddCandidate(I);
+ if (I->getOperandNo() == 0 && isa<StoreSDNode>(User)) {
+ TryToAddCandidate(*I);
}
}
} else {
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored)
- TryToAddCandidate(I);
+ TryToAddCandidate(*I);
}
return RootNode;
@@ -27320,8 +27313,7 @@ SDValue DAGCombiner::visitGET_FPENV_MEM(SDNode *N) {
// Check if the loaded value is used only in a store operation.
StoreSDNode *StNode = nullptr;
- for (auto I = LdNode->use_begin(), E = LdNode->use_end(); I != E; ++I) {
- SDUse &U = I.getUse();
+ for (SDUse &U : LdNode->uses()) {
if (U.getResNo() == 0) {
if (auto *St = dyn_cast<StoreSDNode>(U.getUser())) {
if (StNode)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
index c7d29ec1a836c1..b6abad830c371e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
@@ -88,10 +88,9 @@ void DAGTypeLegalizer::PerformExpensiveChecks() {
if (I != ReplacedValues.end()) {
Mapped |= 1;
// Check that remapped values are only used by nodes marked NewNode.
- for (SDNode::use_iterator UI = Node.use_begin(), UE = Node.use_end();
- UI != UE; ++UI)
- if (UI.getUse().getResNo() == i)
- assert(UI->getNodeId() == NewNode &&
+ for (SDUse &U : Node.uses())
+ if (U.getResNo() == i)
+ assert(U.getUser()->getNodeId() == NewNode &&
"Remapped value has non-trivial use!");
// Check that the final result of applying ReplacedValues is not
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 2e59dbf2f70280..26fc75c0578ec2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -236,7 +236,7 @@ void ScheduleDAGSDNodes::ClusterNeighboringLoads(SDNode *Node) {
// This algorithm requires a reasonably low use count before finding a match
// to avoid uselessly blowing up compile time in large blocks.
unsigned UseCount = 0;
- for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end();
+ for (SDNode::user_iterator I = Chain->user_begin(), E = Chain->user_end();
I != E && UseCount < 100; ++I, ++UseCount) {
if (I.getUse().getResNo() != Chain.getResNo())
continue;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index bd9e5d4dce8ec6..07749ec87d0b20 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -11611,7 +11611,7 @@ class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener {
void NodeDeleted(SDNode *N, SDNode *E) override {
// Increment the iterator as needed.
- while (UI != UE && N == *UI)
+ while (UI != UE && N == UI->getUser())
++UI;
}
@@ -11650,7 +11650,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11660,12 +11660,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
++UI;
Use.set(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
AddModifiedNodeToCSEMaps(User);
@@ -11708,7 +11708,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11718,12 +11718,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
++UI;
Use.setNode(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
@@ -11756,7 +11756,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, const SDValue *To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11767,12 +11767,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, const SDValue *To) {
// user that we can find this way.
bool To_IsDivergent = false;
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
const SDValue &ToOp = To[Use.getResNo()];
++UI;
Use.set(ToOp);
To_IsDivergent |= ToOp->isDivergent();
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
if (To_IsDivergent != From->isDivergent())
updateDivergence(User);
@@ -11810,7 +11810,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
UE = From.getNode()->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
bool UserRemovedFromCSEMaps = false;
// A user can appear in a use list multiple times, and when this
@@ -11818,7 +11818,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
// Skip uses of different values from the same node.
if (Use.getResNo() != From.getResNo()) {
@@ -11837,7 +11837,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
Use.set(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// We are iterating over all uses of the From node, so if a use
// doesn't use the specific value, no changes are made.
if (!UserRemovedFromCSEMaps)
@@ -11982,11 +11982,9 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
for (unsigned i = 0; i != Num; ++i) {
unsigned FromResNo = From[i].getResNo();
SDNode *FromNode = From[i].getNode();
- for (SDNode::use_iterator UI = FromNode->use_begin(),
- E = FromNode->use_end(); UI != E; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : FromNode->uses()) {
if (Use.getResNo() == FromResNo) {
- UseMemo Memo = { *UI, i, &Use };
+ UseMemo Memo = {Use.getUser(), i, &Use};
Uses.push_back(Memo);
}
}
@@ -12462,8 +12460,8 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
assert(Value < getNumValues() && "Bad value!");
// TODO: Only iterate over uses of a given value of the node
- for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) {
- if (UI.getUse().getResNo() == Value) {
+ for (SDUse &U : uses()) {
+ if (U.getResNo() == Value) {
if (NUses == 0)
return false;
--NUses;
@@ -12479,8 +12477,8 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
bool SDNode::hasAnyUseOfValue(unsigned Value) const {
assert(Value < getNumValues() && "Bad value!");
- for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI)
- if (UI.getUse().getResNo() == Value)
+ for (SDUse &U : uses())
+ if (U.getResNo() == Value)
return true;
return false;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index c4d0552ad55d39..c1dabe05452fb9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3792,8 +3792,8 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
for (unsigned i = 1, e = NodeStack.size()-1; i != e; ++i) {
unsigned NNonChainUses = 0;
SDNode *NS = NodeStack[i].getNode();
- for (auto UI = NS->use_begin(), UE = NS->use_end(); UI != UE; ++UI)
- if (UI.getUse().getValueType() != MVT::Other)
+ for (const SDUse &U : NS->uses())
+ if (U.getValueType() != MVT::Other)
if (++NNonChainUses > 1) {
HasMultipleUses = true;
break;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 494506def33a35..257cb716bae430 100644
--- a/l...
[truncated]
|
@llvm/pr-subscribers-backend-aarch64 Author: Craig Topper (topperc) ChangesThis allows to write more range based for loops because we no SDNode is declared after SDUse so I had to put the definition Stacked on #120531 Patch is 53.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120536.diff 18 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
index 77c04369f3e92d..63eb40718a10c7 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAGNodes.h
@@ -310,6 +310,9 @@ class SDUse {
/// Get the next SDUse in the use list.
SDUse *getNext() const { return Next; }
+ /// Return the operand # of this use in its user.
+ inline unsigned getOperandNo() const;
+
/// Convenience function for get().getNode().
SDNode *getNode() const { return Val.getNode(); }
/// Convenience function for get().getResNo().
@@ -750,7 +753,7 @@ END_TWO_BYTE_PACK()
bool use_empty() const { return UseList == nullptr; }
/// Return true if there is exactly one use of this node.
- bool hasOneUse() const { return hasSingleElement(users()); }
+ bool hasOneUse() const { return hasSingleElement(uses()); }
/// Return the number of uses of this node. This method takes
/// time proportional to the number of uses.
@@ -821,20 +824,52 @@ END_TWO_BYTE_PACK()
}
/// Retrieve a pointer to the current user node.
- SDNode *operator*() const {
+ SDUse &operator*() const {
assert(Op && "Cannot dereference end iterator!");
- return Op->getUser();
+ return *Op;
}
- SDNode *operator->() const { return operator*(); }
+ SDUse *operator->() const { return &operator*(); }
+ };
+
+ class user_iterator {
+ friend class SDNode;
+ use_iterator UI;
- SDUse &getUse() const { return *Op; }
+ explicit user_iterator(SDUse *op) : UI(op) {};
- /// Retrieve the operand # of this use in its user.
- unsigned getOperandNo() const {
- assert(Op && "Cannot dereference end iterator!");
- return (unsigned)(Op - Op->getUser()->OperandList);
+ public:
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = SDNode *;
+ using difference_type = std::ptrdiff_t;
+ using pointer = value_type *;
+ using reference = value_type &;
+
+ user_iterator() = default;
+
+ bool operator==(const user_iterator &x) const { return UI == x.UI; }
+ bool operator!=(const user_iterator &x) const { return !operator==(x); }
+
+ // /// Return true if this iterator is at the end of the uses list.
+ bool atEnd() const { return *this == user_iterator(); }
+
+ user_iterator &operator++() { // Preincrement
+ ++UI;
+ return *this;
+ }
+
+ user_iterator operator++(int) { // Postincrement
+ auto tmp = *this;
+ ++*this;
+ return tmp;
}
+
+ // Retrieve a pointer to the current User.
+ SDNode *operator*() const { return UI->getUser(); }
+
+ SDNode *operator->() const { return operator*(); }
+
+ SDUse &getUse() const { return *UI; }
};
/// Provide iteration support to walk over all uses of an SDNode.
@@ -844,22 +879,25 @@ END_TWO_BYTE_PACK()
static use_iterator use_end() { return use_iterator(nullptr); }
- /// Provide iteration support to walk over all users of an SDNode.
- /// For now, this should only be used to get a pointer to the first user.
- /// FIXME: Rename use_iterator to user_iterator. Add user_end().
- use_iterator user_begin() const { return use_iterator(UseList); }
-
- // Dereferencing use_iterator returns the user SDNode* making it closer to a
- // user_iterator thus this function is called users() to reflect that.
- // FIXME: Rename to user_iterator and introduce a use_iterator that returns
- // SDUse*.
- inline iterator_range<use_iterator> users() {
+ inline iterator_range<use_iterator> uses() {
return make_range(use_begin(), use_end());
}
- inline iterator_range<use_iterator> users() const {
+ inline iterator_range<use_iterator> uses() const {
return make_range(use_begin(), use_end());
}
+ /// Provide iteration support to walk over all users of an SDNode.
+ user_iterator user_begin() const { return user_iterator(UseList); }
+
+ static user_iterator user_end() { return user_iterator(nullptr); }
+
+ inline iterator_range<user_iterator> users() {
+ return make_range(user_begin(), user_end());
+ }
+ inline iterator_range<user_iterator> users() const {
+ return make_range(user_begin(), user_end());
+ }
+
/// Return true if there are exactly NUSES uses of the indicated value.
/// This method ignores uses of other values defined by this operation.
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const;
@@ -1019,9 +1057,9 @@ END_TWO_BYTE_PACK()
/// If this node has a glue value with a user, return
/// the user (there is at most one). Otherwise return NULL.
SDNode *getGluedUser() const {
- for (use_iterator UI = use_begin(), UE = use_end(); UI != UE; ++UI)
- if (UI.getUse().get().getValueType() == MVT::Glue)
- return *UI;
+ for (SDUse &U : uses())
+ if (U.getValueType() == MVT::Glue)
+ return U.getUser();
return nullptr;
}
@@ -1268,6 +1306,9 @@ inline void SDValue::dumpr(const SelectionDAG *G) const {
}
// Define inline functions from the SDUse class.
+inline unsigned SDUse::getOperandNo() const {
+ return this - getUser()->op_begin();
+}
inline void SDUse::set(const SDValue &V) {
if (Val.getNode()) removeFromList();
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 85009439c37b3a..6cbfef2d238bbe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -13229,12 +13229,11 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
const TargetLowering &TLI) {
bool HasCopyToRegUses = false;
bool isTruncFree = TLI.isTruncateFree(VT, N0.getValueType());
- for (SDNode::use_iterator UI = N0->use_begin(), UE = N0->use_end(); UI != UE;
- ++UI) {
- SDNode *User = *UI;
+ for (SDUse &Use : N0->uses()) {
+ SDNode *User = Use.getUser();
if (User == N)
continue;
- if (UI.getUse().getResNo() != N0.getResNo())
+ if (Use.getResNo() != N0.getResNo())
continue;
// FIXME: Only extend SETCC N, N and SETCC N, c for now.
if (ExtOpc != ISD::ANY_EXTEND && User->getOpcode() == ISD::SETCC) {
@@ -13266,9 +13265,7 @@ static bool ExtendUsesToFormExtLoad(EVT VT, SDNode *N, SDValue N0,
if (HasCopyToRegUses) {
bool BothLiveOut = false;
- for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
- UI != UE; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : N->uses()) {
if (Use.getResNo() == 0 && Use.getUser()->getOpcode() == ISD::CopyToReg) {
BothLiveOut = true;
break;
@@ -13780,11 +13777,10 @@ SDValue DAGCombiner::foldSextSetcc(SDNode *N) {
// Non-chain users of this value must either be the setcc in this
// sequence or extends that can be folded into the new {z/s}ext-load.
- for (SDNode::use_iterator UI = V->use_begin(), UE = V->use_end();
- UI != UE; ++UI) {
+ for (SDUse &Use : V->uses()) {
// Skip uses of the chain and the setcc.
- SDNode *User = *UI;
- if (UI.getUse().getResNo() != 0 || User == N0.getNode())
+ SDNode *User = Use.getUser();
+ if (Use.getResNo() != 0 || User == N0.getNode())
continue;
// Extra users must have exactly the same cast we are about to create.
// TODO: This restriction could be eased if ExtendUsesToFormExtLoad()
@@ -18925,10 +18921,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
SmallVector<SDNode *, 16> OtherUses;
unsigned MaxSteps = SelectionDAG::getHasPredecessorMaxSteps();
if (isa<ConstantSDNode>(Offset))
- for (SDNode::use_iterator UI = BasePtr->use_begin(),
- UE = BasePtr->use_end();
- UI != UE; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : BasePtr->uses()) {
// Skip the use that is Ptr and uses of other results from BasePtr's
// node (important for nodes that return multiple results).
if (Use.getUser() == Ptr.getNode() || Use != BasePtr)
@@ -18944,7 +18937,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
break;
}
- SDValue Op1 = Use.getUser()->getOperand((UI.getOperandNo() + 1) & 1);
+ SDValue Op1 = Use.getUser()->getOperand((Use.getOperandNo() + 1) & 1);
if (!isa<ConstantSDNode>(Op1)) {
OtherUses.clear();
break;
@@ -20056,13 +20049,12 @@ bool DAGCombiner::SliceUpLoad(SDNode *N) {
// Check if this load is used as several smaller chunks of bits.
// Basically, look for uses in trunc or trunc(lshr) and record a new chain
// of computation for each trunc.
- for (SDNode::use_iterator UI = LD->use_begin(), UIEnd = LD->use_end();
- UI != UIEnd; ++UI) {
+ for (SDUse &U : LD->uses()) {
// Skip the uses of the chain.
- if (UI.getUse().getResNo() != 0)
+ if (U.getResNo() != 0)
continue;
- SDNode *User = *UI;
+ SDNode *User = U.getUser();
unsigned Shift = 0;
// Check if this is a trunc(lshr).
@@ -20936,11 +20928,11 @@ DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
RootCount->second.second > StoreMergeDependenceLimit;
};
- auto TryToAddCandidate = [&](SDNode::use_iterator UseIter) {
+ auto TryToAddCandidate = [&](SDUse &Use) {
// This must be a chain use.
- if (UseIter.getOperandNo() != 0)
+ if (Use.getOperandNo() != 0)
return;
- if (auto *OtherStore = dyn_cast<StoreSDNode>(*UseIter)) {
+ if (auto *OtherStore = dyn_cast<StoreSDNode>(Use.getUser())) {
BaseIndexOffset Ptr;
int64_t PtrDiff;
if (CandidateMatch(OtherStore, Ptr, PtrDiff) &&
@@ -20958,19 +20950,20 @@ DAGCombiner::getStoreMergeCandidates(StoreSDNode *St,
return nullptr;
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored) {
- if (I.getOperandNo() == 0 && isa<LoadSDNode>(*I)) { // walk down chain
- for (auto I2 = (*I)->use_begin(), E2 = (*I)->use_end(); I2 != E2; ++I2)
- TryToAddCandidate(I2);
+ SDNode *User = I->getUser();
+ if (I->getOperandNo() == 0 && isa<LoadSDNode>(User)) { // walk down chain
+ for (SDUse &U2 : User->uses())
+ TryToAddCandidate(U2);
}
// Check stores that depend on the root (e.g. Store 3 in the chart above).
- if (I.getOperandNo() == 0 && isa<StoreSDNode>(*I)) {
- TryToAddCandidate(I);
+ if (I->getOperandNo() == 0 && isa<StoreSDNode>(User)) {
+ TryToAddCandidate(*I);
}
}
} else {
for (auto I = RootNode->use_begin(), E = RootNode->use_end();
I != E && NumNodesExplored < MaxSearchNodes; ++I, ++NumNodesExplored)
- TryToAddCandidate(I);
+ TryToAddCandidate(*I);
}
return RootNode;
@@ -27320,8 +27313,7 @@ SDValue DAGCombiner::visitGET_FPENV_MEM(SDNode *N) {
// Check if the loaded value is used only in a store operation.
StoreSDNode *StNode = nullptr;
- for (auto I = LdNode->use_begin(), E = LdNode->use_end(); I != E; ++I) {
- SDUse &U = I.getUse();
+ for (SDUse &U : LdNode->uses()) {
if (U.getResNo() == 0) {
if (auto *St = dyn_cast<StoreSDNode>(U.getUser())) {
if (StNode)
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
index c7d29ec1a836c1..b6abad830c371e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
@@ -88,10 +88,9 @@ void DAGTypeLegalizer::PerformExpensiveChecks() {
if (I != ReplacedValues.end()) {
Mapped |= 1;
// Check that remapped values are only used by nodes marked NewNode.
- for (SDNode::use_iterator UI = Node.use_begin(), UE = Node.use_end();
- UI != UE; ++UI)
- if (UI.getUse().getResNo() == i)
- assert(UI->getNodeId() == NewNode &&
+ for (SDUse &U : Node.uses())
+ if (U.getResNo() == i)
+ assert(U.getUser()->getNodeId() == NewNode &&
"Remapped value has non-trivial use!");
// Check that the final result of applying ReplacedValues is not
diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
index 2e59dbf2f70280..26fc75c0578ec2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp
@@ -236,7 +236,7 @@ void ScheduleDAGSDNodes::ClusterNeighboringLoads(SDNode *Node) {
// This algorithm requires a reasonably low use count before finding a match
// to avoid uselessly blowing up compile time in large blocks.
unsigned UseCount = 0;
- for (SDNode::use_iterator I = Chain->use_begin(), E = Chain->use_end();
+ for (SDNode::user_iterator I = Chain->user_begin(), E = Chain->user_end();
I != E && UseCount < 100; ++I, ++UseCount) {
if (I.getUse().getResNo() != Chain.getResNo())
continue;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index bd9e5d4dce8ec6..07749ec87d0b20 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -11611,7 +11611,7 @@ class RAUWUpdateListener : public SelectionDAG::DAGUpdateListener {
void NodeDeleted(SDNode *N, SDNode *E) override {
// Increment the iterator as needed.
- while (UI != UE && N == *UI)
+ while (UI != UE && N == UI->getUser())
++UI;
}
@@ -11650,7 +11650,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11660,12 +11660,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDValue FromN, SDValue To) {
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
++UI;
Use.set(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
AddModifiedNodeToCSEMaps(User);
@@ -11708,7 +11708,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11718,12 +11718,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
++UI;
Use.setNode(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
@@ -11756,7 +11756,7 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, const SDValue *To) {
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
@@ -11767,12 +11767,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, const SDValue *To) {
// user that we can find this way.
bool To_IsDivergent = false;
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
const SDValue &ToOp = To[Use.getResNo()];
++UI;
Use.set(ToOp);
To_IsDivergent |= ToOp->isDivergent();
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
if (To_IsDivergent != From->isDivergent())
updateDivergence(User);
@@ -11810,7 +11810,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
UE = From.getNode()->use_end();
RAUWUpdateListener Listener(*this, UI, UE);
while (UI != UE) {
- SDNode *User = *UI;
+ SDNode *User = UI->getUser();
bool UserRemovedFromCSEMaps = false;
// A user can appear in a use list multiple times, and when this
@@ -11818,7 +11818,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
// To help reduce the number of CSE recomputations, process all
// the uses of this user that we can find this way.
do {
- SDUse &Use = UI.getUse();
+ SDUse &Use = *UI;
// Skip uses of different values from the same node.
if (Use.getResNo() != From.getResNo()) {
@@ -11837,7 +11837,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To){
Use.set(To);
if (To->isDivergent() != From->isDivergent())
updateDivergence(User);
- } while (UI != UE && *UI == User);
+ } while (UI != UE && UI->getUser() == User);
// We are iterating over all uses of the From node, so if a use
// doesn't use the specific value, no changes are made.
if (!UserRemovedFromCSEMaps)
@@ -11982,11 +11982,9 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
for (unsigned i = 0; i != Num; ++i) {
unsigned FromResNo = From[i].getResNo();
SDNode *FromNode = From[i].getNode();
- for (SDNode::use_iterator UI = FromNode->use_begin(),
- E = FromNode->use_end(); UI != E; ++UI) {
- SDUse &Use = UI.getUse();
+ for (SDUse &Use : FromNode->uses()) {
if (Use.getResNo() == FromResNo) {
- UseMemo Memo = { *UI, i, &Use };
+ UseMemo Memo = {Use.getUser(), i, &Use};
Uses.push_back(Memo);
}
}
@@ -12462,8 +12460,8 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
assert(Value < getNumValues() && "Bad value!");
// TODO: Only iterate over uses of a given value of the node
- for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) {
- if (UI.getUse().getResNo() == Value) {
+ for (SDUse &U : uses()) {
+ if (U.getResNo() == Value) {
if (NUses == 0)
return false;
--NUses;
@@ -12479,8 +12477,8 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
bool SDNode::hasAnyUseOfValue(unsigned Value) const {
assert(Value < getNumValues() && "Bad value!");
- for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI)
- if (UI.getUse().getResNo() == Value)
+ for (SDUse &U : uses())
+ if (U.getResNo() == Value)
return true;
return false;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index c4d0552ad55d39..c1dabe05452fb9 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3792,8 +3792,8 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
for (unsigned i = 1, e = NodeStack.size()-1; i != e; ++i) {
unsigned NNonChainUses = 0;
SDNode *NS = NodeStack[i].getNode();
- for (auto UI = NS->use_begin(), UE = NS->use_end(); UI != UE; ++UI)
- if (UI.getUse().getValueType() != MVT::Other)
+ for (const SDUse &U : NS->uses())
+ if (U.getValueType() != MVT::Other)
if (++NNonChainUses > 1) {
HasMultipleUses = true;
break;
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 494506def33a35..257cb716bae430 100644
--- a/l...
[truncated]
|
This allows to write more range based for loops because we no longer need the iterator. SDNode is declared after SDUse so I had to put the definition later in the header file.
f44abf4
to
444d81b
Compare
This allows to write more range based for loops because we no
longer need the iterator. It also matches IR.
SDNode is declared after SDUse so I had to put the definition
later in the header file.
Stacked on #120531