Long live the exception handling!
[oota-llvm.git] / include / llvm / CodeGen / SelectionDAGNodes.h
index e60c85684a9ab50ee1d46026e6b49ea7c30bc2b7..c96d516eca18dae437cd5af7cf1858b2bcf66313 100644 (file)
@@ -34,6 +34,7 @@ class GlobalValue;
 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;
@@ -48,11 +49,28 @@ struct SDVTList {
   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.
@@ -80,7 +98,8 @@ namespace ISD {
     // 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,
@@ -92,6 +111,25 @@ namespace ISD {
     // 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,
@@ -101,6 +139,7 @@ namespace ISD {
     // anything else with this node, and this is valid in the target-specific
     // dag, turning into a GlobalAddress operand.
     TargetGlobalAddress,
+    TargetGlobalTLSAddress,
     TargetFrameIndex,
     TargetJumpTable,
     TargetConstantPool,
@@ -159,6 +198,8 @@ namespace ISD {
     /// 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
@@ -182,6 +223,10 @@ namespace ISD {
     // 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
@@ -206,45 +251,30 @@ namespace ISD {
     // 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
@@ -254,34 +284,6 @@ namespace ISD {
     /// 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.
@@ -388,11 +390,6 @@ namespace ISD {
     // 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
@@ -401,10 +398,11 @@ namespace ISD {
     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,
 
@@ -455,7 +453,7 @@ namespace ISD {
     //   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.
@@ -742,6 +740,16 @@ public:
 };
 
 
+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> {
@@ -764,6 +772,10 @@ class SDNode : public FoldingSetNode {
   /// 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;
@@ -878,7 +890,7 @@ public:
 
   /// 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;
@@ -895,138 +907,54 @@ protected:
   /// 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);
   }
@@ -1075,19 +1003,63 @@ inline bool SDOperand::hasOneUse() const {
   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 {
@@ -1095,8 +1067,8 @@ 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; }
@@ -1112,7 +1084,8 @@ class ConstantSDNode : public SDNode {
 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:
 
@@ -1141,8 +1114,8 @@ class ConstantFPSDNode : public SDNode {
 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:
 
@@ -1168,11 +1141,7 @@ class GlobalAddressSDNode : public SDNode {
 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; }
@@ -1181,18 +1150,21 @@ public:
   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; }
@@ -1210,8 +1182,9 @@ class JumpTableSDNode : public SDNode {
 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; }
@@ -1235,30 +1208,30 @@ protected:
   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);
@@ -1301,8 +1274,9 @@ class BasicBlockSDNode : public SDNode {
   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; }
@@ -1320,7 +1294,8 @@ class SrcValueSDNode : public SDNode {
 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; }
@@ -1339,7 +1314,8 @@ class RegisterSDNode : public SDNode {
 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; }
@@ -1356,9 +1332,9 @@ class ExternalSymbolSDNode : public SDNode {
 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; }
@@ -1375,8 +1351,8 @@ class CondCodeSDNode : public SDNode {
   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:
 
@@ -1395,8 +1371,9 @@ class VTSDNode : public SDNode {
   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; }
@@ -1411,7 +1388,8 @@ public:
 ///
 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;
 
@@ -1434,13 +1412,19 @@ class LoadSDNode : public SDNode {
   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:
@@ -1466,7 +1450,8 @@ 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;
 
@@ -1489,13 +1474,20 @@ class StoreSDNode : public SDNode {
   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:
@@ -1579,7 +1571,7 @@ struct ilist_traits<SDNode> {
   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); }
@@ -1621,6 +1613,13 @@ namespace ISD {
       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) {