improve comments.
[oota-llvm.git] / include / llvm / CodeGen / SelectionDAGNodes.h
index e945b983ef25abfb45872114e808d23c60e67c3e..62c3769ebe6124438576d010d78936f2b1c0958a 100644 (file)
 #include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/CodeGen/MachineMemOperand.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/RecyclingAllocator.h"
 #include "llvm/Support/DataTypes.h"
-#include "llvm/CodeGen/DebugLoc.h"
+#include "llvm/Support/DebugLoc.h"
 #include <cassert>
+#include <climits>
 
 namespace llvm {
 
@@ -51,7 +53,7 @@ template <typename T> struct ilist_traits;
 ///
 struct SDVTList {
   const MVT *VTs;
-  unsigned short NumVTs;
+  unsigned int NumVTs;
 };
 
 /// ISD namespace - This namespace contains an enum which represents all of the
@@ -75,7 +77,7 @@ namespace ISD {
   /// and getMachineOpcode() member functions of SDNode.
   ///
   enum NodeType {
-    // DELETED_NODE - This is an illegal flag value that is used to catch
+    // DELETED_NODE - This is an illegal value that is used to catch
     // errors.  This opcode is not a legal opcode for any node.
     DELETED_NODE,
 
@@ -287,9 +289,12 @@ namespace ISD {
     // value as an integer 0/1 value.
     FGETSIGN,
 
-    /// 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(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.  The types of the operands must all be
+    /// the same and must match the vector element type, except that integer
+    /// types are allowed to be larger than the element type, in which case
+    /// the operands are implicitly truncated.
     BUILD_VECTOR,
 
     /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element
@@ -298,7 +303,9 @@ namespace ISD {
     INSERT_VECTOR_ELT,
 
     /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR
-    /// identified by the (potentially variable) element number IDX.
+    /// identified by the (potentially variable) element number IDX.  If the
+    /// return type is an integer type larger than the element type of the
+    /// vector, the result is extended to the width of the return type.
     EXTRACT_VECTOR_ELT,
 
     /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of
@@ -312,32 +319,23 @@ namespace ISD {
     /// 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
-    /// (maybe of an illegal datatype) or undef 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.
+    /// VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as 
+    /// VEC1/VEC2.  A VECTOR_SHUFFLE node also contains an array of constant int 
+    /// values that indicate which value (or undef) each result element will
+    /// get.  These constant ints are accessible through the 
+    /// ShuffleVectorSDNode class.  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.
     VECTOR_SHUFFLE,
 
     /// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a
     /// scalar value into element 0 of the resultant vector type.  The top
-    /// elements 1 to N-1 of the N-element vector are undefined.
+    /// elements 1 to N-1 of the N-element vector are undefined.  The type
+    /// of the operand must match the vector element type, except when they
+    /// are integer types.  In this case the operand is allowed to be wider
+    /// than the vector element type, and is implicitly truncated to it.
     SCALAR_TO_VECTOR,
 
-    // EXTRACT_SUBREG - This node is used to extract a sub-register value.
-    // This node takes a superreg and a constant sub-register index as operands.
-    // Note sub-register indices must be increasing. That is, if the
-    // sub-register index of a 8-bit sub-register is N, then the index for a
-    // 16-bit sub-register must be at least N+1.
-    EXTRACT_SUBREG,
-
-    // INSERT_SUBREG - This node is used to insert a sub-register value.
-    // This node takes a superreg, a subreg value, and a constant sub-register
-    // index as operands.
-    INSERT_SUBREG,
-
     // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing
     // an unsigned/signed value of type i[2*N], then return the top part.
     MULHU, MULHS,
@@ -367,12 +365,11 @@ namespace ISD {
     // them with (op #2) as a CondCodeSDNode.
     SETCC,
 
-    // Vector SetCC operator - This evaluates to a vector of integer elements
-    // with the high bit in each element set to true if the comparison is true
-    // and false if the comparison is false.  All other bits in each element
-    // are undefined.  The operands to this are the left and right operands
-    // to compare (ops #0, and #1) and the condition code to compare them with
-    // (op #2) as a CondCodeSDNode.
+    // RESULT = VSETCC(LHS, RHS, COND) operator - This evaluates to a vector of
+    // integer elements with all bits of the result elements set to true if the
+    // comparison is true or all cleared if the comparison is false.  The
+    // operands to this are the left and right operands to compare (LHS/RHS) and
+    // the condition code to compare them with (COND) as a CondCodeSDNode.
     VSETCC,
 
     // SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded
@@ -1125,7 +1122,7 @@ public:
   unsigned getOpcode()  const { return (unsigned short)NodeType; }
 
   /// isTargetOpcode - Test if this node has a target-specific opcode (in the
-  /// <target>ISD namespace).
+  /// \<target\>ISD namespace).
   bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; }
 
   /// isMachineOpcode - Test if this node has a post-isel opcode, directly
@@ -1708,9 +1705,55 @@ public:
   }
 };
 
+/// ShuffleVectorSDNode - This SDNode is used to implement the code generator
+/// support for the llvm IR shufflevector instruction.  It combines elements
+/// from two input vectors into a new input vector, with the selection and
+/// ordering of elements determined by an array of integers, referred to as
+/// the shuffle mask.  For input vectors of width N, mask indices of 0..N-1
+/// refer to elements from the LHS input, and indices from N to 2N-1 the RHS.
+/// An index of -1 is treated as undef, such that the code generator may put
+/// any value in the corresponding element of the result.
+class ShuffleVectorSDNode : public SDNode {
+  SDUse Ops[2];
+
+  // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and
+  // is freed when the SelectionDAG object is destroyed.
+  const int *Mask;
+protected:
+  friend class SelectionDAG;
+  ShuffleVectorSDNode(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, 
+                      const int *M)
+    : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) {
+    InitOperands(Ops, N1, N2);
+  }
+public:
+
+  void getMask(SmallVectorImpl<int> &M) const {
+    MVT VT = getValueType(0);
+    M.clear();
+    for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i)
+      M.push_back(Mask[i]);
+  }
+  int getMaskElt(unsigned Idx) const {
+    assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!");
+    return Mask[Idx];
+  }
+  
+  bool isSplat() const { return isSplatMask(Mask, getValueType(0)); }
+  int  getSplatIndex() const { 
+    assert(isSplat() && "Cannot get splat index for non-splat!");
+    return Mask[0];
+  }
+  static bool isSplatMask(const int *Mask, MVT VT);
+
+  static bool classof(const ShuffleVectorSDNode *) { return true; }
+  static bool classof(const SDNode *N) {
+    return N->getOpcode() == ISD::VECTOR_SHUFFLE;
+  }
+};
+  
 class ConstantSDNode : public SDNode {
   const ConstantInt *Value;
-protected:
   friend class SelectionDAG;
   ConstantSDNode(bool isTarget, const ConstantInt *val, MVT VT)
     : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant,
@@ -1735,7 +1778,6 @@ public:
 
 class ConstantFPSDNode : public SDNode {
   const ConstantFP *Value;
-protected:
   friend class SelectionDAG;
   ConstantFPSDNode(bool isTarget, const ConstantFP *val, MVT VT)
     : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP,
@@ -1778,14 +1820,17 @@ public:
 class GlobalAddressSDNode : public SDNode {
   GlobalValue *TheGlobal;
   int64_t Offset;
-protected:
+  unsigned char TargetFlags;
   friend class SelectionDAG;
-  GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT VT,
-                      int64_t o = 0);
+  GlobalAddressSDNode(unsigned Opc, const GlobalValue *GA, MVT VT,
+                      int64_t o, unsigned char TargetFlags);
 public:
 
   GlobalValue *getGlobal() const { return TheGlobal; }
   int64_t getOffset() const { return Offset; }
+  unsigned char getTargetFlags() const { return TargetFlags; }
+  // Return the address space this GlobalAddress belongs to.
+  unsigned getAddressSpace() const;
 
   static bool classof(const GlobalAddressSDNode *) { return true; }
   static bool classof(const SDNode *N) {
@@ -1798,7 +1843,6 @@ public:
 
 class FrameIndexSDNode : public SDNode {
   int FI;
-protected:
   friend class SelectionDAG;
   FrameIndexSDNode(int fi, MVT VT, bool isTarg)
     : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex,
@@ -1817,15 +1861,16 @@ public:
 
 class JumpTableSDNode : public SDNode {
   int JTI;
-protected:
+  unsigned char TargetFlags;
   friend class SelectionDAG;
-  JumpTableSDNode(int jti, MVT VT, bool isTarg)
+  JumpTableSDNode(int jti, MVT VT, bool isTarg, unsigned char TF)
     : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable,
-      DebugLoc::getUnknownLoc(), getSDVTList(VT)), JTI(jti) {
+      DebugLoc::getUnknownLoc(), getSDVTList(VT)), JTI(jti), TargetFlags(TF) {
   }
 public:
 
   int getIndex() const { return JTI; }
+  unsigned char getTargetFlags() const { return TargetFlags; }
 
   static bool classof(const JumpTableSDNode *) { return true; }
   static bool classof(const SDNode *N) {
@@ -1840,42 +1885,28 @@ class ConstantPoolSDNode : public SDNode {
     MachineConstantPoolValue *MachineCPVal;
   } Val;
   int Offset;  // It's a MachineConstantPoolValue if top bit is set.
-  unsigned Alignment;
-protected:
+  unsigned Alignment;  // Minimum alignment requirement of CP (not log2 value).
+  unsigned char TargetFlags;
   friend class SelectionDAG;
-  ConstantPoolSDNode(bool isTarget, Constant *c, MVT VT, int o=0)
-    : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
-             DebugLoc::getUnknownLoc(),
-             getSDVTList(VT)), Offset(o), Alignment(0) {
-    assert((int)Offset >= 0 && "Offset is too large");
-    Val.ConstVal = c;
-  }
-  ConstantPoolSDNode(bool isTarget, Constant *c, MVT VT, int o, unsigned Align)
+  ConstantPoolSDNode(bool isTarget, Constant *c, MVT VT, int o, unsigned Align,
+                     unsigned char TF)
     : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
              DebugLoc::getUnknownLoc(),
-             getSDVTList(VT)), Offset(o), Alignment(Align) {
+             getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) {
     assert((int)Offset >= 0 && "Offset is too large");
     Val.ConstVal = c;
   }
   ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
-                     MVT VT, int o=0)
+                     MVT VT, int o, unsigned Align, unsigned char TF)
     : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
              DebugLoc::getUnknownLoc(),
-             getSDVTList(VT)), Offset(o), Alignment(0) {
+             getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) {
     assert((int)Offset >= 0 && "Offset is too large");
     Val.MachineCPVal = v;
-    Offset |= 1 << (sizeof(unsigned)*8-1);
-  }
-  ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v,
-                     MVT VT, int o, unsigned Align)
-    : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool,
-             DebugLoc::getUnknownLoc(),
-             getSDVTList(VT)), Offset(o), Alignment(Align) {
-    assert((int)Offset >= 0 && "Offset is too large");
-    Val.MachineCPVal = v;
-    Offset |= 1 << (sizeof(unsigned)*8-1);
+    Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1);
   }
 public:
