improve comments.
[oota-llvm.git] / include / llvm / CodeGen / SelectionDAGNodes.h
index 7d748259cfacc4f3041419a779fc5d77e80d2fdd..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>
 
@@ -52,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
@@ -288,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
@@ -299,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
@@ -313,18 +319,21 @@ 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,
 
     // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing
@@ -356,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
@@ -1697,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,
@@ -1724,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,
@@ -1767,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) {
@@ -1787,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,
@@ -1806,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) {
@@ -1830,41 +1886,27 @@ class ConstantPoolSDNode : public SDNode {
   } Val;
   int Offset;  // It's a MachineConstantPoolValue if top bit is set.
   unsigned Alignment;  // Minimum alignment requirement of CP (not log2 value).
-protected:
+  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) {
-    assert((int)Offset >= 0 && "Offset is too large");
-    Val.MachineCPVal = v;
-    Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-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) {
+             getSDVTList(VT)), Offset(o), Alignment(Align), TargetFlags(TF) {
     assert((int)Offset >= 0 && "Offset is too large");
     Val.MachineCPVal = v;
     Offset |= 1 << (sizeof(unsigned)*CHAR_BIT-1);
   }
 public:
+  
 
   bool isMachineConstantPoolEntry() const {
     return (int)Offset < 0;
@@ -1887,6 +1929,7 @@ public:
   // Return the alignment of this constant pool object, which is either 0 (for
   // default alignment) or the desired value.
   unsigned getAlignment() const { return Alignment; }
+  unsigned char getTargetFlags() const { return TargetFlags; }
 
   const Type *getType() const;
 
@@ -1899,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
@@ -1953,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)
@@ -1976,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)
@@ -1996,7 +2036,6 @@ public:
 
 class RegisterSDNode : public SDNode {
   unsigned Reg;
-protected:
   friend class SelectionDAG;
   RegisterSDNode(unsigned reg, MVT VT)
     : SDNode(ISD::Register, DebugLoc::getUnknownLoc(),
@@ -2017,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)
@@ -2039,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) {
@@ -2057,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) {
@@ -2077,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(),
@@ -2092,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)
@@ -2202,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(),
@@ -2222,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; }
@@ -2250,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);
@@ -2271,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(),
@@ -2290,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
@@ -2337,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,
@@ -2367,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,