Use a linked data structure for the uses lists of an SDNode, just like

LLVM Value/Use does and MachineRegisterInfo/MachineOperand does.
This allows constant time for all uses list maintenance operations.

The idea was suggested by Chris. Reviewed by Evan and Dan.
Patch is tested and approved by Dan.

On normal use-cases compilation speed is not affected. On very big basic
blocks there are compilation speedups in the range of 15-20% or even better. 



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48822 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Roman Levenstein 2008-03-26 12:39:26 +00:00
parent 8dba9afd08
commit e326332acd
11 changed files with 371 additions and 177 deletions

View File

@ -331,7 +331,7 @@ namespace llvm {
/// register number for the results of the node.
///
void EmitNode(SDNode *Node, unsigned InstNo,
DenseMap<SDOperand, unsigned> &VRBaseMap);
DenseMap<SDOperandImpl, unsigned> &VRBaseMap);
/// EmitNoop - Emit a noop instruction.
///
@ -343,11 +343,11 @@ namespace llvm {
/// implicit physical register output.
void EmitCopyFromReg(SDNode *Node, unsigned ResNo, unsigned InstNo,
unsigned SrcReg,
DenseMap<SDOperand, unsigned> &VRBaseMap);
DenseMap<SDOperandImpl, unsigned> &VRBaseMap);
void CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
const TargetInstrDesc &II,
DenseMap<SDOperand, unsigned> &VRBaseMap);
DenseMap<SDOperandImpl, unsigned> &VRBaseMap);
/// EmitLiveInCopy - Emit a copy for a live in physical register. If the
/// physical register has only a single copy use, then coalesced the copy
@ -375,11 +375,11 @@ namespace llvm {
/// EmitSubregNode - Generate machine code for subreg nodes.
///
void EmitSubregNode(SDNode *Node,
DenseMap<SDOperand, unsigned> &VRBaseMap);
DenseMap<SDOperandImpl, unsigned> &VRBaseMap);
void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum,
const TargetInstrDesc *II,
DenseMap<SDOperand, unsigned> &VRBaseMap);
DenseMap<SDOperandImpl, unsigned> &VRBaseMap);
void AddMemOperand(MachineInstr *MI, const MemOperand &MO);
};

View File

