class MachineBasicBlock;
class MachineConstantPoolValue;
class SDNode;
+template <typename T> struct DenseMapKeyInfo;
template <typename T> struct simplify_type;
template <typename T> struct ilist_traits;
template<typename NodeTy, typename Traits> class iplist;
unsigned short NumVTs;
};
-
/// ISD namespace - This namespace contains an enum which represents all of the
/// SelectionDAG node types and value types.
///
namespace ISD {
+ namespace ParamFlags {
+ enum Flags {
+ NoFlagSet = 0,
+ ZExt = 1<<0, ///< Parameter should be zero extended
+ ZExtOffs = 0,
+ SExt = 1<<1, ///< Parameter should be sign extended
+ SExtOffs = 1,
+ InReg = 1<<2, ///< Parameter should be passed in register
+ InRegOffs = 2,
+ StructReturn = 1<<3, ///< Hidden struct-return pointer
+ StructReturnOffs = 3,
+ ByVal = 1<<4, ///< Struct passed by value
+ ByValOffs = 4,
+ OrigAlignment = 0x1F<<27,
+ OrigAlignmentOffs = 27
+ };
+ }
+
//===--------------------------------------------------------------------===//
/// ISD::NodeType enum - This enum defines all of the operators valid in a
/// SelectionDAG.
// Various leaf nodes.
STRING, BasicBlock, VALUETYPE, CONDCODE, Register,
Constant, ConstantFP,
- GlobalAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol,
+ GlobalAddress, GlobalTLSAddress, FrameIndex,
+ JumpTable, ConstantPool, ExternalSymbol,
// The address of the GOT
GLOBAL_OFFSET_TABLE,
// parent's frame or return address, and so on.
FRAMEADDR, RETURNADDR,
+ // FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to
+ // first (possible) on-stack argument. This is needed for correct stack
+ // adjustment during unwind.
+ FRAME_TO_ARGS_OFFSET,
+
+ // RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the
+ // address of the exception block on entry to an landing pad block.
+ EXCEPTIONADDR,
+
+ // RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node represents
+ // the selection index of the exception thrown.
+ EHSELECTION,
+
+ // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents
+ // 'eh_return' gcc dwarf builtin, which is used to return from
+ // exception. The general meaning is: adjust stack by OFFSET and pass
+ // execution to HANDLER. Many platform-related details also :)
+ EH_RETURN,
+
// TargetConstant* - Like Constant*, but the DAG does not do any folding or
// simplification of the constant.
TargetConstant,
// anything else with this node, and this is valid in the target-specific
// dag, turning into a GlobalAddress operand.
TargetGlobalAddress,
+ TargetGlobalTLSAddress,
TargetFrameIndex,
TargetJumpTable,
TargetConstantPool,
/// Bit 0 - signness
/// Bit 1 - 'inreg' attribute
/// Bit 2 - 'sret' attribute
+ /// Bits 31:27 - argument ABI alignment in the first argument piece and
+ /// alignment '1' in other argument pieces.
CALL,
// EXTRACT_ELEMENT - This is used to get the first or second (determined by
// Simple integer binary arithmetic operators.
ADD, SUB, MUL, SDIV, UDIV, SREM, UREM,
+ // CARRY_FALSE - This node is used when folding other nodes,
+ // like ADDC/SUBC, which indicate the carry result is always false.
+ CARRY_FALSE,
+
// Carry-setting nodes for multiple precision addition and subtraction.
// These nodes take two operands of the same value type, and produce two
// results. The first result is the normal add or sub result, the second
// FCOPYSIGN(f32, f64) is allowed.
FCOPYSIGN,
- /// VBUILD_VECTOR(ELT1, ELT2, ELT3, ELT4,..., COUNT,TYPE) - Return a vector
- /// with the specified, possibly variable, elements. The number of elements
- /// is required to be a power of two.
- VBUILD_VECTOR,
-
- /// BUILD_VECTOR(ELT1, ELT2, ELT3, ELT4,...) - Return a vector
+ /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector
/// with the specified, possibly variable, elements. The number of elements
/// is required to be a power of two.
BUILD_VECTOR,
- /// VINSERT_VECTOR_ELT(VECTOR, VAL, IDX, COUNT,TYPE) - Given a vector
- /// VECTOR, an element ELEMENT, and a (potentially variable) index IDX,
- /// return an vector with the specified element of VECTOR replaced with VAL.
- /// COUNT and TYPE specify the type of vector, as is standard for V* nodes.
- VINSERT_VECTOR_ELT,
-
- /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR (a legal packed
- /// type) with the element at IDX replaced with VAL.
+ /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element
+ /// at IDX replaced with VAL.
INSERT_VECTOR_ELT,
- /// VEXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR
- /// (an MVT::Vector value) identified by the (potentially variable) element
- /// number IDX.
- VEXTRACT_VECTOR_ELT,
-
/// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR
- /// (a legal packed type vector) identified by the (potentially variable)
- /// element number IDX.
+ /// identified by the (potentially variable) element number IDX.
EXTRACT_VECTOR_ELT,
- /// VVECTOR_SHUFFLE(VEC1, VEC2, SHUFFLEVEC, COUNT,TYPE) - Returns a vector,
- /// of the same type as VEC1/VEC2. SHUFFLEVEC is a VBUILD_VECTOR of
- /// constant int values that indicate which value each result element will
- /// get. The elements of VEC1/VEC2 are enumerated in order. This is quite
- /// similar to the Altivec 'vperm' instruction, except that the indices must
- /// be constants and are in terms of the element size of VEC1/VEC2, not in
- /// terms of bytes.
- VVECTOR_SHUFFLE,
-
+ /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of
+ /// vector type with the same length and element type, this produces a
+ /// concatenated vector result value, with length equal to the sum of the
+ /// lengths of the input vectors.
+ CONCAT_VECTORS,
+
+ /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an
+ /// vector value) starting with the (potentially variable) element number
+ /// IDX, which must be a multiple of the result vector length.
+ EXTRACT_SUBVECTOR,
+
/// VECTOR_SHUFFLE(VEC1, VEC2, SHUFFLEVEC) - Returns a vector, of the same
/// type as VEC1/VEC2. SHUFFLEVEC is a BUILD_VECTOR of constant int values
/// (regardless of whether its datatype is legal or not) that indicate
/// of the element size of VEC1/VEC2, not in terms of bytes.
VECTOR_SHUFFLE,
- /// X = VBIT_CONVERT(Y) and X = VBIT_CONVERT(Y, COUNT,TYPE) - This node
- /// represents a conversion from or to an ISD::Vector type.
- ///
- /// This is lowered to a BIT_CONVERT of the appropriate input/output types.
- /// The input and output are required to have the same size and at least one
- /// is required to be a vector (if neither is a vector, just use
- /// BIT_CONVERT).
- ///
- /// If the result is a vector, this takes three operands (like any other
- /// vector producer) which indicate the size and type of the vector result.
- /// Otherwise it takes one input.
- VBIT_CONVERT,
-
- /// BINOP(LHS, RHS, COUNT,TYPE)
- /// Simple abstract vector operators. Unlike the integer and floating point
- /// binary operators, these nodes also take two additional operands:
- /// a constant element count, and a value type node indicating the type of
- /// the elements. The order is count, type, op0, op1. All vector opcodes,
- /// including VLOAD and VConstant must currently have count and type as
- /// their last two operands.
- VADD, VSUB, VMUL, VSDIV, VUDIV,
- VAND, VOR, VXOR,
-
- /// VSELECT(COND,LHS,RHS, COUNT,TYPE) - Select for MVT::Vector values.
- /// COND is a boolean value. This node return LHS if COND is true, RHS if
- /// COND is false.
- VSELECT,
-
/// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a
/// scalar value into the low element of the resultant vector type. The top
/// elements of the vector are undefined.
// indexed memory ops).
LOAD, STORE,
- // Abstract vector version of LOAD. VLOAD has a constant element count as
- // the first operand, followed by a value type node indicating the type of
- // the elements, a token chain, a pointer operand, and a SRCVALUE node.
- VLOAD,
-
// TRUNCSTORE - This operators truncates (for integer) or rounds (for FP) a
// value and stores it to memory in one operation. This can be used for
// either integer or floating point operands. The first four operands of
TRUNCSTORE,
// DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned
- // to a specified boundary. The first operand is the token chain, the
- // second is the number of bytes to allocate, and the third is the alignment
- // boundary. The size is guaranteed to be a multiple of the stack
- // alignment, and the alignment is guaranteed to be bigger than the stack
+ // to a specified boundary. This node always has two return values: a new
+ // stack pointer value and a chain. The first operand is the token chain,
+ // the second is the number of bytes to allocate, and the third is the
+ // alignment boundary. The size is guaranteed to be a multiple of the stack
+ // alignment, and the alignment is guaranteed to be bigger than the stack
// alignment (if required) or 0 to get standard stack alignment.
DYNAMIC_STACKALLOC,
// Operand #0 : input chain.
// Operand #1 : module unique number use to identify the label.
LABEL,
-
+
// STACKSAVE - STACKSAVE has one operand, an input chain. It produces a
// value, the same type as the pointer type for the system, and an output
// chain.
};
+template<> struct DenseMapKeyInfo<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) {
+ return (unsigned)((uintptr_t)Val.Val >> 4) ^
+ (unsigned)((uintptr_t)Val.Val >> 9) + Val.ResNo;
+ }
+ 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<SDOperand> {
/// NodeType - The operation that this node performs.
///
unsigned short NodeType;
+
+ /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true,
+ /// then they will be delete[]'d when the node is destroyed.
+ bool OperandsNeedDelete : 1;
/// NodeId - Unique id per SDNode in the DAG.
int NodeId;
/// getOperationName - Return the opcode of this operation for printing.
///
- const char* getOperationName(const SelectionDAG *G = 0) const;
+ std::string getOperationName(const SelectionDAG *G = 0) const;
static const char* getIndexedModeName(ISD::MemIndexedMode AM);
void dump() const;
void dump(const SelectionDAG *G) const;
/// getValueTypeList - Return a pointer to the specified value type.
///
static MVT::ValueType *getValueTypeList(MVT::ValueType VT);
-
- SDNode(unsigned NT, MVT::ValueType VT) : NodeType(NT), NodeId(-1) {
- OperandList = 0; NumOperands = 0;
- ValueList = getValueTypeList(VT);
- NumValues = 1;
- Prev = 0; Next = 0;
- }
- SDNode(unsigned NT, SDOperand Op)
- : NodeType(NT), NodeId(-1) {
- OperandList = new SDOperand[1];
- OperandList[0] = Op;
- NumOperands = 1;
- Op.Val->Uses.push_back(this);
- ValueList = 0;
- NumValues = 0;
- Prev = 0; Next = 0;
- }
- SDNode(unsigned NT, SDOperand N1, SDOperand N2)
- : NodeType(NT), NodeId(-1) {
- OperandList = new SDOperand[2];
- OperandList[0] = N1;
- OperandList[1] = N2;
- NumOperands = 2;
- N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this);
- ValueList = 0;
- NumValues = 0;
- Prev = 0; Next = 0;
- }
- SDNode(unsigned NT, SDOperand N1, SDOperand N2, SDOperand N3)
- : NodeType(NT), NodeId(-1) {
- OperandList = new SDOperand[3];
- OperandList[0] = N1;
- OperandList[1] = N2;
- OperandList[2] = N3;
- NumOperands = 3;
-
- N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this);
- N3.Val->Uses.push_back(this);
- ValueList = 0;
- NumValues = 0;
- Prev = 0; Next = 0;
+ static SDVTList getSDVTList(MVT::ValueType VT) {
+ SDVTList Ret = { getValueTypeList(VT), 1 };
+ return Ret;
}
- SDNode(unsigned NT, SDOperand N1, SDOperand N2, SDOperand N3, SDOperand N4)
- : NodeType(NT), NodeId(-1) {
- OperandList = new SDOperand[4];
- OperandList[0] = N1;
- OperandList[1] = N2;
- OperandList[2] = N3;
- OperandList[3] = N4;
- NumOperands = 4;
-
- N1.Val->Uses.push_back(this); N2.Val->Uses.push_back(this);
- N3.Val->Uses.push_back(this); N4.Val->Uses.push_back(this);
- ValueList = 0;
- NumValues = 0;
- Prev = 0; Next = 0;
- }
- SDNode(unsigned Opc, const SDOperand *Ops, unsigned NumOps)
+
+ SDNode(unsigned Opc, SDVTList VTs, const SDOperand *Ops, unsigned NumOps)
: NodeType(Opc), NodeId(-1) {
+ OperandsNeedDelete = true;
NumOperands = NumOps;
- OperandList = new SDOperand[NumOperands];
+ OperandList = NumOps ? new SDOperand[NumOperands] : 0;
- for (unsigned i = 0, e = NumOps; i != e; ++i) {
+ for (unsigned i = 0; i != NumOps; ++i) {
OperandList[i] = Ops[i];
- SDNode *N = OperandList[i].Val;
- N->Uses.push_back(this);
+ Ops[i].Val->Uses.push_back(this);
}
- ValueList = 0;
- NumValues = 0;
+
+ ValueList = VTs.VTs;
+ NumValues = VTs.NumVTs;
Prev = 0; Next = 0;
}
-
- /// MorphNodeTo - This clears the return value and operands list, and sets the
- /// opcode of the node to the specified value. This should only be used by
- /// the SelectionDAG class.
- void MorphNodeTo(unsigned Opc) {
- NodeType = Opc;
- ValueList = 0;
- NumValues = 0;
-
- // 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);
- delete [] OperandList;
- OperandList = 0;
+ SDNode(unsigned Opc, SDVTList VTs) : NodeType(Opc), NodeId(-1) {
+ OperandsNeedDelete = false; // Operands set with InitOperands.
NumOperands = 0;
+ OperandList = 0;
+
+ ValueList = VTs.VTs;
+ NumValues = VTs.NumVTs;
+ Prev = 0; Next = 0;
}
- void setValueTypes(SDVTList L) {
- assert(NumValues == 0 && "Should not have values yet!");
- ValueList = L.VTs;
- NumValues = L.NumVTs;
- }
-
- void setOperands(SDOperand Op0) {
- assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[1];
- OperandList[0] = Op0;
- NumOperands = 1;
- Op0.Val->Uses.push_back(this);
- }
- void setOperands(SDOperand Op0, SDOperand Op1) {
- assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[2];
- OperandList[0] = Op0;
- OperandList[1] = Op1;
- NumOperands = 2;
- Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
- }
- void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2) {
- assert(NumOperands == 0 && "Should not have operands yet!");
- OperandList = new SDOperand[3];
- OperandList[0] = Op0;
- OperandList[1] = Op1;
- OperandList[2] = Op2;
- NumOperands = 3;
- Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
- Op2.Val->Uses.push_back(this);
- }
- void setOperands(const SDOperand *Ops, unsigned NumOps) {
- assert(NumOperands == 0 && "Should not have operands yet!");
+ /// InitOperands - Initialize the operands list of this node with the
+ /// specified values, which are part of the node (thus they don't need to be
+ /// copied in or allocated).
+ void InitOperands(SDOperand *Ops, unsigned NumOps) {
+ assert(OperandList == 0 && "Operands already set!");
NumOperands = NumOps;
- OperandList = new SDOperand[NumOperands];
-
- for (unsigned i = 0, e = NumOps; i != e; ++i) {
- OperandList[i] = Ops[i];
- SDNode *N = OperandList[i].Val;
- N->Uses.push_back(this);
- }
+ OperandList = Ops;
+
+ for (unsigned i = 0; i != NumOps; ++i)
+ Ops[i].Val->Uses.push_back(this);
}
-
+
+ /// 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.
+ void MorphNodeTo(unsigned Opc, SDVTList L,
+ const SDOperand *Ops, unsigned NumOps);
+
void addUser(SDNode *User) {
Uses.push_back(User);
}
return Val->hasNUsesOfValue(1, ResNo);
}
+/// UnarySDNode - This class is used for single-operand SDNodes. This is solely
+/// to allow co-allocation of node operands with the node itself.
+class UnarySDNode : public SDNode {
+ virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
+ SDOperand Op;
+public:
+ UnarySDNode(unsigned Opc, SDVTList VTs, SDOperand X)
+ : SDNode(Opc, VTs), Op(X) {
+ InitOperands(&Op, 1);
+ }
+};
+
+/// BinarySDNode - This class is used for two-operand SDNodes. This is solely
+/// to allow co-allocation of node operands with the node itself.
+class BinarySDNode : public SDNode {
+ virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
+ SDOperand Ops[2];
+public:
+ BinarySDNode(unsigned Opc, SDVTList VTs, SDOperand X, SDOperand Y)
+ : SDNode(Opc, VTs) {
+ Ops[0] = X;
+ Ops[1] = Y;
+ InitOperands(Ops, 2);
+ }
+};
+
+/// TernarySDNode - This class is used for three-operand SDNodes. This is solely
+/// to allow co-allocation of node operands with the node itself.
+class TernarySDNode : public SDNode {
+ virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
+ SDOperand Ops[3];
+public:
+ TernarySDNode(unsigned Opc, SDVTList VTs, SDOperand X, SDOperand Y,
+ SDOperand Z)
+ : SDNode(Opc, VTs) {
+ Ops[0] = X;
+ Ops[1] = Y;
+ Ops[2] = Z;
+ InitOperands(Ops, 3);
+ }
+};
+
+
/// HandleSDNode - This class is used to form a handle around another node that
/// is persistant and is updated across invocations of replaceAllUsesWith on its
/// operand. This node should be directly created by end-users and not added to
/// the AllNodes list.
class HandleSDNode : public SDNode {
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
+ SDOperand Op;
public:
- HandleSDNode(SDOperand X) : SDNode(ISD::HANDLENODE, X) {}
- ~HandleSDNode() {
- MorphNodeTo(ISD::HANDLENODE); // Drops operand uses.
+ explicit HandleSDNode(SDOperand X)
+ : SDNode(ISD::HANDLENODE, getSDVTList(MVT::Other)), Op(X) {
+ InitOperands(&Op, 1);
}
-
- SDOperand getValue() const { return getOperand(0); }
+ ~HandleSDNode();
+ SDOperand getValue() const { return Op; }
};
class StringSDNode : public SDNode {
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- StringSDNode(const std::string &val)
- : SDNode(ISD::STRING, MVT::Other), Value(val) {
+ explicit StringSDNode(const std::string &val)
+ : SDNode(ISD::STRING, getSDVTList(MVT::Other)), Value(val) {
}
public:
const std::string &getValue() const { return Value; }
protected:
friend class SelectionDAG;
ConstantSDNode(bool isTarget, uint64_t val, MVT::ValueType VT)
- : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, VT), Value(val) {
+ : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, getSDVTList(VT)),
+ Value(val) {
}
public:
protected:
friend class SelectionDAG;
ConstantFPSDNode(bool isTarget, double val, MVT::ValueType VT)
- : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, VT),
- Value(val) {
+ : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP,
+ getSDVTList(VT)), Value(val) {
}
public:
protected:
friend class SelectionDAG;
GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT,
- int o=0)
- : SDNode(isTarget ? ISD::TargetGlobalAddress : ISD::GlobalAddress, VT),
- Offset(o) {
- TheGlobal = const_cast<GlobalValue*>(GA);
- }
+ int o = 0);
public:
GlobalValue *getGlobal() const { return TheGlobal; }
static bool classof(const GlobalAddressSDNode *) { return true; }
static bool classof(const SDNode *N) {
return N->getOpcode() == ISD::GlobalAddress ||
- N->getOpcode() == ISD::TargetGlobalAddress;
+ N->getOpcode() == ISD::TargetGlobalAddress ||
+ N->getOpcode() == ISD::GlobalTLSAddress ||
+ N->getOpcode() == ISD::TargetGlobalTLSAddress;
}
};
-
class FrameIndexSDNode : public SDNode {
int FI;
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
FrameIndexSDNode(int fi, MVT::ValueType VT, bool isTarg)
- : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, VT), FI(fi) {}
+ : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, getSDVTList(VT)),
+ FI(fi) {
+ }
public:
int getIndex() const { return FI; }
protected:
friend class SelectionDAG;
JumpTableSDNode(int jti, MVT::ValueType VT, bool isTarg)
- : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, VT),
- JTI(jti) {}
+ : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, getSDVTList(VT)),
+ JTI(jti) {
+ }
public:
int getIndex() const { return JTI; }
friend class SelectionDAG;
ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT,
int o=0)
- : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
- Offset(o), Alignment(0) {
+ : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
+ getSDVTList(VT)), Offset(o), Alignment(0) {
assert((int)Offset >= 0 && "Offset is too large");
Val.ConstVal = c;
}
ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT, int o,
unsigned Align)
- : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
- Offset(o), Alignment(Align) {
+ : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
+ getSDVTList(VT)), Offset(o), Alignment(Align) {
assert((int)Offset >= 0 && "Offset is too large");
Val.ConstVal = c;
}
ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
MVT::ValueType VT, int o=0)
- : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
- Offset(o), Alignment(0) {
+ : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
+ getSDVTList(VT)), Offset(o), Alignment(0) {
assert((int)Offset >= 0 && "Offset is too large");
Val.MachineCPVal = v;
Offset |= 1 << (sizeof(unsigned)*8-1);
}
ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
MVT::ValueType VT, int o, unsigned Align)
- : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, VT),
- Offset(o), Alignment(Align) {
+ : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
+ getSDVTList(VT)), Offset(o), Alignment(Align) {
assert((int)Offset >= 0 && "Offset is too large");
Val.MachineCPVal = v;
Offset |= 1 << (sizeof(unsigned)*8-1);
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- BasicBlockSDNode(MachineBasicBlock *mbb)
- : SDNode(ISD::BasicBlock, MVT::Other), MBB(mbb) {}
+ explicit BasicBlockSDNode(MachineBasicBlock *mbb)
+ : SDNode(ISD::BasicBlock, getSDVTList(MVT::Other)), MBB(mbb) {
+ }
public:
MachineBasicBlock *getBasicBlock() const { return MBB; }
protected:
friend class SelectionDAG;
SrcValueSDNode(const Value* v, int o)
- : SDNode(ISD::SRCVALUE, MVT::Other), V(v), offset(o) {}
+ : SDNode(ISD::SRCVALUE, getSDVTList(MVT::Other)), V(v), offset(o) {
+ }
public:
const Value *getValue() const { return V; }
protected:
friend class SelectionDAG;
RegisterSDNode(unsigned reg, MVT::ValueType VT)
- : SDNode(ISD::Register, VT), Reg(reg) {}
+ : SDNode(ISD::Register, getSDVTList(VT)), Reg(reg) {
+ }
public:
unsigned getReg() const { return Reg; }
protected:
friend class SelectionDAG;
ExternalSymbolSDNode(bool isTarget, const char *Sym, MVT::ValueType VT)
- : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, VT),
- Symbol(Sym) {
- }
+ : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol,
+ getSDVTList(VT)), Symbol(Sym) {
+ }
public:
const char *getSymbol() const { return Symbol; }
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- CondCodeSDNode(ISD::CondCode Cond)
- : SDNode(ISD::CONDCODE, MVT::Other), Condition(Cond) {
+ explicit CondCodeSDNode(ISD::CondCode Cond)
+ : SDNode(ISD::CONDCODE, getSDVTList(MVT::Other)), Condition(Cond) {
}
public:
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
protected:
friend class SelectionDAG;
- VTSDNode(MVT::ValueType VT)
- : SDNode(ISD::VALUETYPE, MVT::Other), ValueType(VT) {}
+ explicit VTSDNode(MVT::ValueType VT)
+ : SDNode(ISD::VALUETYPE, getSDVTList(MVT::Other)), ValueType(VT) {
+ }
public:
MVT::ValueType getVT() const { return ValueType; }
///
class LoadSDNode : public SDNode {
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
-
+ SDOperand Ops[3];
+
// AddrMode - unindexed, pre-indexed, post-indexed.
ISD::MemIndexedMode AddrMode;
bool IsVolatile;
protected:
friend class SelectionDAG;
- LoadSDNode(SDOperand Chain, SDOperand Ptr, SDOperand Off,
+ LoadSDNode(SDOperand *ChainPtrOff, SDVTList VTs,
ISD::MemIndexedMode AM, ISD::LoadExtType ETy, MVT::ValueType LVT,
- const Value *SV, int O=0, unsigned Align=1, bool Vol=false)
- : SDNode(ISD::LOAD, Chain, Ptr, Off),
+ const Value *SV, int O=0, unsigned Align=0, bool Vol=false)
+ : SDNode(ISD::LOAD, VTs),
AddrMode(AM), ExtType(ETy), LoadedVT(LVT), SrcValue(SV), SVOffset(O),
Alignment(Align), IsVolatile(Vol) {
- assert((Off.getOpcode() == ISD::UNDEF || AddrMode != ISD::UNINDEXED) &&
+ Ops[0] = ChainPtrOff[0]; // Chain
+ Ops[1] = ChainPtrOff[1]; // Ptr
+ Ops[2] = ChainPtrOff[2]; // Off
+ InitOperands(Ops, 3);
+ assert(Align != 0 && "Loads should have non-zero aligment");
+ assert((getOffset().getOpcode() == ISD::UNDEF ||
+ AddrMode != ISD::UNINDEXED) &&
"Only indexed load has a non-undef offset operand");
}
public:
///
class StoreSDNode : public SDNode {
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
-
+ SDOperand Ops[4];
+
// AddrMode - unindexed, pre-indexed, post-indexed.
ISD::MemIndexedMode AddrMode;
bool IsVolatile;
protected:
friend class SelectionDAG;
- StoreSDNode(SDOperand Chain, SDOperand Value, SDOperand Ptr, SDOperand Off,
+ StoreSDNode(SDOperand *ChainValuePtrOff, SDVTList VTs,
ISD::MemIndexedMode AM, bool isTrunc, MVT::ValueType SVT,
const Value *SV, int O=0, unsigned Align=0, bool Vol=false)
- : SDNode(ISD::STORE, Chain, Value, Ptr, Off),
+ : SDNode(ISD::STORE, VTs),
AddrMode(AM), IsTruncStore(isTrunc), StoredVT(SVT), SrcValue(SV),
SVOffset(O), Alignment(Align), IsVolatile(Vol) {
- assert((Off.getOpcode() == ISD::UNDEF || AddrMode != ISD::UNINDEXED) &&
+ Ops[0] = ChainValuePtrOff[0]; // Chain
+ Ops[1] = ChainValuePtrOff[1]; // Value
+ Ops[2] = ChainValuePtrOff[2]; // Ptr
+ Ops[3] = ChainValuePtrOff[3]; // Off
+ InitOperands(Ops, 4);
+ assert(Align != 0 && "Stores should have non-zero aligment");
+ assert((getOffset().getOpcode() == ISD::UNDEF ||
+ AddrMode != ISD::UNINDEXED) &&
"Only indexed store has a non-undef offset operand");
}
public:
static void setNext(SDNode *N, SDNode *Next) { N->Next = Next; }
static SDNode *createSentinel() {
- return new SDNode(ISD::EntryToken, MVT::Other);
+ return new SDNode(ISD::EntryToken, SDNode::getSDVTList(MVT::Other));
}
static void destroySentinel(SDNode *N) { delete N; }
//static SDNode *createNode(const SDNode &V) { return new SDNode(V); }
cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD;
}
+ /// isUNINDEXEDLoad - Returns true if the specified node is a unindexed load.
+ ///
+ inline bool isUNINDEXEDLoad(const SDNode *N) {
+ return N->getOpcode() == ISD::LOAD &&
+ cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED;
+ }
+
/// isNON_TRUNCStore - Returns true if the specified node is a non-truncating
/// store.
inline bool isNON_TRUNCStore(const SDNode *N) {