From 4abaebae0c72cb7ae06d71f6e53bd4272280ce95 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Mon, 26 Jan 2009 04:35:06 +0000 Subject: [PATCH] Take the next steps in making SDUse more consistent with LLVM Use, and tidy up SDUse and related code. - Replace the operator= member functions with a set method, like LLVM Use has, and variants setInitial and setNode, which take care up updating use lists, like LLVM Use's does. This simplifies code that calls these functions. - getSDValue() is renamed to get(), as in LLVM Use, though most places can either use the implicit conversion to SDValue or the convenience functions instead. - Fix some more node vs. value terminology issues. Also, eliminate the one remaining use of SDOperandPtr, and SDOperandPtr itself. llvm-svn: 62995 --- include/llvm/CodeGen/SelectionDAGNodes.h | 349 ++++++++++----------- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2 +- lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 2 +- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 143 ++++----- lib/Target/X86/X86ISelLowering.cpp | 18 +- 5 files changed, 243 insertions(+), 271 deletions(-) diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index a429855a9d2..7a5cd3b43ee 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -955,63 +955,77 @@ template<> struct simplify_type { } }; -/// SDUse - Represents a use of the SDNode referred by -/// the SDValue. +/// SDUse - Represents a use of a SDNode. This class holds an SDValue, +/// which records the SDNode being used and the result number, a +/// pointer to the SDNode using the value, and Next and Prev pointers, +/// which link together all the uses of an SDNode. +/// class SDUse { - SDValue Operand; - /// User - Parent node of this operand. - SDNode *User; - /// Prev, next - Pointers to the uses list of the SDNode referred by + /// Val - The value being used. + SDValue Val; + /// User - The user of this value. + SDNode *User; + /// Prev, Next - Pointers to the uses list of the SDNode referred by /// this operand. SDUse **Prev, *Next; + + SDUse(const SDUse &U); // Do not implement + void operator=(const SDUse &U); // Do not implement + public: - friend class SDNode; - SDUse(): Operand(), User(NULL), Prev(NULL), Next(NULL) {} + SDUse() : Val(), User(NULL), Prev(NULL), Next(NULL) {} - SDUse(SDNode *val, unsigned resno) : - Operand(val,resno), User(NULL), Prev(NULL), Next(NULL) {} - - SDUse& operator= (const SDValue& Op) { - Operand = Op; - Next = NULL; - Prev = NULL; - return *this; - } - - SDUse& operator= (const SDUse& Op) { - Operand = Op; - Next = NULL; - Prev = NULL; - return *this; - } - - SDUse *getNext() { return Next; } + /// Normally SDUse will just implicitly convert to an SDValue that it holds. + operator const SDValue&() const { return Val; } + /// If implicit conversion to SDValue doesn't work, the get() method returns + /// the SDValue. + const SDValue &get() const { return Val; } + + /// getUser - This returns the SDNode that contains this Use. SDNode *getUser() { return User; } + /// getNext - Get the next SDUse in the use list. + SDUse *getNext() const { return Next; } + + /// getNode - Convenience function for get().getNode(). + SDNode *getNode() const { return Val.getNode(); } + /// getResNo - Convenience function for get().getResNo(). + unsigned getResNo() const { return Val.getResNo(); } + /// getValueType - Convenience function for get().getValueType(). + MVT getValueType() const { return Val.getValueType(); } + + /// operator== - Convenience function for get().operator== + bool operator==(const SDValue &V) const { + return Val == V; + } + + /// operator!= - Convenience function for get().operator!= + bool operator!=(const SDValue &V) const { + return Val != V; + } + + /// operator< - Convenience function for get().operator< + bool operator<(const SDValue &V) const { + return Val < V; + } + +private: + friend class SelectionDAG; + friend class SDNode; + void setUser(SDNode *p) { User = p; } - operator SDValue() const { return Operand; } + /// set - Remove this use from its existing use list, assign it the + /// given value, and add it to the new value's node's use list. + inline void set(const SDValue &V); + /// setInitial - like set, but only supports initializing a newly-allocated + /// SDUse with a non-null value. + inline void setInitial(const SDValue &V); + /// setNode - like set, but only sets the Node portion of the value, + /// leaving the ResNo portion unmodified. + inline void setNode(SDNode *N); - const SDValue& getSDValue() const { return Operand; } - - SDValue &getSDValue() { return Operand; } - SDNode *getVal() { return Operand.getNode(); } - SDNode *getVal() const { return Operand.getNode(); } // FIXME: const correct? - - bool operator==(const SDValue &O) const { - return Operand == O; - } - - bool operator!=(const SDValue &O) const { - return !(Operand == O); - } - - bool operator<(const SDValue &O) const { - return Operand < O; - } - -protected: void addToList(SDUse **List) { Next = *List; if (Next) Next->Prev = &Next; @@ -1025,61 +1039,22 @@ protected: } }; - /// simplify_type specializations - Allow casting operators to work directly on /// SDValues as if they were SDNode*'s. template<> struct simplify_type { typedef SDNode* SimpleType; static SimpleType getSimplifiedValue(const SDUse &Val) { - return static_cast(Val.getVal()); + return static_cast(Val.getNode()); } }; template<> struct simplify_type { typedef SDNode* SimpleType; static SimpleType getSimplifiedValue(const SDUse &Val) { - return static_cast(Val.getVal()); + return static_cast(Val.getNode()); } }; -/// SDOperandPtr - A helper SDValue pointer class, that can handle -/// arrays of SDUse and arrays of SDValue objects. This is required -/// in many places inside the SelectionDAG. -/// -class SDOperandPtr { - const SDValue *ptr; // The pointer to the SDValue object - int object_size; // The size of the object containg the SDValue -public: - SDOperandPtr() : ptr(0), object_size(0) {} - - SDOperandPtr(SDUse * use_ptr) { - ptr = &use_ptr->getSDValue(); - object_size = (int)sizeof(SDUse); - } - - SDOperandPtr(const SDValue * op_ptr) { - ptr = op_ptr; - object_size = (int)sizeof(SDValue); - } - - const SDValue operator *() { return *ptr; } - const SDValue *operator ->() { return ptr; } - SDOperandPtr operator ++ () { - ptr = (SDValue*)((char *)ptr + object_size); - return *this; - } - - SDOperandPtr operator ++ (int) { - SDOperandPtr tmp = *this; - ptr = (SDValue*)((char *)ptr + object_size); - return tmp; - } - - SDValue operator[] (int idx) const { - return *(SDValue*)((char*) ptr + object_size * idx); - } -}; - /// SDNode - Represents one node in the SelectionDAG. /// class SDNode : public FoldingSetNode, public ilist_node { @@ -1113,11 +1088,14 @@ private: /// NumOperands/NumValues - The number of entries in the Operand/Value list. unsigned short NumOperands, NumValues; - /// Uses - List of uses for this SDNode. - SDUse *Uses; + /// UseList - List of uses for this SDNode. + SDUse *UseList; - /// addUse - add SDUse to the list of uses. - void addUse(SDUse &U) { U.addToList(&Uses); } + /// getValueTypeList - Return a pointer to the specified value type. + static const MVT *getValueTypeList(MVT VT); + + friend class SelectionDAG; + friend struct ilist_traits; public: //===--------------------------------------------------------------------===// @@ -1148,7 +1126,7 @@ public: /// use_empty - Return true if there are no uses of this node. /// - bool use_empty() const { return Uses == NULL; } + bool use_empty() const { return UseList == NULL; } /// hasOneUse - Return true if there is exactly one use of this node. /// @@ -1226,7 +1204,7 @@ public: /// of an SDNode. use_iterator use_begin() const { - return use_iterator(Uses); + return use_iterator(UseList); } static use_iterator use_end() { return use_iterator(0); } @@ -1265,14 +1243,13 @@ public: const SDValue &getOperand(unsigned Num) const { assert(Num < NumOperands && "Invalid child # of SDNode!"); - return OperandList[Num].getSDValue(); + return OperandList[Num]; } typedef SDUse* op_iterator; op_iterator op_begin() const { return OperandList; } op_iterator op_end() const { return OperandList+NumOperands; } - SDVTList getVTList() const { SDVTList X = { ValueList, NumValues }; return X; @@ -1339,13 +1316,11 @@ public: /// void Profile(FoldingSetNodeID &ID) const; -protected: - friend class SelectionDAG; - friend struct ilist_traits; - - /// getValueTypeList - Return a pointer to the specified value type. + /// addUse - This method should only be used by the SDUse class. /// - static const MVT *getValueTypeList(MVT VT); + void addUse(SDUse &U) { U.addToList(&UseList); } + +protected: static SDVTList getSDVTList(MVT VT) { SDVTList Ret = { getValueTypeList(VT), 1 }; return Ret; @@ -1353,77 +1328,84 @@ protected: SDNode(unsigned Opc, SDVTList VTs, const SDValue *Ops, unsigned NumOps) : NodeType(Opc), OperandsNeedDelete(true), SubclassData(0), - NodeId(-1), Uses(NULL) { - NumOperands = NumOps; - OperandList = NumOps ? new SDUse[NumOperands] : 0; - + NodeId(-1), + OperandList(NumOps ? new SDUse[NumOps] : 0), + ValueList(VTs.VTs), + NumOperands(NumOps), NumValues(VTs.NumVTs), + UseList(NULL) { for (unsigned i = 0; i != NumOps; ++i) { - OperandList[i] = Ops[i]; OperandList[i].setUser(this); - Ops[i].getNode()->addUse(OperandList[i]); + OperandList[i].setInitial(Ops[i]); } - - ValueList = VTs.VTs; - NumValues = VTs.NumVTs; - } - - SDNode(unsigned Opc, SDVTList VTs, const SDUse *Ops, unsigned NumOps) - : NodeType(Opc), OperandsNeedDelete(true), SubclassData(0), - NodeId(-1), Uses(NULL) { - OperandsNeedDelete = true; - NumOperands = NumOps; - OperandList = NumOps ? new SDUse[NumOperands] : 0; - - for (unsigned i = 0; i != NumOps; ++i) { - OperandList[i] = Ops[i]; - OperandList[i].setUser(this); - Ops[i].getVal()->addUse(OperandList[i]); - } - - ValueList = VTs.VTs; - NumValues = VTs.NumVTs; } /// This constructor adds no operands itself; operands can be /// set later with InitOperands. SDNode(unsigned Opc, SDVTList VTs) : NodeType(Opc), OperandsNeedDelete(false), SubclassData(0), - NodeId(-1), Uses(NULL) { - NumOperands = 0; - OperandList = 0; - ValueList = VTs.VTs; - NumValues = VTs.NumVTs; - } + NodeId(-1), OperandList(0), ValueList(VTs.VTs), + NumOperands(0), NumValues(VTs.NumVTs), + UseList(NULL) {} - /// InitOperands - Initialize the operands list of this node with the - /// specified values, which are part of the node (thus they don't need to be - /// copied in or allocated). - void InitOperands(SDUse *Ops, unsigned NumOps) { - assert(OperandList == 0 && "Operands already set!"); - NumOperands = NumOps; + /// InitOperands - Initialize the operands list of this with 1 operand. + void InitOperands(SDUse *Ops, const SDValue &Op0) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + NumOperands = 1; OperandList = Ops; - Uses = NULL; - - for (unsigned i = 0; i != NumOps; ++i) { - OperandList[i].setUser(this); - Ops[i].getVal()->addUse(OperandList[i]); + } + + /// InitOperands - Initialize the operands list of this with 2 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + NumOperands = 2; + OperandList = Ops; + } + + /// InitOperands - Initialize the operands list of this with 3 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, + const SDValue &Op2) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + Ops[2].setUser(this); + Ops[2].setInitial(Op2); + NumOperands = 3; + OperandList = Ops; + } + + /// InitOperands - Initialize the operands list of this with 4 operands. + void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1, + const SDValue &Op2, const SDValue &Op3) { + Ops[0].setUser(this); + Ops[0].setInitial(Op0); + Ops[1].setUser(this); + Ops[1].setInitial(Op1); + Ops[2].setUser(this); + Ops[2].setInitial(Op2); + Ops[3].setUser(this); + Ops[3].setInitial(Op3); + NumOperands = 4; + OperandList = Ops; + } + + /// InitOperands - Initialize the operands list of this with N operands. + void InitOperands(SDUse *Ops, const SDValue *Vals, unsigned N) { + for (unsigned i = 0; i != N; ++i) { + Ops[i].setUser(this); + Ops[i].setInitial(Vals[i]); } + NumOperands = N; + OperandList = Ops; } /// DropOperands - Release the operands and set this node to have /// zero operands. void DropOperands(); - - void addUser(unsigned i, SDNode *User) { - assert(User->OperandList[i].getUser() && "Node without parent"); - addUse(User->OperandList[i]); - } - - void removeUser(unsigned i, SDNode *User) { - assert(User->OperandList[i].getUser() && "Node without parent"); - SDUse &Op = User->OperandList[i]; - Op.removeFromList(); - } }; @@ -1460,6 +1442,25 @@ inline bool SDValue::hasOneUse() const { return Node->hasNUsesOfValue(1, ResNo); } +// Define inline functions from the SDUse class. + +inline void SDUse::set(const SDValue &V) { + if (Val.getNode()) removeFromList(); + Val = V; + if (V.getNode()) V.getNode()->addUse(*this); +} + +inline void SDUse::setInitial(const SDValue &V) { + Val = V; + V.getNode()->addUse(*this); +} + +inline void SDUse::setNode(SDNode *N) { + if (Val.getNode()) removeFromList(); + Val.setNode(N); + if (N) N->addUse(*this); +} + /// UnarySDNode - This class is used for single-operand SDNodes. This is solely /// to allow co-allocation of node operands with the node itself. class UnarySDNode : public SDNode { @@ -1467,8 +1468,7 @@ class UnarySDNode : public SDNode { public: UnarySDNode(unsigned Opc, SDVTList VTs, SDValue X) : SDNode(Opc, VTs) { - Op = X; - InitOperands(&Op, 1); + InitOperands(&Op, X); } }; @@ -1479,9 +1479,7 @@ class BinarySDNode : public SDNode { public: BinarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y) : SDNode(Opc, VTs) { - Ops[0] = X; - Ops[1] = Y; - InitOperands(Ops, 2); + InitOperands(Ops, X, Y); } }; @@ -1493,10 +1491,7 @@ public: TernarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y, SDValue Z) : SDNode(Opc, VTs) { - Ops[0] = X; - Ops[1] = Y; - Ops[2] = Z; - InitOperands(Ops, 3); + InitOperands(Ops, X, Y, Z); } }; @@ -1516,11 +1511,10 @@ public: explicit HandleSDNode(SDValue X) #endif : SDNode(ISD::HANDLENODE, getSDVTList(MVT::Other)) { - Op = X; - InitOperands(&Op, 1); + InitOperands(&Op, X); } ~HandleSDNode(); - const SDValue &getValue() const { return Op.getSDValue(); } + const SDValue &getValue() const { return Op; } }; /// Abstact virtual class for operations for memory operations @@ -1617,21 +1611,14 @@ public: unsigned Align=0) : MemSDNode(Opc, VTL, MemVT, SrcVal, /*SVOffset=*/0, Align, /*isVolatile=*/true) { - Ops[0] = Chain; - Ops[1] = Ptr; - Ops[2] = Cmp; - Ops[3] = Swp; - InitOperands(Ops, 4); + InitOperands(Ops, Chain, Ptr, Cmp, Swp); } AtomicSDNode(unsigned Opc, SDVTList VTL, MVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value* SrcVal, unsigned Align=0) : MemSDNode(Opc, VTL, MemVT, SrcVal, /*SVOffset=*/0, Align, /*isVolatile=*/true) { - Ops[0] = Chain; - Ops[1] = Ptr; - Ops[2] = Val; - InitOperands(Ops, 3); + InitOperands(Ops, Chain, Ptr, Val); } const SDValue &getBasePtr() const { return getOperand(1); } @@ -1979,8 +1966,7 @@ protected: Value *cu) : SDNode(ISD::DBG_STOPPOINT, getSDVTList(MVT::Other)), Line(l), Column(c), CU(cu) { - Chain = ch; - InitOperands(&Chain, 1); + InitOperands(&Chain, ch); } public: unsigned getLine() const { return Line; } @@ -2000,8 +1986,7 @@ protected: friend class SelectionDAG; LabelSDNode(unsigned NodeTy, SDValue ch, unsigned id) : SDNode(NodeTy, getSDVTList(MVT::Other)), LabelID(id) { - Chain = ch; - InitOperands(&Chain, 1); + InitOperands(&Chain, ch); } public: unsigned getLabelID() const { return LabelID; } @@ -2256,9 +2241,7 @@ public: const Value *SV, int SVO, unsigned Align, bool Vol) : MemSDNode(NodeTy, VTs, VT, SV, SVO, Align, Vol) { SubclassData = AM; - for (unsigned i = 0; i != numOperands; ++i) - Ops[i] = Operands[i]; - InitOperands(Ops, numOperands); + InitOperands(Ops, Operands, numOperands); assert(Align != 0 && "Loads and stores should have non-zero aligment"); assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) && "Only indexed loads and stores have a non-undef offset operand"); diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index e4b24f1aaff..d1759c1ab0e 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -4138,7 +4138,7 @@ SDValue DAGCombiner::visitFP_EXTEND(SDNode *N) { // If this is fp_round(fpextend), don't fold it, allow ourselves to be folded. if (N->hasOneUse() && - N->use_begin().getUse().getSDValue().getOpcode() == ISD::FP_ROUND) + N->use_begin()->getOpcode() == ISD::FP_ROUND) return SDValue(); // fold (fp_extend c1fp) -> c1fp diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index a4f3917b18a..4c5dd030c7a 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -81,7 +81,7 @@ void DAGTypeLegalizer::PerformExpensiveChecks() { // Check that remapped values are only used by nodes marked NewNode. for (SDNode::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; ++UI) - if (UI.getUse().getSDValue().getResNo() == i) + if (UI.getUse().getResNo() == i) assert(UI->getNodeId() == NewNode && "Remapped value has non-trivial use!"); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index ab222c4f2fa..7fd50aca401 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -342,8 +342,8 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID, static void AddNodeIDOperands(FoldingSetNodeID &ID, const SDUse *Ops, unsigned NumOps) { for (; NumOps; --NumOps, ++Ops) { - ID.AddPointer(Ops->getVal()); - ID.AddInteger(Ops->getSDValue().getResNo()); + ID.AddPointer(Ops->getNode()); + ID.AddInteger(Ops->getResNo()); } } @@ -538,8 +538,7 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl &DeadNodes, // Process the worklist, deleting the nodes and adding their uses to the // worklist. while (!DeadNodes.empty()) { - SDNode *N = DeadNodes.back(); - DeadNodes.pop_back(); + SDNode *N = DeadNodes.pop_back_val(); if (UpdateListener) UpdateListener->NodeDeleted(N, 0); @@ -549,10 +548,11 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl &DeadNodes, // Next, brutally remove the operand list. This is safe to do, as there are // no cycles in the graph. - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) { - SDNode *Operand = I->getVal(); - Operand->removeUser(std::distance(N->op_begin(), I), N); - + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Operand = Use.getNode(); + Use.set(SDValue()); + // Now that we removed this operand, see if there are no uses of it left. if (Operand->use_empty()) DeadNodes.push_back(Operand); @@ -581,8 +581,7 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) { assert(N->use_empty() && "Cannot delete a node that is not dead!"); // Drop all of the operands and decrement used node's use counts. - for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) - I->getVal()->removeUser(std::distance(N->op_begin(), I), N); + N->DropOperands(); DeallocateNode(N); } @@ -763,7 +762,7 @@ void SelectionDAG::VerifyNode(SDNode *N) { // following checks at least makes it possible to legalize most of the time. // MVT EltVT = N->getValueType(0).getVectorElementType(); // for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) -// assert(I->getSDValue().getValueType() == EltVT && +// assert(I->getValueType() == EltVT && // "Wrong operand type!"); break; } @@ -819,7 +818,7 @@ void SelectionDAG::clear() { std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(), static_cast(0)); - EntryNode.Uses = 0; + EntryNode.UseList = 0; AllNodes.push_back(&EntryNode); Root = getEntryNode(); } @@ -3915,9 +3914,7 @@ SDValue SelectionDAG::UpdateNodeOperands(SDValue InN, SDValue Op) { InsertPos = 0; // Now we update the operands. - N->OperandList[0].getVal()->removeUser(0, N); - N->OperandList[0].getSDValue() = Op; - Op.getNode()->addUser(0, N); + N->OperandList[0].set(Op); // If this gets put into a CSE map, add it. if (InsertPos) CSEMap.InsertNode(N, InsertPos); @@ -3944,16 +3941,10 @@ UpdateNodeOperands(SDValue InN, SDValue Op1, SDValue Op2) { InsertPos = 0; // Now we update the operands. - if (N->OperandList[0] != Op1) { - N->OperandList[0].getVal()->removeUser(0, N); - N->OperandList[0].getSDValue() = Op1; - Op1.getNode()->addUser(0, N); - } - if (N->OperandList[1] != Op2) { - N->OperandList[1].getVal()->removeUser(1, N); - N->OperandList[1].getSDValue() = Op2; - Op2.getNode()->addUser(1, N); - } + if (N->OperandList[0] != Op1) + N->OperandList[0].set(Op1); + if (N->OperandList[1] != Op2) + N->OperandList[1].set(Op2); // If this gets put into a CSE map, add it. if (InsertPos) CSEMap.InsertNode(N, InsertPos); @@ -4009,13 +4000,9 @@ UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) { InsertPos = 0; // Now we update the operands. - for (unsigned i = 0; i != NumOps; ++i) { - if (N->OperandList[i] != Ops[i]) { - N->OperandList[i].getVal()->removeUser(i, N); - N->OperandList[i].getSDValue() = Ops[i]; - Ops[i].getNode()->addUser(i, N); - } - } + for (unsigned i = 0; i != NumOps; ++i) + if (N->OperandList[i] != Ops[i]) + N->OperandList[i].set(Ops[i]); // If this gets put into a CSE map, add it. if (InsertPos) CSEMap.InsertNode(N, InsertPos); @@ -4027,10 +4014,10 @@ UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) { void SDNode::DropOperands() { // Unlike the code in MorphNodeTo that does this, we don't need to // watch for dead nodes here. - for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) - I->getVal()->removeUser(std::distance(op_begin(), I), this); - - NumOperands = 0; + for (op_iterator I = op_begin(), E = op_end(); I != E; ) { + SDUse &Use = *I++; + Use.set(SDValue()); + } } /// SelectNodeTo - These are wrappers around MorphNodeTo that accept a @@ -4255,10 +4242,10 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, // 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. SmallPtrSet DeadNodeSet; - for (SDNode::op_iterator B = N->op_begin(), I = B, E = N->op_end(); - I != E; ++I) { - SDNode *Used = I->getVal(); - Used->removeUser(std::distance(B, I), N); + for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) { + SDUse &Use = *I++; + SDNode *Used = Use.getNode(); + Use.set(SDValue()); if (Used->use_empty()) DeadNodeSet.insert(Used); } @@ -4284,10 +4271,8 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, // Assign the new operands. N->NumOperands = NumOps; for (unsigned i = 0, e = NumOps; i != e; ++i) { - N->OperandList[i].getSDValue() = Ops[i]; N->OperandList[i].setUser(N); - SDNode *ToUse = N->OperandList[i].getVal(); - ToUse->addUser(i, N); + N->OperandList[i].setInitial(Ops[i]); } // Delete any nodes that are still dead after adding the uses for the @@ -4441,11 +4426,9 @@ 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 { - unsigned operandNum = UI.getOperandNo(); + SDUse &Use = UI.getUse(); ++UI; - From->removeUser(operandNum, User); - User->OperandList[operandNum].getSDValue() = To; - To.getNode()->addUser(operandNum, User); + Use.set(To); } while (UI != UE && *UI == User); // Now that we have modified User, add it back to the CSE maps. If it @@ -4484,11 +4467,9 @@ 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 { - unsigned operandNum = UI.getOperandNo(); + SDUse &Use = UI.getUse(); ++UI; - From->removeUser(operandNum, User); - User->OperandList[operandNum].getSDValue().setNode(To); - To->addUser(operandNum, User); + Use.setNode(To); } while (UI != UE && *UI == User); // Now that we have modified User, add it back to the CSE maps. If it @@ -4522,13 +4503,10 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, // To help reduce the number of CSE recomputations, process all // the uses of this user that we can find this way. do { - unsigned operandNum = UI.getOperandNo(); - const SDValue &ToOp = - To[User->OperandList[operandNum].getSDValue().getResNo()]; + SDUse &Use = UI.getUse(); + const SDValue &ToOp = To[Use.getResNo()]; ++UI; - From->removeUser(operandNum, User); - User->OperandList[operandNum].getSDValue() = ToOp; - ToOp.getNode()->addUser(operandNum, User); + Use.set(ToOp); } while (UI != UE && *UI == User); // Now that we have modified User, add it back to the CSE maps. If it @@ -4538,8 +4516,8 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, } /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving -/// uses of other values produced by From.getVal() alone. The Deleted vector is -/// handled the same way as for ReplaceAllUsesWith. +/// uses of other values produced by From.getNode() alone. The Deleted +/// vector is handled the same way as for ReplaceAllUsesWith. void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, DAGUpdateListener *UpdateListener){ // Handle the really simple, really trivial case efficiently. @@ -4564,11 +4542,10 @@ 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 { - unsigned operandNum = UI.getOperandNo(); + SDUse &Use = UI.getUse(); // Skip uses of different values from the same node. - if (User->OperandList[operandNum].getSDValue().getResNo() != - From.getResNo()) { + if (Use.getResNo() != From.getResNo()) { ++UI; continue; } @@ -4581,9 +4558,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To, } ++UI; - From.getNode()->removeUser(operandNum, User); - User->OperandList[operandNum].getSDValue() = To; - To.getNode()->addUser(operandNum, User); + Use.set(To); } while (UI != UE && *UI == User); // We are iterating over all uses of the From node, so if a use @@ -4603,13 +4578,18 @@ namespace { struct UseMemo { SDNode *User; unsigned Index; - unsigned operandNum; + SDUse *Use; }; + + /// operator< - Sort Memos by User. + bool operator<(const UseMemo &L, const UseMemo &R) { + return (intptr_t)L.User < (intptr_t)R.User; + } } /// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving -/// uses of other values produced by From.getVal() alone. The same value may -/// appear in both the From and To list. The Deleted vector is +/// uses of other values produced by From.getNode() alone. The same value +/// may appear in both the From and To list. The Deleted vector is /// handled the same way as for ReplaceAllUsesWith. void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, @@ -4627,13 +4607,18 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, 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) - if (UI.getUse().getSDValue().getResNo() == FromResNo) { - UseMemo Memo = { *UI, i, UI.getOperandNo() }; + E = FromNode->use_end(); UI != E; ++UI) { + SDUse &Use = UI.getUse(); + if (Use.getResNo() == FromResNo) { + UseMemo Memo = { *UI, i, &Use }; Uses.push_back(Memo); } + } } + // Sort the uses, so that all the uses from a given User are together. + std::sort(Uses.begin(), Uses.end()); + for (unsigned UseIndex = 0, UseIndexEnd = Uses.size(); UseIndex != UseIndexEnd; ) { // We know that this user uses some value of From. If it is the right @@ -4643,18 +4628,16 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From, // This node is about to morph, remove its old self from the CSE maps. RemoveNodeFromCSEMaps(User); - // A user can appear in a use list multiple times, and when this - // happens the uses are usually next to each other in the list. + // The Uses array is sorted, so all the uses for a given User + // are next to each other in the list. // To help reduce the number of CSE recomputations, process all // the uses of this user that we can find this way. do { unsigned i = Uses[UseIndex].Index; - unsigned operandNum = Uses[UseIndex].operandNum; + SDUse &Use = *Uses[UseIndex].Use; ++UseIndex; - From[i].getNode()->removeUser(operandNum, User); - User->OperandList[operandNum].getSDValue() = To[i]; - To[i].getNode()->addUser(operandNum, User); + Use.set(To[i]); } while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User); // Now that we have modified User, add it back to the CSE maps. If it @@ -4839,7 +4822,7 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const { // 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().getSDValue().getResNo() == Value) { + if (UI.getUse().getResNo() == Value) { if (NUses == 0) return false; --NUses; @@ -4857,7 +4840,7 @@ 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().getSDValue().getResNo() == Value) + if (UI.getUse().getResNo() == Value) return true; return false; @@ -4890,7 +4873,7 @@ bool SDValue::isOperandOf(SDNode *N) const { bool SDNode::isOperandOf(SDNode *N) const { for (unsigned i = 0, e = N->NumOperands; i != e; ++i) - if (this == N->OperandList[i].getVal()) + if (this == N->OperandList[i].getNode()) return true; return false; } diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 205a141623a..406b2370b1c 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2160,7 +2160,8 @@ bool X86::isPSHUFLWMask(SDNode *N) { /// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to SHUFP*. -static bool isSHUFPMask(SDOperandPtr Elems, unsigned NumElems) { +template +static bool isSHUFPMask(SDOperand *Elems, unsigned NumElems) { if (NumElems != 2 && NumElems != 4) return false; unsigned Half = NumElems / 2; @@ -2183,7 +2184,8 @@ bool X86::isSHUFPMask(SDNode *N) { /// the reverse of what x86 shuffles want. x86 shuffles requires the lower /// half elements to come from vector 1 (which would equal the dest.) and /// the upper half to come from vector 2. -static bool isCommutedSHUFP(SDOperandPtr Ops, unsigned NumOps) { +template +static bool isCommutedSHUFP(SDOperand *Ops, unsigned NumOps) { if (NumOps != 2 && NumOps != 4) return false; unsigned Half = NumOps / 2; @@ -2277,7 +2279,8 @@ bool X86::isMOVHPMask(SDNode *N) { /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKL. -bool static isUNPCKLMask(SDOperandPtr Elts, unsigned NumElts, +template +bool static isUNPCKLMask(SDOperand *Elts, unsigned NumElts, bool V2IsSplat = false) { if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) return false; @@ -2306,7 +2309,8 @@ bool X86::isUNPCKLMask(SDNode *N, bool V2IsSplat) { /// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKH. -bool static isUNPCKHMask(SDOperandPtr Elts, unsigned NumElts, +template +bool static isUNPCKHMask(SDOperand *Elts, unsigned NumElts, bool V2IsSplat = false) { if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) return false; @@ -2382,7 +2386,8 @@ bool X86::isUNPCKH_v_undef_Mask(SDNode *N) { /// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSS, /// MOVSD, and MOVD, i.e. setting the lowest element. -static bool isMOVLMask(SDOperandPtr Elts, unsigned NumElts) { +template +static bool isMOVLMask(SDOperand *Elts, unsigned NumElts) { if (NumElts != 2 && NumElts != 4) return false; @@ -2405,7 +2410,8 @@ bool X86::isMOVLMask(SDNode *N) { /// isCommutedMOVL - Returns true if the shuffle mask is except the reverse /// of what x86 movss want. X86 movs requires the lowest element to be lowest /// element of vector 2 and the other elements to come from vector 1 in order. -static bool isCommutedMOVL(SDOperandPtr Ops, unsigned NumOps, +template +static bool isCommutedMOVL(SDOperand *Ops, unsigned NumOps, bool V2IsSplat = false, bool V2IsUndef = false) { if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16)