@ -779,7 +779,7 @@ namespace ISD {
//===----------------------------------------------------------------------===//
/// SDOperand - Unlike LLVM values, Selection DAG nodes may return multiple
/// SDOperandImpl - Unlike LLVM values, Selection DAG nodes may return multiple
/// values as the result of a computation. Many nodes return multiple values,
/// from loads (which define a token and a return value) to ADDC (which returns
/// a result and a carry value), to calls (which may return an arbitrary number
@ -787,28 +787,28 @@ namespace ISD {
///
/// As such, each use of a SelectionDAG computation must indicate the node that
/// computes it as well as which return value to use from that node. This pair
/// of information is represented with the SDOperand value type.
/// of information is represented with the SDOperandImpl value type.
///
class SDOperand {
class SDOperandImpl {
public:
SDNode *Val; // The node defining the value we are using.
unsigned ResNo; // Which return value of the node we are using.
SDOperand() : Val(0), ResNo(0) {}
SDOperand(SDNode *val, unsigned resno) : Val(val), ResNo(resno) {}
SDOperandImpl() : Val(0), ResNo(0) {}
SDOperandImpl(SDNode *val, unsigned resno) : Val(val), ResNo(resno) {}
bool operator==(const SDOperand &O) const {
bool operator==(const SDOperandImpl &O) const {
return Val == O.Val && ResNo == O.ResNo;
}
bool operator!=(const SDOperand &O) const {
bool operator!=(const SDOperandImpl &O) const {
return !operator==(O);
}
bool operator<(const SDOperand &O) const {
bool operator<(const SDOperandImpl &O) const {
return Val < O.Val || (Val == O.Val && ResNo < O.ResNo);
}
SDOperand getValue(unsigned R) const {
return SDOperand(Val, R);
SDOperandImpl getValue(unsigned R) const {
return SDOperandImpl(Val, R);
}
// isOperandOf - Return true if this node is an operand of N.
@ -827,7 +827,7 @@ public:
// Forwarding methods - These forward to the corresponding methods in SDNode.
inline unsigned getOpcode() const;
inline unsigned getNumOperands() const;
inline const SDOperand &getOperand(unsigned i) const;
inline const SDOperandImpl &getOperand(unsigned i) const;
inline uint64_t getConstantOperandVal(unsigned i) const;
inline bool isTargetOpcode() const;
inline unsigned getTargetOpcode() const;
@ -838,7 +838,8 @@ public:
/// side-effecting instructions. In practice, this looks through token
/// factors and non-volatile loads. In order to remain efficient, this only
/// looks a couple of nodes in, it does not do an exhaustive search.
bool reachesChainWithoutSideEffects(SDOperand Dest, unsigned Depth = 2) const;
bool reachesChainWithoutSideEffects(SDOperandImpl Dest,
unsigned Depth = 2) const;
/// hasOneUse - Return true if there is exactly one operation using this
/// result value of the defining operator.
@ -850,19 +851,105 @@ public:
};
template<> struct DenseMapInfo<SDOperand> {
static inline SDOperand getEmptyKey() { return SDOperand((SDNode*)-1, -1U); }
static inline SDOperand getTombstoneKey() { return SDOperand((SDNode*)-1, 0);}
static unsigned getHashValue(const SDOperand &Val) {
template<> struct DenseMapInfo<SDOperandImpl> {
static inline SDOperandImpl getEmptyKey() {
return SDOperandImpl((SDNode*)-1, -1U);
}
static inline SDOperandImpl getTombstoneKey() {
return SDOperandImpl((SDNode*)-1, 0);
}
static unsigned getHashValue(const SDOperandImpl &Val) {
return ((unsigned)((uintptr_t)Val.Val >> 4) ^
(unsigned)((uintptr_t)Val.Val >> 9)) + Val.ResNo;
}
static bool isEqual(const SDOperand &LHS, const SDOperand &RHS) {
static bool isEqual(const SDOperandImpl &LHS, const SDOperandImpl &RHS) {
return LHS == RHS;
}
static bool isPod() { return true; }
};
/// simplify_type specializations - Allow casting operators to work directly on
/// SDOperands as if they were SDNode*'s.
template<> struct simplify_type<SDOperandImpl> {
typedef SDNode* SimpleType;
static SimpleType getSimplifiedValue(const SDOperandImpl &Val) {
return static_cast<SimpleType>(Val.Val);
}
};
template<> struct simplify_type<const SDOperandImpl> {
typedef SDNode* SimpleType;
static SimpleType getSimplifiedValue(const SDOperandImpl &Val) {
return static_cast<SimpleType>(Val.Val);
}
};
/// SDOperand - Represents a use of the SDNode referred by
/// the SDOperandImpl.
class SDOperand: public SDOperandImpl {
/// parent - Parent node of this operand.
SDNode *parent;
/// Prev, next - Pointers to the uses list of the SDNode referred by
/// this operand.
SDOperand **Prev, *Next;
public:
friend class SDNode;
SDOperand(): SDOperandImpl(), parent(NULL), Prev(NULL), Next(NULL) {}
SDOperand(SDNode *val, unsigned resno) :
SDOperandImpl(val,resno), parent(NULL), Prev(NULL), Next(NULL) {}
SDOperand(const SDOperandImpl& Op): SDOperandImpl(Op),parent(NULL),
Prev(NULL), Next(NULL) {
}
SDOperand& operator= (SDOperandImpl& Op) {
*(SDOperandImpl*)this = Op;
Next = NULL;
Prev = NULL;
return *this;
}
SDOperand& operator= (const SDOperandImpl& Op) {
*(SDOperandImpl*)this = Op;
Next = NULL;
Prev = NULL;
return *this;
}
SDOperand& operator= (SDOperand& Op) {
*(SDOperandImpl*)this = Op;
Next = NULL;
Prev = NULL;
return *this;
}
SDOperand& operator= (const SDOperand& Op) {
*(SDOperandImpl*)this = Op;
Next = NULL;
Prev = NULL;
return *this;
}
SDOperand * getNext() { return Next; }
SDNode *getUser() { return parent; }
void setUser(SDNode *p) { parent = p; }
protected:
void addToList(SDOperand **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
/// SDOperands as if they were SDNode*'s.
template<> struct simplify_type<SDOperand> {
@ -882,6 +969,7 @@ template<> struct simplify_type<const SDOperand> {
/// SDNode - Represents one node in the SelectionDAG.
///
class SDNode : public FoldingSetNode {
private:
/// NodeType - The operation that this node performs.
///
unsigned short NodeType;
@ -909,10 +997,15 @@ class SDNode : public FoldingSetNode {
SDNode *Prev, *Next;
friend struct ilist_traits<SDNode>;
/// Uses - These are all of the SDNode's that use a value produced by this
/// node.
SmallVector<SDNode*,3> Uses;
/// UsesSize - The size of the uses list.
unsigned UsesSize;
/// Uses - List of uses for this SDNode.
SDOperand *Uses;
/// addUse - add SDOperand to the list of uses.
void addUse(SDOperand &U) { U.addToList(&Uses); }
// Out-of-line virtual method to give class a home.
virtual void ANCHOR();
public:
@ -931,9 +1024,9 @@ public:
return NodeType - ISD::BUILTIN_OP_END;
}
size_t use_size() const { return Uses.size(); }
bool use_empty() const { return Uses.empty(); }
bool hasOneUse() const { return Uses.size() == 1; }
size_t use_size() const { return UsesSize; }
bool use_empty() const { return Uses == NULL; }
bool hasOneUse() const { return use_size() == 1; }
/// getNodeId - Return the unique node id.
///
@ -942,9 +1035,75 @@ public:
/// setNodeId - Set unique node id.
void setNodeId(int Id) { NodeId = Id; }
typedef SmallVector<SDNode*,3>::const_iterator use_iterator;
use_iterator use_begin() const { return Uses.begin(); }
use_iterator use_end() const { return Uses.end(); }
/// use_iterator - This class provides iterator support for SDOperand
/// operands that use a specific SDNode.
class use_iterator
: public forward_iterator<SDOperand, ptrdiff_t> {
SDOperand *Op;
explicit use_iterator(SDOperand *op) : Op(op) {
}
friend class SDNode;
public:
typedef forward_iterator<SDOperand, ptrdiff_t>::reference reference;
typedef forward_iterator<SDOperand, ptrdiff_t>::pointer pointer;
use_iterator(const use_iterator &I) : Op(I.Op) {}
use_iterator() : Op(0) {}
bool operator==(const use_iterator &x) const {
return Op == x.Op;
}
bool operator!=(const use_iterator &x) const {
return !operator==(x);
}
/// atEnd - return true if this iterator is at the end of uses list.
bool atEnd() const { return Op == 0; }
// Iterator traversal: forward iteration only.
use_iterator &operator++() { // Preincrement
assert(Op && "Cannot increment end iterator!");
Op = Op->getNext();
return *this;
}
use_iterator operator++(int) { // Postincrement
use_iterator tmp = *this; ++*this; return tmp;
}
/// getOperandNum - Retrive a number of a current operand.
unsigned getOperandNum() const {
assert(Op && "Cannot dereference end iterator!");
return (Op - Op->getUser()->OperandList);
}
/// Retrieve a reference to the current operand.
SDOperand &operator*() const {
assert(Op && "Cannot dereference end iterator!");
return *Op;
}
/// Retrieve a pointer to the current operand.
SDOperand *operator->() const {
assert(Op && "Cannot dereference end iterator!");
return Op;
}
};
/// use_begin/use_end - Provide iteration support to walk over all uses
/// of an SDNode.
use_iterator use_begin(SDNode *node) const {
return use_iterator(node->Uses);
}
use_iterator use_begin() const {
return use_iterator(Uses);
}
static use_iterator use_end() { return use_iterator(0); }
/// hasNUsesOfValue - Return true if there are exactly NUSES uses of the
/// indicated value. This method ignores uses of other values defined by this
@ -982,7 +1141,7 @@ public:
return OperandList[Num];
}
typedef const SDOperand* op_iterator;
typedef SDOperand* op_iterator;
op_iterator op_begin() const { return OperandList; }
op_iterator op_end() const { return OperandList+NumOperands; }
@ -1039,25 +1198,28 @@ protected:
}
SDNode(unsigned Opc, SDVTList VTs, const SDOperand *Ops, unsigned NumOps)
: NodeType(Opc), NodeId(-1) {
: NodeType(Opc), NodeId(-1), UsesSize(0), Uses(NULL) {
OperandsNeedDelete = true;
NumOperands = NumOps;
OperandList = NumOps ? new SDOperand[NumOperands] : 0;
for (unsigned i = 0; i != NumOps; ++i) {
OperandList[i] = Ops[i];
Ops[i].Val->Uses.push_back(this);
OperandList[i].setUser(this);
Ops[i].Val->addUse(OperandList[i]);
++Ops[i].Val->UsesSize;
}
ValueList = VTs.VTs;
NumValues = VTs.NumVTs;
Prev = 0; Next = 0;
}
SDNode(unsigned Opc, SDVTList VTs) : NodeType(Opc), NodeId(-1) {
SDNode(unsigned Opc, SDVTList VTs)
: NodeType(Opc), NodeId(-1), UsesSize(0), Uses(NULL) {
OperandsNeedDelete = false; // Operands set with InitOperands.
NumOperands = 0;
OperandList = 0;
ValueList = VTs.VTs;
NumValues = VTs.NumVTs;
Prev = 0; Next = 0;
@ -1070,9 +1232,14 @@ protected:
assert(OperandList == 0 && "Operands already set!");
NumOperands = NumOps;
OperandList = Ops;
UsesSize = 0;
Uses = NULL;
for (unsigned i = 0; i != NumOps; ++i)
Ops[i].Val->Uses.push_back(this);
for (unsigned i = 0; i != NumOps; ++i) {
OperandList[i].setUser(this);
Ops[i].Val->addUse(OperandList[i]);
++Ops[i].Val->UsesSize;
}
}
/// MorphNodeTo - This frees the operands of the current node, resets the
@ -1081,50 +1248,48 @@ protected:
void MorphNodeTo(unsigned Opc, SDVTList L,
const SDOperand *Ops, unsigned NumOps);
void addUser(SDNode *User) {
Uses.push_back(User);
void addUser(unsigned i, SDNode *User) {
assert(User->OperandList[i].getUser() && "Node without parent");
addUse(User->OperandList[i]);
++UsesSize;
}
void removeUser(SDNode *User) {
// Remove this user from the operand's use list.
for (unsigned i = Uses.size(); ; --i) {
assert(i != 0 && "Didn't find user!");
if (Uses[i-1] == User) {
Uses[i-1] = Uses.back();
Uses.pop_back();
return;
}
}
void removeUser(unsigned i, SDNode *User) {
assert(User->OperandList[i].getUser() && "Node without parent");
SDOperand &Op = User->OperandList[i];
Op.removeFromList();
--UsesSize;
}
};
// Define inline functions from the SDOperand class.
// Define inline functions from the SDOperandImpl class.
inline unsigned SDOperand::getOpcode() const {
inline unsigned SDOperandImpl::getOpcode() const {
return Val->getOpcode();
}
inline MVT::ValueType SDOperand::getValueType() const {
inline MVT::ValueType SDOperandImpl::getValueType() const {
return Val->getValueType(ResNo);
}
inline unsigned SDOperand::getNumOperands() const {
inline unsigned SDOperandImpl::getNumOperands() const {
return Val->getNumOperands();
}
inline const SDOperand &SDOperand::getOperand(unsigned i) const {
inline const SDOperandImpl &SDOperandImpl::getOperand(unsigned i) const {
return Val->getOperand(i);
}
inline uint64_t SDOperand::getConstantOperandVal(unsigned i) const {
inline uint64_t SDOperandImpl::getConstantOperandVal(unsigned i) const {
return Val->getConstantOperandVal(i);
}
inline bool SDOperand::isTargetOpcode() const {
inline bool SDOperandImpl::isTargetOpcode() const {
return Val->isTargetOpcode();
}
inline unsigned SDOperand::getTargetOpcode() const {
inline unsigned SDOperandImpl::getTargetOpcode() const {
return Val->getTargetOpcode();
}
inline bool SDOperand::hasOneUse() const {
inline bool SDOperandImpl::hasOneUse() const {
return Val->hasNUsesOfValue(1, ResNo);
}
inline bool SDOperand::use_empty() const {
inline bool SDOperandImpl::use_empty() const {
return !Val->hasAnyUseOfValue(ResNo);
}

View File

@ -78,7 +78,7 @@ namespace {
void AddUsersToWorkList(SDNode *N) {
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
UI != UE; ++UI)
AddToWorkList(*UI);
AddToWorkList(UI->getUser());
}
/// visit - call the node-specific routine that knows how to fold each
@ -2704,7 +2704,7 @@ static bool ExtendUsesToFormExtLoad(SDNode *N, SDOperand N0,
bool isTruncFree = TLI.isTruncateFree(N->getValueType(0), N0.getValueType());
for (SDNode::use_iterator UI = N0.Val->use_begin(), UE = N0.Val->use_end();
UI != UE; ++UI) {
SDNode *User = *UI;
SDNode *User = UI->getUser();
if (User == N)
continue;
// FIXME: Only extend SETCC N, N and SETCC N, c for now.
@ -2743,7 +2743,7 @@ static bool ExtendUsesToFormExtLoad(SDNode *N, SDOperand N0,
bool BothLiveOut = false;
for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
UI != UE; ++UI) {
SDNode *User = *UI;
SDNode *User = UI->getUser();
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
SDOperand UseOp = User->getOperand(i);
if (UseOp.Val == N && UseOp.ResNo == 0) {
@ -3880,7 +3880,7 @@ SDOperand DAGCombiner::visitFP_EXTEND(SDNode *N) {
MVT::ValueType VT = N->getValueType(0);
// If this is fp_round(fpextend), don't fold it, allow ourselves to be folded.
if (N->hasOneUse() && (*N->use_begin())->getOpcode() == ISD::FP_ROUND)
if (N->hasOneUse() && (N->use_begin())->getOpcode() == ISD::FP_ROUND)
return SDOperand();
// fold (fp_extend c1fp) -> c1fp
@ -4101,7 +4101,7 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) {
bool RealUse = false;
for (SDNode::use_iterator I = Ptr.Val->use_begin(),
E = Ptr.Val->use_end(); I != E; ++I) {
SDNode *Use = *I;
SDNode *Use = I->getUser();
if (Use == N)
continue;
if (Use->isPredecessorOf(N))
@ -4186,7 +4186,7 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
for (SDNode::use_iterator I = Ptr.Val->use_begin(),
E = Ptr.Val->use_end(); I != E; ++I) {
SDNode *Op = *I;
SDNode *Op = I->getUser();
if (Op == N ||
(Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB))
continue;
@ -4214,7 +4214,7 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
bool TryNext = false;
for (SDNode::use_iterator II = BasePtr.Val->use_begin(),
EE = BasePtr.Val->use_end(); II != EE; ++II) {
SDNode *Use = *II;
SDNode *Use = II->getUser();
if (Use == Ptr.Val)
continue;
@ -4224,7 +4224,7 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) {
bool RealUse = false;
for (SDNode::use_iterator III = Use->use_begin(),
EEE = Use->use_end(); III != EEE; ++III) {
SDNode *UseUse = *III;
SDNode *UseUse = III->getUser();
if (!((UseUse->getOpcode() == ISD::LOAD &&
cast<LoadSDNode>(UseUse)->getBasePtr().Val == Use) ||
(UseUse->getOpcode() == ISD::STORE &&

View File

@ -85,17 +85,17 @@ class VISIBILITY_HIDDEN SelectionDAGLegalize {
/// LegalizedNodes - For nodes that are of legal width, and that have more
/// than one use, this map indicates what regularized operand to use. This
/// allows us to avoid legalizing the same thing more than once.
DenseMap<SDOperand, SDOperand> LegalizedNodes;
DenseMap<SDOperandImpl, SDOperand> LegalizedNodes;
/// PromotedNodes - For nodes that are below legal width, and that have more
/// than one use, this map indicates what promoted value to use. This allows
/// us to avoid promoting the same thing more than once.
DenseMap<SDOperand, SDOperand> PromotedNodes;
DenseMap<SDOperandImpl, SDOperand> PromotedNodes;
/// ExpandedNodes - For nodes that need to be expanded this map indicates
/// which which operands are the expanded version of the input. This allows
/// us to avoid expanding the same node more than once.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedNodes;
DenseMap<SDOperandImpl, std::pair<SDOperand, SDOperand> > ExpandedNodes;
/// SplitNodes - For vector nodes that need to be split, this map indicates
/// which which operands are the split version of the input. This allows us
@ -308,7 +308,7 @@ static void ComputeTopDownOrdering(SelectionDAG &DAG,
// are now done.
for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
UI != E; ++UI)
Worklist.push_back(*UI);
Worklist.push_back(UI->getUser());
}
assert(Order.size() == Visited.size() &&
@ -381,7 +381,7 @@ static SDNode *FindCallEndFromCallStart(SDNode *Node) {
E = Node->use_end(); UI != E; ++UI) {
// Make sure to only follow users of our token chain.
SDNode *User = *UI;
SDNode *User = UI->getUser();
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i)
if (User->getOperand(i) == TheChain)
if (SDNode *Result = FindCallEndFromCallStart(User))
@ -783,7 +783,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
// Note that LegalizeOp may be reentered even from single-use nodes, which
// means that we always must cache transformed nodes.
DenseMap<SDOperand, SDOperand>::iterator I = LegalizedNodes.find(Op);
DenseMap<SDOperandImpl, SDOperand>::iterator I = LegalizedNodes.find(Op);
if (I != LegalizedNodes.end()) return I->second;
SDOperand Tmp1, Tmp2, Tmp3, Tmp4;
@ -1599,7 +1599,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
// will cause this node to be legalized as well as handling libcalls right.
if (LastCALLSEQ_END.Val != Node) {
LegalizeOp(SDOperand(FindCallStartFromCallEnd(Node), 0));
DenseMap<SDOperand, SDOperand>::iterator I = LegalizedNodes.find(Op);
DenseMap<SDOperandImpl, SDOperand>::iterator I = LegalizedNodes.find(Op);
assert(I != LegalizedNodes.end() &&
"Legalizing the call start should have legalized this node!");
return I->second;
@ -4136,7 +4136,7 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) {
SDOperand Result;
SDNode *Node = Op.Val;
DenseMap<SDOperand, SDOperand>::iterator I = PromotedNodes.find(Op);
DenseMap<SDOperandImpl, SDOperand>::iterator I = PromotedNodes.find(Op);
if (I != PromotedNodes.end()) return I->second;
switch (Node->getOpcode()) {
@ -5833,7 +5833,7 @@ void SelectionDAGLegalize::ExpandOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi){
"Cannot expand to FP value or to larger int value!");
// See if we already expanded it.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator I
DenseMap<SDOperandImpl, std::pair<SDOperand, SDOperand> >::iterator I
= ExpandedNodes.find(Op);
if (I != ExpandedNodes.end()) {
Lo = I->second.first;

View File

@ -137,7 +137,7 @@ NodeDone:
for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
UI != E; ++UI) {
SDNode *User = *UI;
SDNode *User = UI->getUser();
int NodeID = User->getNodeId();
assert(NodeID != ReadyToProcess && NodeID != Processed &&
"Invalid node id for user of unprocessed node!");
@ -344,7 +344,7 @@ void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) {
/// RemapNode - If the specified value was already legalized to another value,
/// replace it by that value.
void DAGTypeLegalizer::RemapNode(SDOperand &N) {
DenseMap<SDOperand, SDOperand>::iterator I = ReplacedNodes.find(N);
DenseMap<SDOperandImpl, SDOperand>::iterator I = ReplacedNodes.find(N);
if (I != ReplacedNodes.end()) {
// Use path compression to speed up future lookups if values get multiply
// replaced with other values.

View File

@ -110,27 +110,27 @@ private:
/// PromotedNodes - For nodes that are below legal width, this map indicates
/// what promoted value to use.
DenseMap<SDOperand, SDOperand> PromotedNodes;
DenseMap<SDOperandImpl, SDOperand> PromotedNodes;
/// ExpandedNodes - For nodes that need to be expanded this map indicates
/// which operands are the expanded version of the input.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedNodes;
DenseMap<SDOperandImpl, std::pair<SDOperand, SDOperand> > ExpandedNodes;
/// FloatToIntedNodes - For floating point nodes converted to integers of
/// the same size, this map indicates the converted value to use.
DenseMap<SDOperand, SDOperand> FloatToIntedNodes;
DenseMap<SDOperandImpl, SDOperand> FloatToIntedNodes;
/// ScalarizedNodes - For nodes that are <1 x ty>, this map indicates the
/// scalar value of type 'ty' to use.
DenseMap<SDOperand, SDOperand> ScalarizedNodes;
DenseMap<SDOperandImpl, SDOperand> ScalarizedNodes;
/// SplitNodes - For nodes that need to be split this map indicates
/// which operands are the expanded version of the input.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > SplitNodes;
DenseMap<SDOperandImpl, std::pair<SDOperand, SDOperand> > SplitNodes;
/// ReplacedNodes - For nodes that have been replaced with another,
/// indicates the replacement node to use.
DenseMap<SDOperand, SDOperand> ReplacedNodes;
DenseMap<SDOperandImpl, SDOperand> ReplacedNodes;
/// Worklist - This defines a worklist of nodes to process. In order to be
/// pushed onto this worklist, all operands of a node must have already been

View File

@ -135,11 +135,11 @@ void ScheduleDAG::BuildSchedUnits() {
bool HasFlagUse = false;
for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
UI != E; ++UI)
if (FlagVal.isOperandOf(*UI)) {
if (FlagVal.isOperandOf(UI->getUser())) {
HasFlagUse = true;
NodeSUnit->FlaggedNodes.push_back(N);
SUnitMap[N].push_back(NodeSUnit);
N = *UI;
N = UI->getUser();
break;
}
if (!HasFlagUse) break;
@ -398,7 +398,7 @@ static const TargetRegisterClass *getInstrOperandRegClass(
void ScheduleDAG::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
unsigned InstanceNo, unsigned SrcReg,
DenseMap<SDOperand, unsigned> &VRBaseMap) {
DenseMap<SDOperandImpl, unsigned> &VRBaseMap) {
unsigned VRBase = 0;
if (TargetRegisterInfo::isVirtualRegister(SrcReg)) {
// Just use the input register directly!
@ -414,7 +414,7 @@ void ScheduleDAG::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
bool MatchReg = true;
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *Use = *UI;
SDNode *Use = UI->getUser();
bool Match = true;
if (Use->getOpcode() == ISD::CopyToReg &&
Use->getOperand(2).Val == Node &&
@ -469,7 +469,7 @@ void ScheduleDAG::EmitCopyFromReg(SDNode *Node, unsigned ResNo,
void ScheduleDAG::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
const TargetInstrDesc &II,
DenseMap<SDOperand, unsigned> &VRBaseMap) {
DenseMap<SDOperandImpl, unsigned> &VRBaseMap) {
for (unsigned i = 0; i < II.getNumDefs(); ++i) {
// If the specific node value is only used by a CopyToReg and the dest reg
// is a vreg, use the CopyToReg'd destination register instead of creating
@ -477,7 +477,7 @@ void ScheduleDAG::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
unsigned VRBase = 0;
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *Use = *UI;
SDNode *Use = UI->getUser();
if (Use->getOpcode() == ISD::CopyToReg &&
Use->getOperand(2).Val == Node &&
Use->getOperand(2).ResNo == i) {
@ -512,8 +512,8 @@ void ScheduleDAG::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
/// getVR - Return the virtual register corresponding to the specified result
/// of the specified node.
static unsigned getVR(SDOperand Op, DenseMap<SDOperand, unsigned> &VRBaseMap) {
DenseMap<SDOperand, unsigned>::iterator I = VRBaseMap.find(Op);
static unsigned getVR(SDOperand Op, DenseMap<SDOperandImpl, unsigned> &VRBaseMap) {
DenseMap<SDOperandImpl, unsigned>::iterator I = VRBaseMap.find(Op);
assert(I != VRBaseMap.end() && "Node emitted out of order - late");
return I->second;
}
@ -526,7 +526,7 @@ static unsigned getVR(SDOperand Op, DenseMap<SDOperand, unsigned> &VRBaseMap) {
void ScheduleDAG::AddOperand(MachineInstr *MI, SDOperand Op,
unsigned IIOpNum,
const TargetInstrDesc *II,
DenseMap<SDOperand, unsigned> &VRBaseMap) {
DenseMap<SDOperandImpl, unsigned> &VRBaseMap) {
if (Op.isTargetOpcode()) {
// Note that this case is redundant with the final else block, but we
// include it because it is the most common and it makes the logic
@ -658,7 +658,7 @@ static const TargetRegisterClass *getSuperregRegisterClass(
/// EmitSubregNode - Generate machine code for subreg nodes.
///
void ScheduleDAG::EmitSubregNode(SDNode *Node,
DenseMap<SDOperand, unsigned> &VRBaseMap) {
DenseMap<SDOperandImpl, unsigned> &VRBaseMap) {
unsigned VRBase = 0;
unsigned Opc = Node->getTargetOpcode();
@ -666,7 +666,7 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node,
// the CopyToReg'd destination register instead of creating a new vreg.
for (SDNode::use_iterator UI = Node->use_begin(), E = Node->use_end();
UI != E; ++UI) {
SDNode *Use = *UI;
SDNode *Use = UI->getUser();
if (Use->getOpcode() == ISD::CopyToReg &&
Use->getOperand(2).Val == Node) {
unsigned DestReg = cast<RegisterSDNode>(Use->getOperand(1))->getReg();
@ -750,7 +750,7 @@ void ScheduleDAG::EmitSubregNode(SDNode *Node,
/// EmitNode - Generate machine code for an node and needed dependencies.
///
void ScheduleDAG::EmitNode(SDNode *Node, unsigned InstanceNo,
DenseMap<SDOperand, unsigned> &VRBaseMap) {
DenseMap<SDOperandImpl, unsigned> &VRBaseMap) {
// If machine instruction
if (Node->isTargetOpcode()) {
unsigned Opc = Node->getTargetOpcode();
@ -1067,7 +1067,7 @@ void ScheduleDAG::EmitSchedule() {
}
// Finally, emit the code for all of the scheduled instructions.
DenseMap<SDOperand, unsigned> VRBaseMap;
DenseMap<SDOperandImpl, unsigned> VRBaseMap;
DenseMap<SUnit*, unsigned> CopyVRBaseMap;
for (unsigned i = 0, e = Sequence.size(); i != e; i++) {
if (SUnit *SU = Sequence[i]) {

View File

@ -10,7 +10,6 @@
// This implements the SelectionDAG class.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Constants.h"
#include "llvm/GlobalAlias.h"
@ -465,14 +464,15 @@ void SelectionDAG::RemoveDeadNodes() {
// no cycles in the graph.
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
SDNode *Operand = I->Val;
Operand->removeUser(N);
Operand->removeUser(std::distance(N->op_begin(), I), N);
// Now that we removed this operand, see if there are no uses of it left.
if (Operand->use_empty())
DeadNodes.push_back(Operand);
}
if (N->OperandsNeedDelete)
if (N->OperandsNeedDelete) {
delete[] N->OperandList;
}
N->OperandList = 0;
N->NumOperands = 0;
@ -504,14 +504,15 @@ void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){
// no cycles in the graph.
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
SDNode *Operand = I->Val;
Operand->removeUser(N);
Operand->removeUser(std::distance(N->op_begin(), I), N);
// Now that we removed this operand, see if there are no uses of it left.
if (Operand->use_empty())
DeadNodes.push_back(Operand);
}
if (N->OperandsNeedDelete)
if (N->OperandsNeedDelete) {
delete[] N->OperandList;
}
N->OperandList = 0;
N->NumOperands = 0;
@ -538,9 +539,10 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
// Drop all of the operands and decrement used nodes use counts.
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
I->Val->removeUser(N);
if (N->OperandsNeedDelete)
I->Val->removeUser(std::distance(N->op_begin(), I), N);
if (N->OperandsNeedDelete) {
delete[] N->OperandList;
}
N->OperandList = 0;
N->NumOperands = 0;
@ -701,8 +703,9 @@ SelectionDAG::~SelectionDAG() {
while (!AllNodes.empty()) {
SDNode *N = AllNodes.begin();
N->SetNextInBucket(0);
if (N->OperandsNeedDelete)
if (N->OperandsNeedDelete) {
delete [] N->OperandList;
}
N->OperandList = 0;
N->NumOperands = 0;
AllNodes.pop_front();
@ -2920,9 +2923,10 @@ UpdateNodeOperands(SDOperand InN, SDOperand Op) {
RemoveNodeFromCSEMaps(N);
// Now we update the operands.
N->OperandList[0].Val->removeUser(N);
Op.Val->addUser(N);
N->OperandList[0].Val->removeUser(0, N);
N->OperandList[0] = Op;
N->OperandList[0].setUser(N);
Op.Val->addUser(0, N);
// If this gets put into a CSE map, add it.
if (InsertPos) CSEMap.InsertNode(N, InsertPos);
@ -2949,14 +2953,16 @@ UpdateNodeOperands(SDOperand InN, SDOperand Op1, SDOperand Op2) {
// Now we update the operands.
if (N->OperandList[0] != Op1) {
N->OperandList[0].Val->removeUser(N);
Op1.Val->addUser(N);
N->OperandList[0].Val->removeUser(0, N);
N->OperandList[0] = Op1;
N->OperandList[0].setUser(N);
Op1.Val->addUser(0, N);
}
if (N->OperandList[1] != Op2) {
N->OperandList[1].Val->removeUser(N);
Op2.Val->addUser(N);
N->OperandList[1].Val->removeUser(1, N);
N->OperandList[1] = Op2;
N->OperandList[1].setUser(N);
Op2.Val->addUser(1, N);
}
// If this gets put into a CSE map, add it.
@ -2984,7 +2990,6 @@ UpdateNodeOperands(SDOperand N, SDOperand Op1, SDOperand Op2,
return UpdateNodeOperands(N, Ops, 5);
}
SDOperand SelectionDAG::
UpdateNodeOperands(SDOperand InN, SDOperand *Ops, unsigned NumOps) {
SDNode *N = InN.Val;
@ -3015,9 +3020,10 @@ UpdateNodeOperands(SDOperand InN, SDOperand *Ops, unsigned NumOps) {
// Now we update the operands.
for (unsigned i = 0; i != NumOps; ++i) {
if (N->OperandList[i] != Ops[i]) {
N->OperandList[i].Val->removeUser(N);
Ops[i].Val->addUser(N);
N->OperandList[i].Val->removeUser(i, N);
N->OperandList[i] = Ops[i];
N->OperandList[i].setUser(N);
Ops[i].Val->addUser(i, N);
}
}
@ -3026,7 +3032,6 @@ UpdateNodeOperands(SDOperand InN, SDOperand *Ops, unsigned NumOps) {
return InN;
}
/// MorphNodeTo - This frees the operands of the current node, resets the
/// opcode, types, and operands to the specified value. This should only be
/// used by the SelectionDAG class.
@ -3039,13 +3044,14 @@ void SDNode::MorphNodeTo(unsigned Opc, SDVTList L,
// Clear the operands list, updating used nodes to remove this from their
// use list.
for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
I->Val->removeUser(this);
I->Val->removeUser(std::distance(op_begin(), I), this);
// If NumOps is larger than the # of operands we currently have, reallocate
// the operand list.
if (NumOps > NumOperands) {
if (OperandsNeedDelete)
if (OperandsNeedDelete) {
delete [] OperandList;
}
OperandList = new SDOperand[NumOps];
OperandsNeedDelete = true;
}
@ -3055,8 +3061,10 @@ void SDNode::MorphNodeTo(unsigned Opc, SDVTList L,
for (unsigned i = 0, e = NumOps; i != e; ++i) {
OperandList[i] = Ops[i];
OperandList[i].setUser(this);
SDNode *N = OperandList[i].Val;
N->Uses.push_back(this);
N->addUser(i, this);
++N->UsesSize;
}
}
@ -3324,21 +3332,27 @@ void SelectionDAG::ReplaceAllUsesWith(SDOperand FromN, SDOperand To,
assert(From->getNumValues() == 1 && FromN.ResNo == 0 &&
"Cannot replace with this method!");
assert(From != To.Val && "Cannot replace uses of with self");
SmallSetVector<SDNode*, 16> Users;
while (!From->use_empty()) {
// Process users until they are all gone.
SDNode *U = *From->use_begin();
SDNode::use_iterator UI = From->use_begin();
SDNode *U = UI->getUser();
// Remember that this node is about to morph.
if (Users.count(U))
continue;
Users.insert(U);
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(U);
for (SDOperand *I = U->OperandList, *E = U->OperandList+U->NumOperands;
I != E; ++I)
int operandNum = 0;
for (SDNode::op_iterator I = U->op_begin(), E = U->op_end();
I != E; ++I, ++operandNum)
if (I->Val == From) {
From->removeUser(U);
From->removeUser(operandNum, U);
*I = To;
To.Val->addUser(U);
}
I->setUser(U);
To.Val->addUser(operandNum, U);
}
// Now that we have modified U, add it back to the CSE maps. If it already
// exists there, recursively merge the results together.
@ -3372,21 +3386,26 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To,
return ReplaceAllUsesWith(SDOperand(From, 0), SDOperand(To, 0),
UpdateListener);
SmallSetVector<SDNode*, 16> Users;
while (!From->use_empty()) {
// Process users until they are all gone.
SDNode *U = *From->use_begin();
SDNode::use_iterator UI = From->use_begin();
SDNode *U = UI->getUser();
// Remember that this node is about to morph.
if (Users.count(U))
continue;
Users.insert(U);
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(U);
for (SDOperand *I = U->OperandList, *E = U->OperandList+U->NumOperands;
I != E; ++I)
int operandNum = 0;
for (SDNode::op_iterator I = U->op_begin(), E = U->op_end();
I != E; ++I, ++operandNum)
if (I->Val == From) {
From->removeUser(U);
From->removeUser(operandNum, U);
I->Val = To;
To->addUser(U);
To->addUser(operandNum, U);
}
// Now that we have modified U, add it back to the CSE maps. If it already
// exists there, recursively merge the results together.
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) {
@ -3415,22 +3434,28 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From,
if (From->getNumValues() == 1) // Handle the simple case efficiently.
return ReplaceAllUsesWith(SDOperand(From, 0), To[0], UpdateListener);
SmallSetVector<SDNode*, 16> Users;
while (!From->use_empty()) {
// Process users until they are all gone.
SDNode *U = *From->use_begin();
SDNode::use_iterator UI = From->use_begin();
SDNode *U = UI->getUser();
// Remember that this node is about to morph.
if (Users.count(U))
continue;
Users.insert(U);
// This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(U);
for (SDOperand *I = U->OperandList, *E = U->OperandList+U->NumOperands;
I != E; ++I)
int operandNum = 0;
for (SDNode::op_iterator I = U->op_begin(), E = U->op_end();
I != E; ++I, ++operandNum)
if (I->Val == From) {
const SDOperand &ToOp = To[I->ResNo];
From->removeUser(U);
From->removeUser(operandNum, U);
*I = ToOp;
ToOp.Val->addUser(U);
I->setUser(U);
ToOp.Val->addUser(operandNum, U);
}
// Now that we have modified U, add it back to the CSE maps. If it already
// exists there, recursively merge the results together.
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) {
@ -3460,7 +3485,7 @@ namespace {
ChainedSetUpdaterListener(SmallSetVector<SDNode*, 16> &set,
SelectionDAG::DAGUpdateListener *chain)
: Set(set), Chain(chain) {}
virtual void NodeDeleted(SDNode *N) {
Set.remove(N);
if (Chain) Chain->NodeDeleted(N);
@ -3488,7 +3513,13 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To,
// Get all of the users of From.Val. We want these in a nice,
// deterministically ordered and uniqued set, so we use a SmallSetVector.
SmallSetVector<SDNode*, 16> Users(From.Val->use_begin(), From.Val->use_end());
SmallSetVector<SDNode*, 16> Users;
for (SDNode::use_iterator UI = From.Val->use_begin(),
E = From.Val->use_end(); UI != E; ++UI) {
SDNode *User = UI->getUser();
if (!Users.count(User))
Users.insert(User);
}
// When one of the recursive merges deletes nodes from the graph, we need to
// make sure that UpdateListener is notified *and* that the node is removed
@ -3502,7 +3533,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To,
Users.pop_back();
// Scan for an operand that matches From.
SDOperand *Op = User->OperandList, *E = User->OperandList+User->NumOperands;
SDNode::op_iterator Op = User->op_begin(), E = User->op_end();
for (; Op != E; ++Op)
if (*Op == From) break;
@ -3516,9 +3547,10 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To,
// Update all operands that match "From" in case there are multiple uses.
for (; Op != E; ++Op) {
if (*Op == From) {
From.Val->removeUser(User);
*Op = To;
To.Val->addUser(User);
From.Val->removeUser(Op-User->op_begin(), User);
*Op = To;
Op->setUser(User);
To.Val->addUser(Op-User->op_begin(), User);
}
}
@ -3698,16 +3730,13 @@ bool SDNode::hasNUsesOfValue(unsigned NUses, unsigned Value) const {
SmallPtrSet<SDNode*, 32> UsersHandled;
for (SDNode::use_iterator UI = Uses.begin(), E = Uses.end(); UI != E; ++UI) {
SDNode *User = *UI;
if (User->getNumOperands() == 1 ||
UsersHandled.insert(User)) // First time we've seen this?
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i)
if (User->getOperand(i) == TheValue) {
if (NUses == 0)
return false; // too many uses
--NUses;
}
// 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 == TheValue) {
if (NUses == 0)
return false;
--NUses;
}
}
// Found exactly the right number of uses?
@ -3726,8 +3755,8 @@ bool SDNode::hasAnyUseOfValue(unsigned Value) const {
SmallPtrSet<SDNode*, 32> UsersHandled;
for (SDNode::use_iterator UI = Uses.begin(), E = Uses.end(); UI != E; ++UI) {
SDNode *User = *UI;
for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) {
SDNode *User = UI->getUser();
if (User->getNumOperands() == 1 ||
UsersHandled.insert(User)) // First time we've seen this?
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i)
@ -3745,7 +3774,7 @@ bool SDNode::hasAnyUseOfValue(unsigned Value) const {
bool SDNode::isOnlyUseOf(SDNode *N) const {
bool Seen = false;
for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
SDNode *User = *I;
SDNode *User = I->getUser();
if (User == this)
Seen = true;
else
@ -3757,7 +3786,7 @@ bool SDNode::isOnlyUseOf(SDNode *N) const {
/// isOperand - Return true if this node is an operand of N.
///
bool SDOperand::isOperandOf(SDNode *N) const {
bool SDOperandImpl::isOperandOf(SDNode *N) const {
for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
if (*this == N->getOperand(i))
return true;
@ -3776,7 +3805,7 @@ bool SDNode::isOperandOf(SDNode *N) const {
/// side-effecting instructions. In practice, this looks through token
/// factors and non-volatile loads. In order to remain efficient, this only
/// looks a couple of nodes in, it does not do an exhaustive search.
bool SDOperand::reachesChainWithoutSideEffects(SDOperand Dest,
bool SDOperandImpl::reachesChainWithoutSideEffects(SDOperandImpl Dest,
unsigned Depth) const {
if (*this == Dest) return true;

View File

@ -3660,11 +3660,11 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
SDNode *LHSN = N->getOperand(0).Val;
for (SDNode::use_iterator UI = LHSN->use_begin(), E = LHSN->use_end();
UI != E; ++UI)
if ((*UI)->getOpcode() == PPCISD::VCMPo &&
(*UI)->getOperand(1) == N->getOperand(1) &&
(*UI)->getOperand(2) == N->getOperand(2) &&
(*UI)->getOperand(0) == N->getOperand(0)) {
VCMPoNode = *UI;
if ((*UI).getUser()->getOpcode() == PPCISD::VCMPo &&
(*UI).getUser()->getOperand(1) == N->getOperand(1) &&
(*UI).getUser()->getOperand(2) == N->getOperand(2) &&
(*UI).getUser()->getOperand(0) == N->getOperand(0)) {
VCMPoNode = UI->getUser();
break;
}
@ -3680,7 +3680,7 @@ SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N,
for (SDNode::use_iterator UI = VCMPoNode->use_begin();
FlagUser == 0; ++UI) {
assert(UI != VCMPoNode->use_end() && "Didn't find user!");
SDNode *User = *UI;
SDNode *User = UI->getUser();
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
if (User->getOperand(i) == SDOperand(VCMPoNode, 1)) {
FlagUser = User;

View File

@ -225,7 +225,7 @@ namespace {
static SDNode *findFlagUse(SDNode *N) {
unsigned FlagResNo = N->getNumValues()-1;
for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) {
SDNode *User = *I;
SDNode *User = I->getUser();
for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) {
SDOperand Op = User->getOperand(i);
if (Op.Val == N && Op.ResNo == FlagResNo)

View File

@ -3724,7 +3724,7 @@ X86TargetLowering::LowerEXTRACT_VECTOR_ELT_SSE4(SDOperand Op,
// result has a single use which is a store.
if (!Op.hasOneUse())
return SDOperand();
SDNode *User = *Op.Val->use_begin();
SDNode *User = Op.Val->use_begin()->getUser();
if (User->getOpcode() != ISD::STORE)
return SDOperand();
SDOperand Extract = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, MVT::i32,