mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-20 10:30:03 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@62995 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
19c10e658a
commit
e7852d0144
@ -955,63 +955,77 @@ template<> struct simplify_type<const SDValue> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// SDUse - Represents a use of the SDNode referred by
|
/// SDUse - Represents a use of a SDNode. This class holds an SDValue,
|
||||||
/// the 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 {
|
class SDUse {
|
||||||
SDValue Operand;
|
/// Val - The value being used.
|
||||||
/// User - Parent node of this operand.
|
SDValue Val;
|
||||||
SDNode *User;
|
/// User - The user of this value.
|
||||||
/// Prev, next - Pointers to the uses list of the SDNode referred by
|
SDNode *User;
|
||||||
|
/// Prev, Next - Pointers to the uses list of the SDNode referred by
|
||||||
/// this operand.
|
/// this operand.
|
||||||
SDUse **Prev, *Next;
|
SDUse **Prev, *Next;
|
||||||
|
|
||||||
|
SDUse(const SDUse &U); // Do not implement
|
||||||
|
void operator=(const SDUse &U); // Do not implement
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend class SDNode;
|
SDUse() : Val(), User(NULL), Prev(NULL), Next(NULL) {}
|
||||||
SDUse(): Operand(), User(NULL), Prev(NULL), Next(NULL) {}
|
|
||||||
|
|
||||||
SDUse(SDNode *val, unsigned resno) :
|
/// Normally SDUse will just implicitly convert to an SDValue that it holds.
|
||||||
Operand(val,resno), User(NULL), Prev(NULL), Next(NULL) {}
|
operator const SDValue&() const { return Val; }
|
||||||
|
|
||||||
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; }
|
|
||||||
|
|
||||||
|
/// 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; }
|
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; }
|
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) {
|
void addToList(SDUse **List) {
|
||||||
Next = *List;
|
Next = *List;
|
||||||
if (Next) Next->Prev = &Next;
|
if (Next) Next->Prev = &Next;
|
||||||
@ -1025,61 +1039,22 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// simplify_type specializations - Allow casting operators to work directly on
|
/// simplify_type specializations - Allow casting operators to work directly on
|
||||||
/// SDValues as if they were SDNode*'s.
|
/// SDValues as if they were SDNode*'s.
|
||||||
template<> struct simplify_type<SDUse> {
|
template<> struct simplify_type<SDUse> {
|
||||||
typedef SDNode* SimpleType;
|
typedef SDNode* SimpleType;
|
||||||
static SimpleType getSimplifiedValue(const SDUse &Val) {
|
static SimpleType getSimplifiedValue(const SDUse &Val) {
|
||||||
return static_cast<SimpleType>(Val.getVal());
|
return static_cast<SimpleType>(Val.getNode());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
template<> struct simplify_type<const SDUse> {
|
template<> struct simplify_type<const SDUse> {
|
||||||
typedef SDNode* SimpleType;
|
typedef SDNode* SimpleType;
|
||||||
static SimpleType getSimplifiedValue(const SDUse &Val) {
|
static SimpleType getSimplifiedValue(const SDUse &Val) {
|
||||||
return static_cast<SimpleType>(Val.getVal());
|
return static_cast<SimpleType>(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.
|
/// SDNode - Represents one node in the SelectionDAG.
|
||||||
///
|
///
|
||||||
class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
|
class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
|
||||||
@ -1113,11 +1088,14 @@ private:
|
|||||||
/// NumOperands/NumValues - The number of entries in the Operand/Value list.
|
/// NumOperands/NumValues - The number of entries in the Operand/Value list.
|
||||||
unsigned short NumOperands, NumValues;
|
unsigned short NumOperands, NumValues;
|
||||||
|
|
||||||
/// Uses - List of uses for this SDNode.
|
/// UseList - List of uses for this SDNode.
|
||||||
SDUse *Uses;
|
SDUse *UseList;
|
||||||
|
|
||||||
/// addUse - add SDUse to the list of uses.
|
/// getValueTypeList - Return a pointer to the specified value type.
|
||||||
void addUse(SDUse &U) { U.addToList(&Uses); }
|
static const MVT *getValueTypeList(MVT VT);
|
||||||
|
|
||||||
|
friend class SelectionDAG;
|
||||||
|
friend struct ilist_traits<SDNode>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
@ -1148,7 +1126,7 @@ public:
|
|||||||
|
|
||||||
/// use_empty - Return true if there are no uses of this node.
|
/// 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.
|
/// hasOneUse - Return true if there is exactly one use of this node.
|
||||||
///
|
///
|
||||||
@ -1226,7 +1204,7 @@ public:
|
|||||||
/// of an SDNode.
|
/// of an SDNode.
|
||||||
|
|
||||||
use_iterator use_begin() const {
|
use_iterator use_begin() const {
|
||||||
return use_iterator(Uses);
|
return use_iterator(UseList);
|
||||||
}
|
}
|
||||||
|
|
||||||
static use_iterator use_end() { return use_iterator(0); }
|
static use_iterator use_end() { return use_iterator(0); }
|
||||||
@ -1265,14 +1243,13 @@ public:
|
|||||||
|
|
||||||
const SDValue &getOperand(unsigned Num) const {
|
const SDValue &getOperand(unsigned Num) const {
|
||||||
assert(Num < NumOperands && "Invalid child # of SDNode!");
|
assert(Num < NumOperands && "Invalid child # of SDNode!");
|
||||||
return OperandList[Num].getSDValue();
|
return OperandList[Num];
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef SDUse* op_iterator;
|
typedef SDUse* op_iterator;
|
||||||
op_iterator op_begin() const { return OperandList; }
|
op_iterator op_begin() const { return OperandList; }
|
||||||
op_iterator op_end() const { return OperandList+NumOperands; }
|
op_iterator op_end() const { return OperandList+NumOperands; }
|
||||||
|
|
||||||
|
|
||||||
SDVTList getVTList() const {
|
SDVTList getVTList() const {
|
||||||
SDVTList X = { ValueList, NumValues };
|
SDVTList X = { ValueList, NumValues };
|
||||||
return X;
|
return X;
|
||||||
@ -1339,13 +1316,11 @@ public:
|
|||||||
///
|
///
|
||||||
void Profile(FoldingSetNodeID &ID) const;
|
void Profile(FoldingSetNodeID &ID) const;
|
||||||
|
|
||||||
protected:
|
/// addUse - This method should only be used by the SDUse class.
|
||||||
friend class SelectionDAG;
|
|
||||||
friend struct ilist_traits<SDNode>;
|
|
||||||
|
|
||||||
/// getValueTypeList - Return a pointer to the specified value type.
|
|
||||||
///
|
///
|
||||||
static const MVT *getValueTypeList(MVT VT);
|
void addUse(SDUse &U) { U.addToList(&UseList); }
|
||||||
|
|
||||||
|
protected:
|
||||||
static SDVTList getSDVTList(MVT VT) {
|
static SDVTList getSDVTList(MVT VT) {
|
||||||
SDVTList Ret = { getValueTypeList(VT), 1 };
|
SDVTList Ret = { getValueTypeList(VT), 1 };
|
||||||
return Ret;
|
return Ret;
|
||||||
@ -1353,77 +1328,84 @@ protected:
|
|||||||
|
|
||||||
SDNode(unsigned Opc, SDVTList VTs, const SDValue *Ops, unsigned NumOps)
|
SDNode(unsigned Opc, SDVTList VTs, const SDValue *Ops, unsigned NumOps)
|
||||||
: NodeType(Opc), OperandsNeedDelete(true), SubclassData(0),
|
: NodeType(Opc), OperandsNeedDelete(true), SubclassData(0),
|
||||||
NodeId(-1), Uses(NULL) {
|
NodeId(-1),
|
||||||
NumOperands = NumOps;
|
OperandList(NumOps ? new SDUse[NumOps] : 0),
|
||||||
OperandList = NumOps ? new SDUse[NumOperands] : 0;
|
ValueList(VTs.VTs),
|
||||||
|
NumOperands(NumOps), NumValues(VTs.NumVTs),
|
||||||
|
UseList(NULL) {
|
||||||
for (unsigned i = 0; i != NumOps; ++i) {
|
for (unsigned i = 0; i != NumOps; ++i) {
|
||||||
OperandList[i] = Ops[i];
|
|
||||||
OperandList[i].setUser(this);
|
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
|
/// This constructor adds no operands itself; operands can be
|
||||||
/// set later with InitOperands.
|
/// set later with InitOperands.
|
||||||
SDNode(unsigned Opc, SDVTList VTs)
|
SDNode(unsigned Opc, SDVTList VTs)
|
||||||
: NodeType(Opc), OperandsNeedDelete(false), SubclassData(0),
|
: NodeType(Opc), OperandsNeedDelete(false), SubclassData(0),
|
||||||
NodeId(-1), Uses(NULL) {
|
NodeId(-1), OperandList(0), ValueList(VTs.VTs),
|
||||||
NumOperands = 0;
|
NumOperands(0), NumValues(VTs.NumVTs),
|
||||||
OperandList = 0;
|
UseList(NULL) {}
|
||||||
ValueList = VTs.VTs;
|
|
||||||
NumValues = VTs.NumVTs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// InitOperands - Initialize the operands list of this node with the
|
/// InitOperands - Initialize the operands list of this with 1 operand.
|
||||||
/// specified values, which are part of the node (thus they don't need to be
|
void InitOperands(SDUse *Ops, const SDValue &Op0) {
|
||||||
/// copied in or allocated).
|
Ops[0].setUser(this);
|
||||||
void InitOperands(SDUse *Ops, unsigned NumOps) {
|
Ops[0].setInitial(Op0);
|
||||||
assert(OperandList == 0 && "Operands already set!");
|
NumOperands = 1;
|
||||||
NumOperands = NumOps;
|
|
||||||
OperandList = Ops;
|
OperandList = Ops;
|
||||||
Uses = NULL;
|
}
|
||||||
|
|
||||||
for (unsigned i = 0; i != NumOps; ++i) {
|
/// InitOperands - Initialize the operands list of this with 2 operands.
|
||||||
OperandList[i].setUser(this);
|
void InitOperands(SDUse *Ops, const SDValue &Op0, const SDValue &Op1) {
|
||||||
Ops[i].getVal()->addUse(OperandList[i]);
|
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
|
/// DropOperands - Release the operands and set this node to have
|
||||||
/// zero operands.
|
/// zero operands.
|
||||||
void DropOperands();
|
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);
|
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
|
/// UnarySDNode - This class is used for single-operand SDNodes. This is solely
|
||||||
/// to allow co-allocation of node operands with the node itself.
|
/// to allow co-allocation of node operands with the node itself.
|
||||||
class UnarySDNode : public SDNode {
|
class UnarySDNode : public SDNode {
|
||||||
@ -1467,8 +1468,7 @@ class UnarySDNode : public SDNode {
|
|||||||
public:
|
public:
|
||||||
UnarySDNode(unsigned Opc, SDVTList VTs, SDValue X)
|
UnarySDNode(unsigned Opc, SDVTList VTs, SDValue X)
|
||||||
: SDNode(Opc, VTs) {
|
: SDNode(Opc, VTs) {
|
||||||
Op = X;
|
InitOperands(&Op, X);
|
||||||
InitOperands(&Op, 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1479,9 +1479,7 @@ class BinarySDNode : public SDNode {
|
|||||||
public:
|
public:
|
||||||
BinarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y)
|
BinarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y)
|
||||||
: SDNode(Opc, VTs) {
|
: SDNode(Opc, VTs) {
|
||||||
Ops[0] = X;
|
InitOperands(Ops, X, Y);
|
||||||
Ops[1] = Y;
|
|
||||||
InitOperands(Ops, 2);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1493,10 +1491,7 @@ public:
|
|||||||
TernarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y,
|
TernarySDNode(unsigned Opc, SDVTList VTs, SDValue X, SDValue Y,
|
||||||
SDValue Z)
|
SDValue Z)
|
||||||
: SDNode(Opc, VTs) {
|
: SDNode(Opc, VTs) {
|
||||||
Ops[0] = X;
|
InitOperands(Ops, X, Y, Z);
|
||||||
Ops[1] = Y;
|
|
||||||
Ops[2] = Z;
|
|
||||||
InitOperands(Ops, 3);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1516,11 +1511,10 @@ public:
|
|||||||
explicit HandleSDNode(SDValue X)
|
explicit HandleSDNode(SDValue X)
|
||||||
#endif
|
#endif
|
||||||
: SDNode(ISD::HANDLENODE, getSDVTList(MVT::Other)) {
|
: SDNode(ISD::HANDLENODE, getSDVTList(MVT::Other)) {
|
||||||
Op = X;
|
InitOperands(&Op, X);
|
||||||
InitOperands(&Op, 1);
|
|
||||||
}
|
}
|
||||||
~HandleSDNode();
|
~HandleSDNode();
|
||||||
const SDValue &getValue() const { return Op.getSDValue(); }
|
const SDValue &getValue() const { return Op; }
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Abstact virtual class for operations for memory operations
|
/// Abstact virtual class for operations for memory operations
|
||||||
@ -1617,21 +1611,14 @@ public:
|
|||||||
unsigned Align=0)
|
unsigned Align=0)
|
||||||
: MemSDNode(Opc, VTL, MemVT, SrcVal, /*SVOffset=*/0,
|
: MemSDNode(Opc, VTL, MemVT, SrcVal, /*SVOffset=*/0,
|
||||||
Align, /*isVolatile=*/true) {
|
Align, /*isVolatile=*/true) {
|
||||||
Ops[0] = Chain;
|
InitOperands(Ops, Chain, Ptr, Cmp, Swp);
|
||||||
Ops[1] = Ptr;
|
|
||||||
Ops[2] = Cmp;
|
|
||||||
Ops[3] = Swp;
|
|
||||||
InitOperands(Ops, 4);
|
|
||||||
}
|
}
|
||||||
AtomicSDNode(unsigned Opc, SDVTList VTL, MVT MemVT,
|
AtomicSDNode(unsigned Opc, SDVTList VTL, MVT MemVT,
|
||||||
SDValue Chain, SDValue Ptr,
|
SDValue Chain, SDValue Ptr,
|
||||||
SDValue Val, const Value* SrcVal, unsigned Align=0)
|
SDValue Val, const Value* SrcVal, unsigned Align=0)
|
||||||
: MemSDNode(Opc, VTL, MemVT, SrcVal, /*SVOffset=*/0,
|
: MemSDNode(Opc, VTL, MemVT, SrcVal, /*SVOffset=*/0,
|
||||||
Align, /*isVolatile=*/true) {
|
Align, /*isVolatile=*/true) {
|
||||||
Ops[0] = Chain;
|
InitOperands(Ops, Chain, Ptr, Val);
|
||||||
Ops[1] = Ptr;
|
|
||||||
Ops[2] = Val;
|
|
||||||
InitOperands(Ops, 3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDValue &getBasePtr() const { return getOperand(1); }
|
const SDValue &getBasePtr() const { return getOperand(1); }
|
||||||
@ -1979,8 +1966,7 @@ protected:
|
|||||||
Value *cu)
|
Value *cu)
|
||||||
: SDNode(ISD::DBG_STOPPOINT, getSDVTList(MVT::Other)),
|
: SDNode(ISD::DBG_STOPPOINT, getSDVTList(MVT::Other)),
|
||||||
Line(l), Column(c), CU(cu) {
|
Line(l), Column(c), CU(cu) {
|
||||||
Chain = ch;
|
InitOperands(&Chain, ch);
|
||||||
InitOperands(&Chain, 1);
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
unsigned getLine() const { return Line; }
|
unsigned getLine() const { return Line; }
|
||||||
@ -2000,8 +1986,7 @@ protected:
|
|||||||
friend class SelectionDAG;
|
friend class SelectionDAG;
|
||||||
LabelSDNode(unsigned NodeTy, SDValue ch, unsigned id)
|
LabelSDNode(unsigned NodeTy, SDValue ch, unsigned id)
|
||||||
: SDNode(NodeTy, getSDVTList(MVT::Other)), LabelID(id) {
|
: SDNode(NodeTy, getSDVTList(MVT::Other)), LabelID(id) {
|
||||||
Chain = ch;
|
InitOperands(&Chain, ch);
|
||||||
InitOperands(&Chain, 1);
|
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
unsigned getLabelID() const { return LabelID; }
|
unsigned getLabelID() const { return LabelID; }
|
||||||
@ -2256,9 +2241,7 @@ public:
|
|||||||
const Value *SV, int SVO, unsigned Align, bool Vol)
|
const Value *SV, int SVO, unsigned Align, bool Vol)
|
||||||
: MemSDNode(NodeTy, VTs, VT, SV, SVO, Align, Vol) {
|
: MemSDNode(NodeTy, VTs, VT, SV, SVO, Align, Vol) {
|
||||||
SubclassData = AM;
|
SubclassData = AM;
|
||||||
for (unsigned i = 0; i != numOperands; ++i)
|
InitOperands(Ops, Operands, numOperands);
|
||||||
Ops[i] = Operands[i];
|
|
||||||
InitOperands(Ops, numOperands);
|
|
||||||
assert(Align != 0 && "Loads and stores should have non-zero aligment");
|
assert(Align != 0 && "Loads and stores should have non-zero aligment");
|
||||||
assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) &&
|
assert((getOffset().getOpcode() == ISD::UNDEF || isIndexed()) &&
|
||||||
"Only indexed loads and stores have a non-undef offset operand");
|
"Only indexed loads and stores have a non-undef offset operand");
|
||||||
|
@ -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 this is fp_round(fpextend), don't fold it, allow ourselves to be folded.
|
||||||
if (N->hasOneUse() &&
|
if (N->hasOneUse() &&
|
||||||
N->use_begin().getUse().getSDValue().getOpcode() == ISD::FP_ROUND)
|
N->use_begin()->getOpcode() == ISD::FP_ROUND)
|
||||||
return SDValue();
|
return SDValue();
|
||||||
|
|
||||||
// fold (fp_extend c1fp) -> c1fp
|
// fold (fp_extend c1fp) -> c1fp
|
||||||
|
@ -81,7 +81,7 @@ void DAGTypeLegalizer::PerformExpensiveChecks() {
|
|||||||
// Check that remapped values are only used by nodes marked NewNode.
|
// Check that remapped values are only used by nodes marked NewNode.
|
||||||
for (SDNode::use_iterator UI = I->use_begin(), UE = I->use_end();
|
for (SDNode::use_iterator UI = I->use_begin(), UE = I->use_end();
|
||||||
UI != UE; ++UI)
|
UI != UE; ++UI)
|
||||||
if (UI.getUse().getSDValue().getResNo() == i)
|
if (UI.getUse().getResNo() == i)
|
||||||
assert(UI->getNodeId() == NewNode &&
|
assert(UI->getNodeId() == NewNode &&
|
||||||
"Remapped value has non-trivial use!");
|
"Remapped value has non-trivial use!");
|
||||||
|
|
||||||
|
@ -342,8 +342,8 @@ static void AddNodeIDOperands(FoldingSetNodeID &ID,
|
|||||||
static void AddNodeIDOperands(FoldingSetNodeID &ID,
|
static void AddNodeIDOperands(FoldingSetNodeID &ID,
|
||||||
const SDUse *Ops, unsigned NumOps) {
|
const SDUse *Ops, unsigned NumOps) {
|
||||||
for (; NumOps; --NumOps, ++Ops) {
|
for (; NumOps; --NumOps, ++Ops) {
|
||||||
ID.AddPointer(Ops->getVal());
|
ID.AddPointer(Ops->getNode());
|
||||||
ID.AddInteger(Ops->getSDValue().getResNo());
|
ID.AddInteger(Ops->getResNo());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -538,8 +538,7 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes,
|
|||||||
// Process the worklist, deleting the nodes and adding their uses to the
|
// Process the worklist, deleting the nodes and adding their uses to the
|
||||||
// worklist.
|
// worklist.
|
||||||
while (!DeadNodes.empty()) {
|
while (!DeadNodes.empty()) {
|
||||||
SDNode *N = DeadNodes.back();
|
SDNode *N = DeadNodes.pop_back_val();
|
||||||
DeadNodes.pop_back();
|
|
||||||
|
|
||||||
if (UpdateListener)
|
if (UpdateListener)
|
||||||
UpdateListener->NodeDeleted(N, 0);
|
UpdateListener->NodeDeleted(N, 0);
|
||||||
@ -549,10 +548,11 @@ void SelectionDAG::RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes,
|
|||||||
|
|
||||||
// Next, brutally remove the operand list. This is safe to do, as there are
|
// Next, brutally remove the operand list. This is safe to do, as there are
|
||||||
// no cycles in the graph.
|
// no cycles in the graph.
|
||||||
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
|
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) {
|
||||||
SDNode *Operand = I->getVal();
|
SDUse &Use = *I++;
|
||||||
Operand->removeUser(std::distance(N->op_begin(), I), N);
|
SDNode *Operand = Use.getNode();
|
||||||
|
Use.set(SDValue());
|
||||||
|
|
||||||
// Now that we removed this operand, see if there are no uses of it left.
|
// Now that we removed this operand, see if there are no uses of it left.
|
||||||
if (Operand->use_empty())
|
if (Operand->use_empty())
|
||||||
DeadNodes.push_back(Operand);
|
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!");
|
assert(N->use_empty() && "Cannot delete a node that is not dead!");
|
||||||
|
|
||||||
// Drop all of the operands and decrement used node's use counts.
|
// 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)
|
N->DropOperands();
|
||||||
I->getVal()->removeUser(std::distance(N->op_begin(), I), N);
|
|
||||||
|
|
||||||
DeallocateNode(N);
|
DeallocateNode(N);
|
||||||
}
|
}
|
||||||
@ -763,7 +762,7 @@ void SelectionDAG::VerifyNode(SDNode *N) {
|
|||||||
// following checks at least makes it possible to legalize most of the time.
|
// following checks at least makes it possible to legalize most of the time.
|
||||||
// MVT EltVT = N->getValueType(0).getVectorElementType();
|
// MVT EltVT = N->getValueType(0).getVectorElementType();
|
||||||
// for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
|
// 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!");
|
// "Wrong operand type!");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -819,7 +818,7 @@ void SelectionDAG::clear() {
|
|||||||
std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(),
|
std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(),
|
||||||
static_cast<SDNode*>(0));
|
static_cast<SDNode*>(0));
|
||||||
|
|
||||||
EntryNode.Uses = 0;
|
EntryNode.UseList = 0;
|
||||||
AllNodes.push_back(&EntryNode);
|
AllNodes.push_back(&EntryNode);
|
||||||
Root = getEntryNode();
|
Root = getEntryNode();
|
||||||
}
|
}
|
||||||
@ -3915,9 +3914,7 @@ SDValue SelectionDAG::UpdateNodeOperands(SDValue InN, SDValue Op) {
|
|||||||
InsertPos = 0;
|
InsertPos = 0;
|
||||||
|
|
||||||
// Now we update the operands.
|
// Now we update the operands.
|
||||||
N->OperandList[0].getVal()->removeUser(0, N);
|
N->OperandList[0].set(Op);
|
||||||
N->OperandList[0].getSDValue() = Op;
|
|
||||||
Op.getNode()->addUser(0, N);
|
|
||||||
|
|
||||||
// If this gets put into a CSE map, add it.
|
// If this gets put into a CSE map, add it.
|
||||||
if (InsertPos) CSEMap.InsertNode(N, InsertPos);
|
if (InsertPos) CSEMap.InsertNode(N, InsertPos);
|
||||||
@ -3944,16 +3941,10 @@ UpdateNodeOperands(SDValue InN, SDValue Op1, SDValue Op2) {
|
|||||||
InsertPos = 0;
|
InsertPos = 0;
|
||||||
|
|
||||||
// Now we update the operands.
|
// Now we update the operands.
|
||||||
if (N->OperandList[0] != Op1) {
|
if (N->OperandList[0] != Op1)
|
||||||
N->OperandList[0].getVal()->removeUser(0, N);
|
N->OperandList[0].set(Op1);
|
||||||
N->OperandList[0].getSDValue() = Op1;
|
if (N->OperandList[1] != Op2)
|
||||||
Op1.getNode()->addUser(0, N);
|
N->OperandList[1].set(Op2);
|
||||||
}
|
|
||||||
if (N->OperandList[1] != Op2) {
|
|
||||||
N->OperandList[1].getVal()->removeUser(1, N);
|
|
||||||
N->OperandList[1].getSDValue() = Op2;
|
|
||||||
Op2.getNode()->addUser(1, N);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this gets put into a CSE map, add it.
|
// If this gets put into a CSE map, add it.
|
||||||
if (InsertPos) CSEMap.InsertNode(N, InsertPos);
|
if (InsertPos) CSEMap.InsertNode(N, InsertPos);
|
||||||
@ -4009,13 +4000,9 @@ UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) {
|
|||||||
InsertPos = 0;
|
InsertPos = 0;
|
||||||
|
|
||||||
// Now we update the operands.
|
// Now we update the operands.
|
||||||
for (unsigned i = 0; i != NumOps; ++i) {
|
for (unsigned i = 0; i != NumOps; ++i)
|
||||||
if (N->OperandList[i] != Ops[i]) {
|
if (N->OperandList[i] != Ops[i])
|
||||||
N->OperandList[i].getVal()->removeUser(i, N);
|
N->OperandList[i].set(Ops[i]);
|
||||||
N->OperandList[i].getSDValue() = Ops[i];
|
|
||||||
Ops[i].getNode()->addUser(i, N);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this gets put into a CSE map, add it.
|
// If this gets put into a CSE map, add it.
|
||||||
if (InsertPos) CSEMap.InsertNode(N, InsertPos);
|
if (InsertPos) CSEMap.InsertNode(N, InsertPos);
|
||||||
@ -4027,10 +4014,10 @@ UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) {
|
|||||||
void SDNode::DropOperands() {
|
void SDNode::DropOperands() {
|
||||||
// Unlike the code in MorphNodeTo that does this, we don't need to
|
// Unlike the code in MorphNodeTo that does this, we don't need to
|
||||||
// watch for dead nodes here.
|
// watch for dead nodes here.
|
||||||
for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
|
for (op_iterator I = op_begin(), E = op_end(); I != E; ) {
|
||||||
I->getVal()->removeUser(std::distance(op_begin(), I), this);
|
SDUse &Use = *I++;
|
||||||
|
Use.set(SDValue());
|
||||||
NumOperands = 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SelectNodeTo - These are wrappers around MorphNodeTo that accept a
|
/// 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
|
// 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.
|
// use list. Keep track of any operands that become dead as a result.
|
||||||
SmallPtrSet<SDNode*, 16> DeadNodeSet;
|
SmallPtrSet<SDNode*, 16> DeadNodeSet;
|
||||||
for (SDNode::op_iterator B = N->op_begin(), I = B, E = N->op_end();
|
for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ) {
|
||||||
I != E; ++I) {
|
SDUse &Use = *I++;
|
||||||
SDNode *Used = I->getVal();
|
SDNode *Used = Use.getNode();
|
||||||
Used->removeUser(std::distance(B, I), N);
|
Use.set(SDValue());
|
||||||
if (Used->use_empty())
|
if (Used->use_empty())
|
||||||
DeadNodeSet.insert(Used);
|
DeadNodeSet.insert(Used);
|
||||||
}
|
}
|
||||||
@ -4284,10 +4271,8 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
|
|||||||
// Assign the new operands.
|
// Assign the new operands.
|
||||||
N->NumOperands = NumOps;
|
N->NumOperands = NumOps;
|
||||||
for (unsigned i = 0, e = NumOps; i != e; ++i) {
|
for (unsigned i = 0, e = NumOps; i != e; ++i) {
|
||||||
N->OperandList[i].getSDValue() = Ops[i];
|
|
||||||
N->OperandList[i].setUser(N);
|
N->OperandList[i].setUser(N);
|
||||||
SDNode *ToUse = N->OperandList[i].getVal();
|
N->OperandList[i].setInitial(Ops[i]);
|
||||||
ToUse->addUser(i, N);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete any nodes that are still dead after adding the uses for the
|
// 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
|
// To help reduce the number of CSE recomputations, process all
|
||||||
// the uses of this user that we can find this way.
|
// the uses of this user that we can find this way.
|
||||||
do {
|
do {
|
||||||
unsigned operandNum = UI.getOperandNo();
|
SDUse &Use = UI.getUse();
|
||||||
++UI;
|
++UI;
|
||||||
From->removeUser(operandNum, User);
|
Use.set(To);
|
||||||
User->OperandList[operandNum].getSDValue() = To;
|
|
||||||
To.getNode()->addUser(operandNum, User);
|
|
||||||
} while (UI != UE && *UI == User);
|
} while (UI != UE && *UI == User);
|
||||||
|
|
||||||
// Now that we have modified User, add it back to the CSE maps. If it
|
// 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
|
// To help reduce the number of CSE recomputations, process all
|
||||||
// the uses of this user that we can find this way.
|
// the uses of this user that we can find this way.
|
||||||
do {
|
do {
|
||||||
unsigned operandNum = UI.getOperandNo();
|
SDUse &Use = UI.getUse();
|
||||||
++UI;
|
++UI;
|
||||||
From->removeUser(operandNum, User);
|
Use.setNode(To);
|
||||||
User->OperandList[operandNum].getSDValue().setNode(To);
|
|
||||||
To->addUser(operandNum, User);
|
|
||||||
} while (UI != UE && *UI == User);
|
} while (UI != UE && *UI == User);
|
||||||
|
|
||||||
// Now that we have modified User, add it back to the CSE maps. If it
|
// 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
|
// To help reduce the number of CSE recomputations, process all
|
||||||
// the uses of this user that we can find this way.
|
// the uses of this user that we can find this way.
|
||||||
do {
|
do {
|
||||||
unsigned operandNum = UI.getOperandNo();
|
SDUse &Use = UI.getUse();
|
||||||
const SDValue &ToOp =
|
const SDValue &ToOp = To[Use.getResNo()];
|
||||||
To[User->OperandList[operandNum].getSDValue().getResNo()];
|
|
||||||
++UI;
|
++UI;
|
||||||
From->removeUser(operandNum, User);
|
Use.set(ToOp);
|
||||||
User->OperandList[operandNum].getSDValue() = ToOp;
|
|
||||||
ToOp.getNode()->addUser(operandNum, User);
|
|
||||||
} while (UI != UE && *UI == User);
|
} while (UI != UE && *UI == User);
|
||||||
|
|
||||||
// Now that we have modified User, add it back to the CSE maps. If it
|
// 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
|
/// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving
|
||||||
/// uses of other values produced by From.getVal() alone. The Deleted vector is
|
/// uses of other values produced by From.getNode() alone. The Deleted
|
||||||
/// handled the same way as for ReplaceAllUsesWith.
|
/// vector is handled the same way as for ReplaceAllUsesWith.
|
||||||
void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To,
|
void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To,
|
||||||
DAGUpdateListener *UpdateListener){
|
DAGUpdateListener *UpdateListener){
|
||||||
// Handle the really simple, really trivial case efficiently.
|
// 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
|
// To help reduce the number of CSE recomputations, process all
|
||||||
// the uses of this user that we can find this way.
|
// the uses of this user that we can find this way.
|
||||||
do {
|
do {
|
||||||
unsigned operandNum = UI.getOperandNo();
|
SDUse &Use = UI.getUse();
|
||||||
|
|
||||||
// Skip uses of different values from the same node.
|
// Skip uses of different values from the same node.
|
||||||
if (User->OperandList[operandNum].getSDValue().getResNo() !=
|
if (Use.getResNo() != From.getResNo()) {
|
||||||
From.getResNo()) {
|
|
||||||
++UI;
|
++UI;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -4581,9 +4558,7 @@ void SelectionDAG::ReplaceAllUsesOfValueWith(SDValue From, SDValue To,
|
|||||||
}
|
}
|
||||||
|
|
||||||
++UI;
|
++UI;
|
||||||
From.getNode()->removeUser(operandNum, User);
|
Use.set(To);
|
||||||
User->OperandList[operandNum].getSDValue() = To;
|
|
||||||
To.getNode()->addUser(operandNum, User);
|
|
||||||
} while (UI != UE && *UI == User);
|
} while (UI != UE && *UI == User);
|
||||||
|
|
||||||
// We are iterating over all uses of the From node, so if a use
|
// We are iterating over all uses of the From node, so if a use
|
||||||
@ -4603,13 +4578,18 @@ namespace {
|
|||||||
struct UseMemo {
|
struct UseMemo {
|
||||||
SDNode *User;
|
SDNode *User;
|
||||||
unsigned Index;
|
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
|
/// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving
|
||||||
/// uses of other values produced by From.getVal() alone. The same value may
|
/// uses of other values produced by From.getNode() alone. The same value
|
||||||
/// appear in both the From and To list. The Deleted vector is
|
/// may appear in both the From and To list. The Deleted vector is
|
||||||
/// handled the same way as for ReplaceAllUsesWith.
|
/// handled the same way as for ReplaceAllUsesWith.
|
||||||
void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
|
void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
|
||||||
const SDValue *To,
|
const SDValue *To,
|
||||||
@ -4627,13 +4607,18 @@ void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDValue *From,
|
|||||||
unsigned FromResNo = From[i].getResNo();
|
unsigned FromResNo = From[i].getResNo();
|
||||||
SDNode *FromNode = From[i].getNode();
|
SDNode *FromNode = From[i].getNode();
|
||||||
for (SDNode::use_iterator UI = FromNode->use_begin(),
|
for (SDNode::use_iterator UI = FromNode->use_begin(),
|
||||||
E = FromNode->use_end(); UI != E; ++UI)
|
E = FromNode->use_end(); UI != E; ++UI) {
|
||||||
if (UI.getUse().getSDValue().getResNo() == FromResNo) {
|
SDUse &Use = UI.getUse();
|
||||||
UseMemo Memo = { *UI, i, UI.getOperandNo() };
|
if (Use.getResNo() == FromResNo) {
|
||||||
|
UseMemo Memo = { *UI, i, &Use };
|
||||||
Uses.push_back(Memo);
|
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();
|
for (unsigned UseIndex = 0, UseIndexEnd = Uses.size();
|
||||||
UseIndex != UseIndexEnd; ) {
|
UseIndex != UseIndexEnd; ) {
|
||||||
// We know that this user uses some value of From. If it is the right
|
// 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.
|
// This node is about to morph, remove its old self from the CSE maps.
|
||||||
RemoveNodeFromCSEMaps(User);
|
RemoveNodeFromCSEMaps(User);
|
||||||
|
|
||||||
// A user can appear in a use list multiple times, and when this
|
// The Uses array is sorted, so all the uses for a given User
|
||||||
// happens the uses are usually next to each other in the list.
|
// are next to each other in the list.
|
||||||
// To help reduce the number of CSE recomputations, process all
|
// To help reduce the number of CSE recomputations, process all
|
||||||
// the uses of this user that we can find this way.
|
// the uses of this user that we can find this way.
|
||||||
do {
|
do {
|
||||||
unsigned i = Uses[UseIndex].Index;
|
unsigned i = Uses[UseIndex].Index;
|
||||||
unsigned operandNum = Uses[UseIndex].operandNum;
|
SDUse &Use = *Uses[UseIndex].Use;
|
||||||
++UseIndex;
|
++UseIndex;
|
||||||
|
|
||||||
From[i].getNode()->removeUser(operandNum, User);
|
Use.set(To[i]);
|
||||||
User->OperandList[operandNum].getSDValue() = To[i];
|
|
||||||
To[i].getNode()->addUser(operandNum, User);
|
|
||||||
} while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User);
|
} while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User);
|
||||||
|
|
||||||
// Now that we have modified User, add it back to the CSE maps. If it
|
// 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
|
// 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) {
|
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)
|
if (NUses == 0)
|
||||||
return false;
|
return false;
|
||||||
--NUses;
|
--NUses;
|
||||||
@ -4857,7 +4840,7 @@ bool SDNode::hasAnyUseOfValue(unsigned Value) const {
|
|||||||
assert(Value < getNumValues() && "Bad value!");
|
assert(Value < getNumValues() && "Bad value!");
|
||||||
|
|
||||||
for (SDNode::use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI)
|
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 true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -4890,7 +4873,7 @@ bool SDValue::isOperandOf(SDNode *N) const {
|
|||||||
|
|
||||||
bool SDNode::isOperandOf(SDNode *N) const {
|
bool SDNode::isOperandOf(SDNode *N) const {
|
||||||
for (unsigned i = 0, e = N->NumOperands; i != e; ++i)
|
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 true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2160,7 +2160,8 @@ bool X86::isPSHUFLWMask(SDNode *N) {
|
|||||||
|
|
||||||
/// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to SHUFP*.
|
/// specifies a shuffle of elements that is suitable for input to SHUFP*.
|
||||||
static bool isSHUFPMask(SDOperandPtr Elems, unsigned NumElems) {
|
template<class SDOperand>
|
||||||
|
static bool isSHUFPMask(SDOperand *Elems, unsigned NumElems) {
|
||||||
if (NumElems != 2 && NumElems != 4) return false;
|
if (NumElems != 2 && NumElems != 4) return false;
|
||||||
|
|
||||||
unsigned Half = NumElems / 2;
|
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
|
/// 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
|
/// half elements to come from vector 1 (which would equal the dest.) and
|
||||||
/// the upper half to come from vector 2.
|
/// the upper half to come from vector 2.
|
||||||
static bool isCommutedSHUFP(SDOperandPtr Ops, unsigned NumOps) {
|
template<class SDOperand>
|
||||||
|
static bool isCommutedSHUFP(SDOperand *Ops, unsigned NumOps) {
|
||||||
if (NumOps != 2 && NumOps != 4) return false;
|
if (NumOps != 2 && NumOps != 4) return false;
|
||||||
|
|
||||||
unsigned Half = NumOps / 2;
|
unsigned Half = NumOps / 2;
|
||||||
@ -2277,7 +2279,8 @@ bool X86::isMOVHPMask(SDNode *N) {
|
|||||||
|
|
||||||
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to UNPCKL.
|
/// specifies a shuffle of elements that is suitable for input to UNPCKL.
|
||||||
bool static isUNPCKLMask(SDOperandPtr Elts, unsigned NumElts,
|
template<class SDOperand>
|
||||||
|
bool static isUNPCKLMask(SDOperand *Elts, unsigned NumElts,
|
||||||
bool V2IsSplat = false) {
|
bool V2IsSplat = false) {
|
||||||
if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
|
if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
|
||||||
return false;
|
return false;
|
||||||
@ -2306,7 +2309,8 @@ bool X86::isUNPCKLMask(SDNode *N, bool V2IsSplat) {
|
|||||||
|
|
||||||
/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to UNPCKH.
|
/// specifies a shuffle of elements that is suitable for input to UNPCKH.
|
||||||
bool static isUNPCKHMask(SDOperandPtr Elts, unsigned NumElts,
|
template<class SDOperand>
|
||||||
|
bool static isUNPCKHMask(SDOperand *Elts, unsigned NumElts,
|
||||||
bool V2IsSplat = false) {
|
bool V2IsSplat = false) {
|
||||||
if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
|
if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16)
|
||||||
return false;
|
return false;
|
||||||
@ -2382,7 +2386,8 @@ bool X86::isUNPCKH_v_undef_Mask(SDNode *N) {
|
|||||||
/// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand
|
/// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand
|
||||||
/// specifies a shuffle of elements that is suitable for input to MOVSS,
|
/// specifies a shuffle of elements that is suitable for input to MOVSS,
|
||||||
/// MOVSD, and MOVD, i.e. setting the lowest element.
|
/// MOVSD, and MOVD, i.e. setting the lowest element.
|
||||||
static bool isMOVLMask(SDOperandPtr Elts, unsigned NumElts) {
|
template<class SDOperand>
|
||||||
|
static bool isMOVLMask(SDOperand *Elts, unsigned NumElts) {
|
||||||
if (NumElts != 2 && NumElts != 4)
|
if (NumElts != 2 && NumElts != 4)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -2405,7 +2410,8 @@ bool X86::isMOVLMask(SDNode *N) {
|
|||||||
/// isCommutedMOVL - Returns true if the shuffle mask is except the reverse
|
/// 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
|
/// 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.
|
/// element of vector 2 and the other elements to come from vector 1 in order.
|
||||||
static bool isCommutedMOVL(SDOperandPtr Ops, unsigned NumOps,
|
template<class SDOperand>
|
||||||
|
static bool isCommutedMOVL(SDOperand *Ops, unsigned NumOps,
|
||||||
bool V2IsSplat = false,
|
bool V2IsSplat = false,
|
||||||
bool V2IsUndef = false) {
|
bool V2IsUndef = false) {
|
||||||
if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16)
|
if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16)
|
||||||
|
Loading…
Reference in New Issue
Block a user