+  
 
   bool isMachineConstantPoolEntry() const {
     return (int)Offset < 0;
@@ -1892,12 +1923,13 @@ public:
   }
 
   int getOffset() const {
-    return Offset & ~(1 << (sizeof(unsigned)*8-1));
+    return Offset & ~(1 << (sizeof(unsigned)*CHAR_BIT-1));
   }
 
   // Return the alignment of this constant pool object, which is either 0 (for
-  // default alignment) or log2 of the desired value.
+  // default alignment) or the desired value.
   unsigned getAlignment() const { return Alignment; }
+  unsigned char getTargetFlags() const { return TargetFlags; }
 
   const Type *getType() const;
 
@@ -1910,7 +1942,6 @@ public:
 
 class BasicBlockSDNode : public SDNode {
   MachineBasicBlock *MBB;
-protected:
   friend class SelectionDAG;
   /// Debug info is meaningful and potentially useful here, but we create
   /// blocks out of order when they're jumped to, which makes it a bit
@@ -1932,6 +1963,8 @@ public:
 /// BuildVectorSDNode - A "pseudo-class" with methods for operating on
 /// BUILD_VECTORs.
 class BuildVectorSDNode : public SDNode {
+  // These are constructed as SDNodes and then cast to BuildVectorSDNodes.
+  explicit BuildVectorSDNode();        // Do not implement
 public:
   /// isConstantSplat - Check if this is a constant splat, and if so, find the
   /// smallest element size that splats the vector.  If MinSplatBits is
@@ -1962,7 +1995,6 @@ public:
 ///
 class SrcValueSDNode : public SDNode {
   const Value *V;
-protected:
   friend class SelectionDAG;
   /// Create a SrcValue for a general value.
   explicit SrcValueSDNode(const Value *v)
@@ -1985,7 +2017,6 @@ public:
 /// and ISD::STORE have been lowered.
 ///
 class MemOperandSDNode : public SDNode {
-protected:
   friend class SelectionDAG;
   /// Create a MachineMemOperand node
   explicit MemOperandSDNode(const MachineMemOperand &mo)
@@ -2005,7 +2036,6 @@ public:
 
 class RegisterSDNode : public SDNode {
   unsigned Reg;
-protected:
   friend class SelectionDAG;
   RegisterSDNode(unsigned reg, MVT VT)
     : SDNode(ISD::Register, DebugLoc::getUnknownLoc(),
@@ -2026,7 +2056,6 @@ class DbgStopPointSDNode : public SDNode {
   unsigned Line;
   unsigned Column;
   Value *CU;
-protected:
   friend class SelectionDAG;
   DbgStopPointSDNode(SDValue ch, unsigned l, unsigned c,
                      Value *cu)
@@ -2048,7 +2077,6 @@ public:
 class LabelSDNode : public SDNode {
   SDUse Chain;
   unsigned LabelID;
-protected:
   friend class SelectionDAG;
 LabelSDNode(unsigned NodeTy, DebugLoc dl, SDValue ch, unsigned id)
     : SDNode(NodeTy, dl, getSDVTList(MVT::Other)), LabelID(id) {
@@ -2066,16 +2094,18 @@ public:
 
 class ExternalSymbolSDNode : public SDNode {
   const char *Symbol;
-protected:
+  unsigned char TargetFlags;
+  
   friend class SelectionDAG;
-  ExternalSymbolSDNode(bool isTarget, const char *Sym, MVT VT)
+  ExternalSymbolSDNode(bool isTarget, const char *Sym, unsigned char TF, MVT VT)
     : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol,
              DebugLoc::getUnknownLoc(),
-             getSDVTList(VT)), Symbol(Sym) {
+             getSDVTList(VT)), Symbol(Sym), TargetFlags(TF) {
   }
 public:
 
   const char *getSymbol() const { return Symbol; }
+  unsigned char getTargetFlags() const { return TargetFlags; }
 
   static bool classof(const ExternalSymbolSDNode *) { return true; }
   static bool classof(const SDNode *N) {
@@ -2086,7 +2116,6 @@ public:
 
 class CondCodeSDNode : public SDNode {
   ISD::CondCode Condition;
-protected:
   friend class SelectionDAG;
   explicit CondCodeSDNode(ISD::CondCode Cond)
     : SDNode(ISD::CONDCODE, DebugLoc::getUnknownLoc(),
@@ -2101,12 +2130,11 @@ public:
     return N->getOpcode() == ISD::CONDCODE;
   }
 };
-
+  
 /// CvtRndSatSDNode - NOTE: avoid using this node as this may disappear in the
 /// future and most targets don't support it.
 class CvtRndSatSDNode : public SDNode {
   ISD::CvtCode CvtCode;
-protected:
   friend class SelectionDAG;
   explicit CvtRndSatSDNode(MVT VT, DebugLoc dl, const SDValue *Ops,
                            unsigned NumOps, ISD::CvtCode Code)
@@ -2211,7 +2239,6 @@ namespace ISD {
 /// ARG_FLAGSSDNode - Leaf node holding parameter flags.
 class ARG_FLAGSSDNode : public SDNode {
   ISD::ArgFlagsTy TheFlags;
-protected:
   friend class SelectionDAG;
   explicit ARG_FLAGSSDNode(ISD::ArgFlagsTy Flags)
     : SDNode(ISD::ARG_FLAGS, DebugLoc::getUnknownLoc(),
@@ -2231,18 +2258,18 @@ class CallSDNode : public SDNode {
   unsigned CallingConv;
   bool IsVarArg;
   bool IsTailCall;
+  unsigned NumFixedArgs;
   // We might eventually want a full-blown Attributes for the result; that
   // will expand the size of the representation.  At the moment we only
   // need Inreg.
   bool Inreg;
-protected:
   friend class SelectionDAG;
   CallSDNode(unsigned cc, DebugLoc dl, bool isvararg, bool istailcall,
              bool isinreg, SDVTList VTs, const SDValue *Operands,
-             unsigned numOperands)
+             unsigned numOperands, unsigned numFixedArgs)
     : SDNode(ISD::CALL, dl, VTs, Operands, numOperands),
       CallingConv(cc), IsVarArg(isvararg), IsTailCall(istailcall),
-      Inreg(isinreg) {}
+      NumFixedArgs(numFixedArgs), Inreg(isinreg) {}
 public:
   unsigned getCallingConv() const { return CallingConv; }
   unsigned isVarArg() const { return IsVarArg; }
@@ -2259,6 +2286,12 @@ public:
   SDValue getCallee() const { return getOperand(1); }
 
   unsigned getNumArgs() const { return (getNumOperands() - 2) / 2; }
+  unsigned getNumFixedArgs() const {
+    if (isVarArg())
+      return NumFixedArgs;
+    else
+      return getNumArgs();
+  }
   SDValue getArg(unsigned i) const { return getOperand(2+2*i); }
   SDValue getArgFlagsVal(unsigned i) const {
     return getOperand(3+2*i);
@@ -2280,7 +2313,6 @@ public:
 /// to parameterize some operations.
 class VTSDNode : public SDNode {
   MVT ValueType;
-protected:
   friend class SelectionDAG;
   explicit VTSDNode(MVT VT)
     : SDNode(ISD::VALUETYPE, DebugLoc::getUnknownLoc(),
@@ -2299,7 +2331,6 @@ public:
 /// LSBaseSDNode - Base class for LoadSDNode and StoreSDNode
 ///
 class LSBaseSDNode : public MemSDNode {
-protected:
   //! Operand array for load and store
   /*!
     \note Moving this array to the base class captures more
@@ -2346,7 +2377,6 @@ public:
 /// LoadSDNode - This class is used to represent ISD::LOAD nodes.
 ///
 class LoadSDNode : public LSBaseSDNode {
-protected:
   friend class SelectionDAG;
   LoadSDNode(SDValue *ChainPtrOff, DebugLoc dl, SDVTList VTs,
              ISD::MemIndexedMode AM, ISD::LoadExtType ETy, MVT LVT,
@@ -2376,7 +2406,6 @@ public:
 /// StoreSDNode - This class is used to represent ISD::STORE nodes.
 ///
 class StoreSDNode : public LSBaseSDNode {
-protected:
   friend class SelectionDAG;
   StoreSDNode(SDValue *ChainValuePtrOff, DebugLoc dl, SDVTList VTs,
               ISD::MemIndexedMode AM, bool isTrunc, MVT SVT,