Index: llvm/include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAGNodes.h +++ llvm/include/llvm/CodeGen/SelectionDAGNodes.h @@ -280,8 +280,10 @@ SDNode *User = nullptr; /// Prev, Next - Pointers to the uses list of the SDNode referred by /// this operand. - SDUse **Prev = nullptr; - SDUse *Next = nullptr; + SDUse **AllUsesPrev = nullptr; + SDUse *AllUsesNext = nullptr; + SDUse **ResNoUsesPrev = nullptr; + SDUse *ResNoUsesNext = nullptr; public: SDUse() = default; @@ -298,9 +300,6 @@ /// This returns the SDNode that contains this Use. SDNode *getUser() { return User; } - /// Get the next SDUse in the use list. - SDUse *getNext() const { return Next; } - /// Convenience function for get().getNode(). SDNode *getNode() const { return Val.getNode(); } /// Convenience function for get().getResNo(). @@ -340,18 +339,6 @@ /// Like set, but only sets the Node portion of the value, /// leaving the ResNo portion unmodified. inline void setNode(SDNode *N); - - void addToList(SDUse **List) { - Next = *List; - if (Next) Next->Prev = &Next; - Prev = List; - *List = this; - } - - void removeFromList() { - *Prev = Next; - if (Next) Next->Prev = Prev; - } }; /// simplify_type specializations - Allow casting operators to work directly on @@ -592,7 +579,11 @@ /// define multiple values simultaneously. const EVT *ValueList; - /// List of uses for this SDNode. + /// Lists of uses for each value of this SDNode. + SmallVector ResNoToUseList; + /// List of all uses. Duplicates info from ResNoToUseList but is easier + /// to iterate over so using it gives better performance in cases where + /// the whole use list is needed. SDUse *UseList = nullptr; /// The number of entries in the Operand/Value list. @@ -730,12 +721,12 @@ /// This class provides iterator support for SDUse /// operands that use a specific SDNode. - class use_iterator { + template class use_iterator_template { friend class SDNode; SDUse *Op = nullptr; - explicit use_iterator(SDUse *op) : Op(op) {} + explicit use_iterator_template(SDUse *Op) : Op(Op) {} public: using iterator_category = std::forward_iterator_tag; @@ -744,11 +735,15 @@ using pointer = value_type *; using reference = value_type &; - use_iterator() = default; - use_iterator(const use_iterator &I) = default; + use_iterator_template() = default; + use_iterator_template(const use_iterator_template &I) = default; - bool operator==(const use_iterator &x) const { return Op == x.Op; } - bool operator!=(const use_iterator &x) const { + template + bool operator==(const use_iterator_template &x) const { + return Op == x.Op; + } + template + bool operator!=(const use_iterator_template &x) const { return !operator==(x); } @@ -756,14 +751,16 @@ bool atEnd() const { return Op == nullptr; } // Iterator traversal: forward iteration only. - use_iterator &operator++() { // Preincrement + use_iterator_template &operator++() { // Preincrement assert(Op && "Cannot increment end iterator!"); - Op = Op->getNext(); + Op = (NeedAllUses ? Op->AllUsesNext : Op->ResNoUsesNext); return *this; } - use_iterator operator++(int) { // Postincrement - use_iterator tmp = *this; ++*this; return tmp; + use_iterator_template operator++(int) { // Postincrement + use_iterator_template tmp = *this; + ++*this; + return tmp; } /// Retrieve a pointer to the current user node. @@ -783,20 +780,91 @@ } }; + using use_iterator = use_iterator_template; + using use_per_resno_iterator = use_iterator_template; + /// Provide iteration support to walk over all uses of an SDNode. - use_iterator use_begin() const { - return use_iterator(UseList); - } + use_iterator use_begin() const { return use_iterator(UseList); } static use_iterator use_end() { return use_iterator(nullptr); } +#define LLVM_SDNODE_CHECK_USELIST_MAP_SIZE() \ + assert(ResNoToUseList.size() == NumValues && \ + "ResNo count in UseList map does not match NumValues"); + +public: + /// Provide iteration support to walk over all uses of an SDNode. + use_per_resno_iterator use_per_resno_begin(unsigned ResNo) const { + LLVM_SDNODE_CHECK_USELIST_MAP_SIZE(); + assert(ResNo < NumValues && "ResNo exceeds NumValues"); + return use_per_resno_iterator(ResNoToUseList[ResNo]); + } + + use_per_resno_iterator use_per_resno_end(unsigned ResNo) const { + LLVM_SDNODE_CHECK_USELIST_MAP_SIZE(); + assert(ResNo < NumValues && "ResNo exceeds NumValues"); + return use_per_resno_iterator(nullptr); + } + inline iterator_range uses() { + LLVM_SDNODE_CHECK_USELIST_MAP_SIZE(); return make_range(use_begin(), use_end()); } inline iterator_range uses() const { + LLVM_SDNODE_CHECK_USELIST_MAP_SIZE(); return make_range(use_begin(), use_end()); } + /// This method should only be used by the SDUse class. + void addUse(SDUse &U) { + LLVM_SDNODE_CHECK_USELIST_MAP_SIZE(); + assert(U.getResNo() < NumValues && "ResNo exceeds NumValues"); + + SDUse **ResNoUsesList = &ResNoToUseList[U.getResNo()]; + U.ResNoUsesNext = *ResNoUsesList; + if (U.ResNoUsesNext) + U.ResNoUsesNext->ResNoUsesPrev = &U.ResNoUsesNext; + U.ResNoUsesPrev = ResNoUsesList; + *ResNoUsesList = &U; + + SDUse **AllUsesList = &UseList; + U.AllUsesNext = *AllUsesList; + if (U.AllUsesNext) + U.AllUsesNext->AllUsesPrev = &U.AllUsesNext; + U.AllUsesPrev = AllUsesList; + *AllUsesList = &U; + } + + /// This method should only be used by the SDUse class. + void removeUse(SDUse &U) { + LLVM_SDNODE_CHECK_USELIST_MAP_SIZE(); + + *U.ResNoUsesPrev = U.ResNoUsesNext; + if (U.ResNoUsesNext) + U.ResNoUsesNext->ResNoUsesPrev = U.ResNoUsesPrev; + + *U.AllUsesPrev = U.AllUsesNext; + if (U.AllUsesNext) + U.AllUsesNext->AllUsesPrev = U.AllUsesPrev; + } + + /// To be used from MorphNodeTo when changing NumValues + /// leads to ResNoToUseList remapping. + void remapUses() { + std::vector AllUses; + for (auto UI = use_begin(), UE = use_end(); UI != UE; ++UI) { + AllUses.emplace_back(&UI.getUse()); + } + + UseList = nullptr; + ResNoToUseList = SmallVector(NumValues, nullptr); + for (auto it = AllUses.rbegin(); it != AllUses.rend(); ++it) + if ((*it)->getNode()) + addUse(**it); + } + +#undef LLVM_SDNODE_CHECK_USELIST_MAP_SIZE + /// 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; @@ -1052,9 +1120,6 @@ /// Gather unique data for the node. void Profile(FoldingSetNodeID &ID) const; - /// This method should only be used by the SDUse class. - void addUse(SDUse &U) { U.addToList(&UseList); } - protected: static SDVTList getSDVTList(EVT VT) { SDVTList Ret = { getValueTypeList(VT), 1 }; @@ -1066,8 +1131,8 @@ /// SDNodes are created without any operands, and never own the operand /// storage. To add operands, see SelectionDAG::createOperands. SDNode(unsigned Opc, unsigned Order, DebugLoc dl, SDVTList VTs) - : NodeType(Opc), ValueList(VTs.VTs), NumValues(VTs.NumVTs), - IROrder(Order), debugLoc(std::move(dl)) { + : NodeType(Opc), ValueList(VTs.VTs), ResNoToUseList(VTs.NumVTs, nullptr), + NumValues(VTs.NumVTs), IROrder(Order), debugLoc(std::move(dl)) { memset(&RawSDNodeBits, 0, sizeof(RawSDNodeBits)); assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor"); assert(NumValues == VTs.NumVTs && @@ -1193,7 +1258,8 @@ // Define inline functions from the SDUse class. inline void SDUse::set(const SDValue &V) { - if (Val.getNode()) removeFromList(); + if (Val.getNode()) + Val.getNode()->removeUse(*this); Val = V; if (V.getNode()) V->addUse(*this); @@ -1205,7 +1271,8 @@ } inline void SDUse::setNode(SDNode *N) { - if (Val.getNode()) removeFromList(); + if (Val.getNode()) + Val.getNode()->removeUse(*this); Val.setNode(N); if (N) N->addUse(*this); } Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -11228,13 +11228,12 @@ 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) { + for (auto UI = N0->use_per_resno_begin(N0.getResNo()), + UE = N0->use_per_resno_end(N0.getResNo()); + UI != UE; ++UI) { SDNode *User = *UI; if (User == N) continue; - if (UI.getUse().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) { ISD::CondCode CC = cast(User->getOperand(2))->get(); @@ -11265,10 +11264,9 @@ if (HasCopyToRegUses) { bool BothLiveOut = false; - for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end(); + for (auto UI = N->use_per_resno_begin(0), UE = N->use_per_resno_end(0); UI != UE; ++UI) { - SDUse &Use = UI.getUse(); - if (Use.getResNo() == 0 && Use.getUser()->getOpcode() == ISD::CopyToReg) { + if (UI.getUse().getUser()->getOpcode() == ISD::CopyToReg) { BothLiveOut = true; break; } @@ -11727,11 +11725,11 @@ // 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(); + for (auto UI = V->use_per_resno_begin(0), UE = V->use_per_resno_end(0); UI != UE; ++UI) { // Skip uses of the chain and the setcc. SDNode *User = *UI; - if (UI.getUse().getResNo() != 0 || User == N0.getNode()) + if (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() @@ -17155,12 +17153,9 @@ // 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(); + // Iterate over uses of 0 value only to skip the uses of the chain. + for (auto UI = LD->use_per_resno_begin(0), UIEnd = LD->use_per_resno_end(0); UI != UIEnd; ++UI) { - // Skip the uses of the chain. - if (UI.getUse().getResNo() != 0) - continue; - SDNode *User = *UI; unsigned Shift = 0; Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -86,11 +86,11 @@ if (ResId && (ReplacedValues.find(ResId) != 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(); + for (auto UI = Node.use_per_resno_begin(i), + UE = Node.use_per_resno_end(i); UI != UE; ++UI) - if (UI.getUse().getResNo() == i) - assert(UI->getNodeId() == NewNode && - "Remapped value has non-trivial use!"); + assert(UI->getNodeId() == NewNode && + "Remapped value has non-trivial use!"); // Check that the final result of applying ReplacedValues is not // marked NewNode. Index: llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -231,11 +231,10 @@ // 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(); + unsigned ChResNo = Chain.getResNo(); + for (auto I = Chain->use_per_resno_begin(ChResNo), + E = Chain->use_per_resno_end(ChResNo); I != E && UseCount < 100; ++I, ++UseCount) { - if (I.getUse().getResNo() != Chain.getResNo()) - continue; - SDNode *User = *I; if (User == Node || !Visited.insert(User).second) continue; Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1328,11 +1328,13 @@ MCSymbols.clear(); SDCallSiteDbgInfo.clear(); std::fill(CondCodeNodes.begin(), CondCodeNodes.end(), - static_cast(nullptr)); + static_cast(nullptr)); std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(), - static_cast(nullptr)); - + static_cast(nullptr)); + std::fill(EntryNode.ResNoToUseList.begin(), EntryNode.ResNoToUseList.end(), + static_cast(nullptr)); EntryNode.UseList = nullptr; + InsertNode(&EntryNode); Root = getEntryNode(); DbgInfo->clear(); @@ -9342,6 +9344,7 @@ N->NodeType = Opc; N->ValueList = VTs.VTs; N->NumValues = VTs.NumVTs; + N->remapUses(); // Clear the operands list, updating used nodes to remove this from their // use list. Keep track of any operands that become dead as a result. @@ -10186,13 +10189,11 @@ 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(); - if (Use.getResNo() == FromResNo) { - UseMemo Memo = { *UI, i, &Use }; - Uses.push_back(Memo); - } + for (auto UI = FromNode->use_per_resno_begin(FromResNo), + E = FromNode->use_per_resno_end(FromResNo); + UI != E; ++UI) { + UseMemo Memo = {*UI, i, &UI.getUse()}; + Uses.push_back(Memo); } } @@ -10630,13 +10631,11 @@ 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) { - if (NUses == 0) - return false; - --NUses; - } + for (auto UI = use_per_resno_begin(Value), UE = use_per_resno_end(Value); + UI != UE; ++UI) { + if (NUses == 0) + return false; + --NUses; } // Found exactly the right number of uses? @@ -10647,12 +10646,7 @@ /// value. This method ignores uses of other values defined by this operation. 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) - return true; - - return false; + return (ResNoToUseList[Value] != nullptr); } /// isOnlyUserOf - Return true if this node is the only use of N. @@ -11598,8 +11592,8 @@ #ifndef NDEBUG static void checkForCyclesHelper(const SDNode *N, - SmallPtrSetImpl &Visited, - SmallPtrSetImpl &Checked, + SmallPtrSetImpl &Visited, + SmallPtrSetImpl &Checked, const llvm::SelectionDAG *DAG) { // If this node has already been checked, don't check it again. if (Checked.count(N)) Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2049,11 +2049,11 @@ /// static SDNode *findGlueUse(SDNode *N) { unsigned FlagResNo = N->getNumValues()-1; - for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { - SDUse &Use = I.getUse(); - if (Use.getResNo() == FlagResNo) - return Use.getUser(); - } + auto UseIt = N->use_per_resno_begin(FlagResNo); + + if (UseIt != N->use_end()) + return UseIt.getUse().getUser(); + return nullptr; } Index: llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUISelDAGToDAG.cpp @@ -920,15 +920,14 @@ bool IsAdd = N->getOpcode() == ISD::UADDO; bool IsVALU = N->isDivergent(); - for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end(); UI != E; - ++UI) - if (UI.getUse().getResNo() == 1) { - if ((IsAdd && (UI->getOpcode() != ISD::ADDCARRY)) || - (!IsAdd && (UI->getOpcode() != ISD::SUBCARRY))) { - IsVALU = true; - break; - } + for (auto UI = N->use_per_resno_begin(1), E = N->use_per_resno_end(1); + UI != E; ++UI) { + if ((IsAdd && (UI->getOpcode() != ISD::ADDCARRY)) || + (!IsAdd && (UI->getOpcode() != ISD::SUBCARRY))) { + IsVALU = true; + break; } + } if (IsVALU) { unsigned Opc = IsAdd ? AMDGPU::V_ADD_CO_U32_e64 : AMDGPU::V_SUB_CO_U32_e64; Index: llvm/lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -5196,12 +5196,10 @@ static SDNode *findUser(SDValue Value, unsigned Opcode) { SDNode *Parent = Value.getNode(); - for (SDNode::use_iterator I = Parent->use_begin(), E = Parent->use_end(); + unsigned ResNo = Value.getResNo(); + for (auto I = Parent->use_per_resno_begin(ResNo), + E = Parent->use_per_resno_end(ResNo); I != E; ++I) { - - if (I.getUse().get() != Value) - continue; - if (I->getOpcode() == Opcode) return *I; } @@ -11302,13 +11300,9 @@ } // Try to figure out the used register components - for (SDNode::use_iterator I = Node->use_begin(), E = Node->use_end(); + // Don't look at users of the chain. + for (auto I = Node->use_per_resno_begin(0), E = Node->use_per_resno_end(0); I != E; ++I) { - - // Don't look at users of the chain. - if (I.getUse().getResNo() != 0) - continue; - // Abort if we can't understand the usage if (!I->isMachineOpcode() || I->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG) Index: llvm/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm/lib/Target/ARM/ARMISelLowering.cpp +++ llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -15909,11 +15909,11 @@ SmallVector BaseUpdates; // Search for a use of the address operand that is an increment. - for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), - UE = Addr.getNode()->use_end(); UI != UE; ++UI) { + for (auto UI = Addr.getNode()->use_per_resno_begin(Addr.getResNo()), + UE = Addr.getNode()->use_per_resno_end(Addr.getResNo()); + UI != UE; ++UI) { SDNode *User = *UI; - if (UI.getUse().getResNo() != Addr.getResNo() || - User->getNumOperands() != 2) + if (User->getNumOperands() != 2) continue; SDValue Inc = User->getOperand(UI.getOperandNo() == 1 ? 0 : 1); @@ -15931,12 +15931,14 @@ if (findPointerConstIncrement(Addr.getNode(), &Base, &CInc)) { unsigned Offset = getPointerConstIncrement(Addr->getOpcode(), Base, CInc, DCI.DAG); - for (SDNode::use_iterator UI = Base->use_begin(), UE = Base->use_end(); + + unsigned BaseResNo = Base.getResNo(); + for (auto UI = Base->use_per_resno_begin(BaseResNo), + UE = Base->use_per_resno_end(BaseResNo); UI != UE; ++UI) { SDNode *User = *UI; - if (UI.getUse().getResNo() != Base.getResNo() || User == Addr.getNode() || - User->getNumOperands() != 2) + if (User == Addr.getNode() || User->getNumOperands() != 2) continue; SDValue UserInc = User->getOperand(UI.getOperandNo() == 0 ? 1 : 0); @@ -16014,12 +16016,11 @@ return SDValue(); // Search for a use of the address operand that is an increment. - for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), - UE = Addr.getNode()->use_end(); + for (auto UI = Addr.getNode()->use_per_resno_begin(Addr.getResNo()), + UE = Addr.getNode()->use_per_resno_end(Addr.getResNo()); UI != UE; ++UI) { SDNode *User = *UI; - if (User->getOpcode() != ISD::ADD || - UI.getUse().getResNo() != Addr.getResNo()) + if (User->getOpcode() != ISD::ADD) continue; // Check that the add is independent of the load/store. Otherwise, folding Index: llvm/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -2953,10 +2953,9 @@ if (!LoadedVal.hasOneUse()) return false; - for (SDNode::use_iterator UI = LD->use_begin(), UE = LD->use_end(); + for (auto UI = LD->use_per_resno_begin(0), UE = LD->use_per_resno_end(0); UI != UE; ++UI) - if (UI.getUse().get().getResNo() == 0 && - UI->getOpcode() != ISD::SCALAR_TO_VECTOR && + if (UI->getOpcode() != ISD::SCALAR_TO_VECTOR && UI->getOpcode() != PPCISD::SCALAR_TO_VECTOR_PERMUTED) return false; @@ -8334,14 +8333,10 @@ if (!Subtarget.hasP9Vector() && MMO->getSize() <= 2) return true; - for (SDNode::use_iterator UI = Origin->use_begin(), - UE = Origin->use_end(); + // Only look at the users of the loaded value. + for (auto UI = Origin->use_per_resno_begin(0), + UE = Origin->use_per_resno_end(0); UI != UE; ++UI) { - - // Only look at the users of the loaded value. - if (UI.getUse().get().getResNo() != 0) - continue; - if (UI->getOpcode() != ISD::SINT_TO_FP && UI->getOpcode() != ISD::UINT_TO_FP && UI->getOpcode() != ISD::STRICT_SINT_TO_FP && @@ -15031,9 +15026,10 @@ // If the load return value 0 has more than one user except the // shufflevector instruction, it is not profitable to replace the // shufflevector with a reverse load. - for (SDNode::use_iterator UI = LSBase->use_begin(), UE = LSBase->use_end(); + for (auto UI = LSBase->use_per_resno_begin(0), + UE = LSBase->use_per_resno_end(0); UI != UE; ++UI) - if (UI.getUse().getResNo() == 0 && UI->getOpcode() != ISD::VECTOR_SHUFFLE) + if (UI->getOpcode() != ISD::VECTOR_SHUFFLE) return SDValue(); SDLoc dl(LSBase); @@ -15241,10 +15237,8 @@ if (!LD->hasNUsesOfValue(2, 0)) return false; - auto UI = LD->use_begin(); - while (UI.getUse().getResNo() != 0) ++UI; + auto UI = LD->use_per_resno_begin(0); SDNode *Trunc = *UI++; - while (UI.getUse().getResNo() != 0) ++UI; SDNode *RightShift = *UI; if (Trunc->getOpcode() != ISD::TRUNCATE) std::swap(Trunc, RightShift); Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -2953,20 +2953,19 @@ /// other than ZF. bool X86DAGToDAGISel::onlyUsesZeroFlag(SDValue Flags) const { // Examine each user of the node. - for (SDNode::use_iterator UI = Flags->use_begin(), UE = Flags->use_end(); - UI != UE; ++UI) { - // Only check things that use the flags. - if (UI.getUse().getResNo() != Flags.getResNo()) - continue; + // Only check things that use the flags. + for (auto UI = Flags->use_per_resno_begin(Flags.getResNo()), + UE = Flags->use_per_resno_end(Flags.getResNo()); + UI != UE; ++UI) { // Only examine CopyToReg uses that copy to EFLAGS. if (UI->getOpcode() != ISD::CopyToReg || cast(UI->getOperand(1))->getReg() != X86::EFLAGS) return false; // Examine each user of the CopyToReg use. - for (SDNode::use_iterator FlagUI = UI->use_begin(), - FlagUE = UI->use_end(); FlagUI != FlagUE; ++FlagUI) { - // Only examine the Flag result. - if (FlagUI.getUse().getResNo() != 1) continue; + // Only examine the Flag result. + for (auto FlagUI = UI->use_per_resno_begin(1), + FlagUE = UI->use_per_resno_end(1); + FlagUI != FlagUE; ++FlagUI) { // Anything unusual: assume conservatively. if (!FlagUI->isMachineOpcode()) return false; // Examine the condition code of the user. @@ -2989,20 +2988,19 @@ /// flag to be accurate. bool X86DAGToDAGISel::hasNoSignFlagUses(SDValue Flags) const { // Examine each user of the node. - for (SDNode::use_iterator UI = Flags->use_begin(), UE = Flags->use_end(); - UI != UE; ++UI) { - // Only check things that use the flags. - if (UI.getUse().getResNo() != Flags.getResNo()) - continue; + // Only check things that use the flags. + for (auto UI = Flags->use_per_resno_begin(Flags.getResNo()), + UE = Flags->use_per_resno_end(Flags.getResNo()); + UI != UE; ++UI) { // Only examine CopyToReg uses that copy to EFLAGS. if (UI->getOpcode() != ISD::CopyToReg || cast(UI->getOperand(1))->getReg() != X86::EFLAGS) return false; // Examine each user of the CopyToReg use. - for (SDNode::use_iterator FlagUI = UI->use_begin(), - FlagUE = UI->use_end(); FlagUI != FlagUE; ++FlagUI) { - // Only examine the Flag result. - if (FlagUI.getUse().getResNo() != 1) continue; + // Only examine the Flag result. + for (auto FlagUI = UI->use_per_resno_begin(1), + FlagUE = UI->use_per_resno_end(1); + FlagUI != FlagUE; ++FlagUI) { // Anything unusual: assume conservatively. if (!FlagUI->isMachineOpcode()) return false; // Examine the condition code of the user. @@ -3043,26 +3041,24 @@ /// Test whether the given node which sets flags has any uses which require the /// CF flag to be accurate. - bool X86DAGToDAGISel::hasNoCarryFlagUses(SDValue Flags) const { +bool X86DAGToDAGISel::hasNoCarryFlagUses(SDValue Flags) const { // Examine each user of the node. - for (SDNode::use_iterator UI = Flags->use_begin(), UE = Flags->use_end(); - UI != UE; ++UI) { - // Only check things that use the flags. - if (UI.getUse().getResNo() != Flags.getResNo()) - continue; - + // Only check things that use the flags. + for (auto UI = Flags->use_per_resno_begin(Flags.getResNo()), + UE = Flags->use_per_resno_end(Flags.getResNo()); + UI != UE; ++UI) { unsigned UIOpc = UI->getOpcode(); if (UIOpc == ISD::CopyToReg) { // Only examine CopyToReg uses that copy to EFLAGS. if (cast(UI->getOperand(1))->getReg() != X86::EFLAGS) return false; + // Examine each user of the CopyToReg use. - for (SDNode::use_iterator FlagUI = UI->use_begin(), FlagUE = UI->use_end(); + // Only examine the Flag result. + for (auto FlagUI = UI->use_per_resno_begin(1), + FlagUE = UI->use_per_resno_end(1); FlagUI != FlagUE; ++FlagUI) { - // Only examine the Flag result. - if (FlagUI.getUse().getResNo() != 1) - continue; // Anything unusual: assume conservatively. if (!FlagUI->isMachineOpcode()) return false; Index: llvm/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm/lib/Target/X86/X86ISelLowering.cpp +++ llvm/lib/Target/X86/X86ISelLowering.cpp @@ -5536,11 +5536,10 @@ // can be store-folded. Therefore, it's probably not worth splitting the load. EVT VT = Load->getValueType(0); if ((VT.is256BitVector() || VT.is512BitVector()) && !Load->hasOneUse()) { - for (auto UI = Load->use_begin(), UE = Load->use_end(); UI != UE; ++UI) { - // Skip uses of the chain value. Result 0 of the node is the load value. - if (UI.getUse().getResNo() != 0) - continue; - + // Skip uses of the chain value. Result 0 of the node is the load value. + for (auto UI = Load->use_per_resno_begin(0), + UE = Load->use_per_resno_end(0); + UI != UE; ++UI) { // If this use is not an extract + store, it's probably worth splitting. if (UI->getOpcode() != ISD::EXTRACT_SUBVECTOR || !UI->hasOneUse() || UI->use_begin()->getOpcode() != ISD::STORE)