Grammer correction.
[oota-llvm.git] / include / llvm / CodeGen / SelectionDAGNodes.h
index 8d5cf1065623b0ac811658930c9d0dfb241a51b6..eb48ce8f6d1b688852a2810c8b61ca22709bce13 100644 (file)
@@ -22,7 +22,6 @@
 #include "llvm/CodeGen/ValueTypes.h"
 #include "llvm/Value.h"
 #include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/GraphTraits.h"
 #include "llvm/ADT/iterator"
 #include "llvm/Support/DataTypes.h"
 #include <cassert>
@@ -35,6 +34,9 @@ class GlobalValue;
 class MachineBasicBlock;
 class SDNode;
 template <typename T> struct simplify_type;
+template <typename T> struct ilist_traits;
+template<typename NodeTy, typename Traits> class iplist;
+template<typename NodeTy> class ilist_iterator;
 
 /// ISD namespace - This namespace contains an enum which represents all of the
 /// SelectionDAG node types and value types.
@@ -61,9 +63,14 @@ namespace ISD {
     AssertSext, AssertZext,
 
     // Various leaf nodes.
-    Constant, ConstantFP, GlobalAddress, FrameIndex, ConstantPool,
+    Constant, ConstantFP, STRING,
+    GlobalAddress, FrameIndex, ConstantPool,
     BasicBlock, ExternalSymbol, VALUETYPE, CONDCODE, Register,
     
+    // ConstantVec works like Constant or ConstantFP, except that it is not a
+    // leaf node.  All operands are either Constant or ConstantFP nodes.
+    ConstantVec,
+    
     // TargetConstant - Like Constant, but the DAG does not do any folding or
     // simplification of the constant.  This is used by the DAG->DAG selector.
     TargetConstant,
@@ -74,6 +81,7 @@ namespace ISD {
     TargetGlobalAddress,
     TargetFrameIndex,
     TargetConstantPool,
+    TargetExternalSymbol,
 
     // CopyToReg - This node has three operands: a chain, a register number to
     // set to this value, and a value.  
@@ -84,12 +92,6 @@ namespace ISD {
     // SelectionDAG.  The register is available from the RegSDNode object.
     CopyFromReg,
 
-    // ImplicitDef - This node indicates that the specified register is
-    // implicitly defined by some operation (e.g. its a live-in argument).  The
-    // two operands to this are the token chain coming in and the register.
-    // The only result is the token chain going out.
-    ImplicitDef,
-
     // UNDEF - An undefined node
     UNDEF,
 
@@ -103,10 +105,27 @@ namespace ISD {
     // two values of the same integer value type, this produces a value twice as
     // big.  Like EXTRACT_ELEMENT, this can only be used before legalization.
     BUILD_PAIR,
-
-
-    // Simple binary arithmetic operators.
+    
+    // MERGE_VALUES - This node takes multiple discrete operands and returns
+    // them all as its individual results.  This nodes has exactly the same
+    // number of inputs and outputs, and is only valid before legalization.
+    // This node is useful for some pieces of the code generator that want to
+    // think about a single node with multiple results, not multiple nodes.
+    MERGE_VALUES,
+
+    // Simple integer binary arithmetic operators.
     ADD, SUB, MUL, SDIV, UDIV, SREM, UREM,
+    
+    // Simple binary floating point operators.
+    FADD, FSUB, FMUL, FDIV, FREM,
+    
+    // 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 op0, op1, count, type.  All vector opcodes,
+    // including VLOAD, must currently have count and type as their 3rd and 4th
+    // arguments.
+    VADD, VSUB, VMUL,
 
     // 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.
@@ -158,6 +177,9 @@ namespace ISD {
     // ZERO_EXTEND - Used for integer types, zeroing the new bits.
     ZERO_EXTEND,
 
+    // ANY_EXTEND - Used for integer types.  The high bits are undefined.
+    ANY_EXTEND,
+    
     // TRUNCATE - Completely drop the high bits.
     TRUNCATE,
 
@@ -192,6 +214,14 @@ namespace ISD {
     // FP_EXTEND - Extend a smaller FP type into a larger FP type.
     FP_EXTEND,
 
+    // BIT_CONVERT - Theis operator converts between integer and FP values, as
+    // if one was stored to memory as integer and the other was loaded from the
+    // same address (or equivalently for vector format conversions, etc).  The 
+    // source and result are required to have the same bit size (e.g. 
+    // f32 <-> i32).  This can also be used for int-to-int or fp-to-fp 
+    // conversions, but that is a noop, deleted by getNode().
+    BIT_CONVERT,
+    
     // FNEG, FABS, FSQRT, FSIN, FCOS - Perform unary floating point negation,
     // absolute value, square root, sine and cosine operations.
     FNEG, FABS, FSQRT, FSIN, FCOS,
@@ -200,6 +230,11 @@ namespace ISD {
     // operand, then the same operands as an LLVM load/store instruction, then a
     // SRCVALUE node that provides alias analysis information.
     LOAD, STORE,
+    
+    // Abstract vector version of LOAD.  VLOAD has a token chain as the first
+    // operand, followed by a pointer operand, a constant element count, a value
+    // type node indicating the type of the elements, and a SRCVALUE node.
+    VLOAD,
 
     // EXTLOAD, SEXTLOAD, ZEXTLOAD - These three operators all load a value from
     // memory and extend them to a larger value (e.g. load a byte into a word
@@ -298,12 +333,39 @@ namespace ISD {
     // PCMARKER - This corresponds to the pcmarker intrinsic.
     PCMARKER,
 
+    // READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic.
+    // The only operand is a chain and a value and a chain are produced.  The
+    // value is the contents of the architecture specific cycle counter like 
+    // register (or other high accuracy low latency clock source)
+    READCYCLECOUNTER,
+
     // READPORT, WRITEPORT, READIO, WRITEIO - These correspond to the LLVM
     // intrinsics of the same name.  The first operand is a token chain, the
     // other operands match the intrinsic.  These produce a token chain in
     // addition to a value (if any).
     READPORT, WRITEPORT, READIO, WRITEIO,
-
+    
+    // HANDLENODE node - Used as a handle for various purposes.
+    HANDLENODE,
+
+    // LOCATION - This node is used to represent a source location for debug
+    // info.  It takes token chain as input, then a line number, then a column
+    // number, then a filename, then a working dir.  It produces a token chain
+    // as output.
+    LOCATION,
+    
+    // DEBUG_LOC - This node is used to represent source line information
+    // embedded in the code.  It takes a token chain as input, then a line
+    // number, then a column then a file id (provided by MachineDebugInfo.) It
+    // produces a token chain as output.
+    DEBUG_LOC,
+    
+    // DEBUG_LABEL - This node is used to mark a location in the code where a
+    // label should be generated for use by the debug information.  It takes a
+    // token chain as input and then a unique id (provided by MachineDebugInfo.)
+    // It produces a token chain as output.
+    DEBUG_LABEL,
+    
     // BUILTIN_OP_END - This must be the last enum value in this list.
     BUILTIN_OP_END,
   };
@@ -481,19 +543,30 @@ class SDNode {
   /// depth of 2, etc.
   unsigned short NodeDepth;
 
-  /// Operands - The values that are used by this operation.
+  /// OperandList - The values that are used by this operation.
   ///
-  std::vector<SDOperand> Operands;
+  SDOperand *OperandList;
+  
+  /// ValueList - The types of the values this node defines.  SDNode's may
+  /// define multiple values simultaneously.
+  MVT::ValueType *ValueList;
 
-  /// Values - The types of the values this node defines.  SDNode's may define
-  /// multiple values simultaneously.
-  std::vector<MVT::ValueType> Values;
+  /// NumOperands/NumValues - The number of entries in the Operand/Value list.
+  unsigned short NumOperands, NumValues;
+  
+  /// Prev/Next pointers - These pointers form the linked list of of the
+  /// AllNodes list in the current DAG.
+  SDNode *Prev, *Next;
+  friend struct ilist_traits<SDNode>;
 
   /// Uses - These are all of the SDNode's that use a value produced by this
   /// node.
   std::vector<SDNode*> Uses;
 public:
-
+  virtual ~SDNode() {
+    assert(NumOperands == 0 && "Operand list not cleared before deletion");
+  }
+  
   //===--------------------------------------------------------------------===//
   //  Accessors
   //
@@ -523,37 +596,32 @@ public:
 
   /// getNumOperands - Return the number of values used by this operation.
   ///
-  unsigned getNumOperands() const { return Operands.size(); }
-
-  const SDOperand &getOperand(unsigned Num) {
-    assert(Num < Operands.size() && "Invalid child # of SDNode!");
-    return Operands[Num];
-  }
+  unsigned getNumOperands() const { return NumOperands; }
 
   const SDOperand &getOperand(unsigned Num) const {
-    assert(Num < Operands.size() && "Invalid child # of SDNode!");
-    return Operands[Num];
+    assert(Num < NumOperands && "Invalid child # of SDNode!");
+    return OperandList[Num];
   }
-  typedef std::vector<SDOperand>::const_iterator op_iterator;
-  op_iterator op_begin() const { return Operands.begin(); }
-  op_iterator op_end() const { return Operands.end(); }
+  typedef const SDOperand* op_iterator;
+  op_iterator op_begin() const { return OperandList; }
+  op_iterator op_end() const { return OperandList+NumOperands; }
 
 
   /// getNumValues - Return the number of values defined/returned by this
   /// operator.
   ///
-  unsigned getNumValues() const { return Values.size(); }
+  unsigned getNumValues() const { return NumValues; }
 
   /// getValueType - Return the type of a specified result.
   ///
   MVT::ValueType getValueType(unsigned ResNo) const {
-    assert(ResNo < Values.size() && "Illegal result number!");
-    return Values[ResNo];
+    assert(ResNo < NumValues && "Illegal result number!");
+    return ValueList[ResNo];
   }
 
-  typedef std::vector<MVT::ValueType>::const_iterator value_iterator;
-  value_iterator value_begin() const { return Values.begin(); }
-  value_iterator value_end() const { return Values.end(); }
+  typedef const MVT::ValueType* value_iterator;
+  value_iterator value_begin() const { return ValueList; }
+  value_iterator value_end() const { return ValueList+NumValues; }
 
   /// getOperationName - Return the opcode of this operation for printing.
   ///
@@ -569,15 +637,26 @@ public:
 
 protected:
   friend class SelectionDAG;
+  
+  /// getValueTypeList - Return a pointer to the specified value type.
+  ///
+  static MVT::ValueType *getValueTypeList(MVT::ValueType VT);
 
   SDNode(unsigned NT, MVT::ValueType VT) : NodeType(NT), NodeDepth(1) {
-    Values.reserve(1);
-    Values.push_back(VT);
+    OperandList = 0; NumOperands = 0;
+    ValueList = getValueTypeList(VT);
+    NumValues = 1;
+    Prev = 0; Next = 0;
   }
   SDNode(unsigned NT, SDOperand Op)
     : NodeType(NT), NodeDepth(Op.Val->getNodeDepth()+1) {
-    Operands.reserve(1); Operands.push_back(Op);
+    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) {
@@ -585,8 +664,14 @@ protected:
       NodeDepth = N1.Val->getNodeDepth()+1;
     else
       NodeDepth = N2.Val->getNodeDepth()+1;
-    Operands.reserve(2); Operands.push_back(N1); Operands.push_back(N2);
+    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) {
@@ -597,10 +682,17 @@ protected:
       ND = N3.Val->getNodeDepth();
     NodeDepth = ND+1;
 
-    Operands.reserve(3); Operands.push_back(N1); Operands.push_back(N2);
-    Operands.push_back(N3);
+    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;
   }
   SDNode(unsigned NT, SDOperand N1, SDOperand N2, SDOperand N3, SDOperand N4)
     : NodeType(NT) {
@@ -613,94 +705,129 @@ protected:
       ND = N4.Val->getNodeDepth();
     NodeDepth = ND+1;
 
-    Operands.reserve(4); Operands.push_back(N1); Operands.push_back(N2);
-    Operands.push_back(N3); Operands.push_back(N4);
+    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 NT, std::vector<SDOperand> &Nodes) : NodeType(NT) {
-    Operands.swap(Nodes);
+  SDNode(unsigned Opc, const std::vector<SDOperand> &Nodes) : NodeType(Opc) {
+    NumOperands = Nodes.size();
+    OperandList = new SDOperand[NumOperands];
+    
     unsigned ND = 0;
-    for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
-      Operands[i].Val->Uses.push_back(this);
-      if (ND < Operands[i].Val->getNodeDepth())
-        ND = Operands[i].Val->getNodeDepth();
+    for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
+      OperandList[i] = Nodes[i];
+      SDNode *N = OperandList[i].Val;
+      N->Uses.push_back(this);
+      if (ND < N->getNodeDepth()) ND = N->getNodeDepth();
     }
     NodeDepth = ND+1;
+    ValueList = 0;
+    NumValues = 0;
+    Prev = 0; Next = 0;
   }
 
-  virtual ~SDNode() {}
-
   /// 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;
-    Values.clear();
+    ValueList = 0;
+    NumValues = 0;
     
     // Clear the operands list, updating used nodes to remove this from their
     // use list.
-    while (!Operands.empty()) {
-      SDNode *O = Operands.back().Val;
-      Operands.pop_back();
-      O->removeUser(this);
-    }
+    for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
+      I->Val->removeUser(this);
+    delete [] OperandList;
+    OperandList = 0;
+    NumOperands = 0;
   }
   
   void setValueTypes(MVT::ValueType VT) {
-    Values.reserve(1);
-    Values.push_back(VT);
-  }
-  void setValueTypes(MVT::ValueType VT1, MVT::ValueType VT2) {
-    Values.reserve(2);
-    Values.push_back(VT1);
-    Values.push_back(VT2);
+    assert(NumValues == 0 && "Should not have values yet!");
+    ValueList = getValueTypeList(VT);
+    NumValues = 1;
   }
-  /// Note: this method destroys the vector passed in.
-  void setValueTypes(std::vector<MVT::ValueType> &VTs) {
-    std::swap(Values, VTs);
+  void setValueTypes(MVT::ValueType *List, unsigned NumVal) {
+    assert(NumValues == 0 && "Should not have values yet!");
+    ValueList = List;
+    NumValues = NumVal;
   }
   
   void setOperands(SDOperand Op0) {
-    Operands.reserve(1);
-    Operands.push_back(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) {
-    Operands.reserve(2);
-    Operands.push_back(Op0);
-    Operands.push_back(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) {
-    Operands.reserve(3);
-    Operands.push_back(Op0);
-    Operands.push_back(Op1);
-    Operands.push_back(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(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3) {
-    Operands.reserve(4);
-    Operands.push_back(Op0);
-    Operands.push_back(Op1);
-    Operands.push_back(Op2);
-    Operands.push_back(Op3);
+    assert(NumOperands == 0 && "Should not have operands yet!");
+    OperandList = new SDOperand[4];
+    OperandList[0] = Op0;
+    OperandList[1] = Op1;
+    OperandList[2] = Op2;
+    OperandList[3] = Op3;
+    NumOperands = 4;
     Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
     Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
   }
   void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3,
                    SDOperand Op4) {
-    Operands.reserve(5);
-    Operands.push_back(Op0);
-    Operands.push_back(Op1);
-    Operands.push_back(Op2);
-    Operands.push_back(Op3);
-    Operands.push_back(Op4);
+    assert(NumOperands == 0 && "Should not have operands yet!");
+    OperandList = new SDOperand[5];
+    OperandList[0] = Op0;
+    OperandList[1] = Op1;
+    OperandList[2] = Op2;
+    OperandList[3] = Op3;
+    OperandList[4] = Op4;
+    NumOperands = 5;
     Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
     Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
     Op4.Val->Uses.push_back(this);
   }
+  void setOperands(SDOperand Op0, SDOperand Op1, SDOperand Op2, SDOperand Op3,
+                   SDOperand Op4, SDOperand Op5) {
+    assert(NumOperands == 0 && "Should not have operands yet!");
+    OperandList = new SDOperand[6];
+    OperandList[0] = Op0;
+    OperandList[1] = Op1;
+    OperandList[2] = Op2;
+    OperandList[3] = Op3;
+    OperandList[4] = Op4;
+    OperandList[5] = Op5;
+    NumOperands = 6;
+    Op0.Val->Uses.push_back(this); Op1.Val->Uses.push_back(this);
+    Op2.Val->Uses.push_back(this); Op3.Val->Uses.push_back(this);
+    Op4.Val->Uses.push_back(this); Op5.Val->Uses.push_back(this);
+  }
   void addUser(SDNode *User) {
     Uses.push_back(User);
   }
@@ -745,6 +872,34 @@ inline bool SDOperand::hasOneUse() const {
   return Val->hasNUsesOfValue(1, ResNo);
 }
 
+/// 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 {
+public:
+  HandleSDNode(SDOperand X) : SDNode(ISD::HANDLENODE, X) {}
+  ~HandleSDNode() {
+    MorphNodeTo(ISD::HANDLENODE);  // Drops operand uses.
+  }
+  
+  SDOperand getValue() const { return getOperand(0); }
+};
+
+class StringSDNode : public SDNode {
+  std::string Value;
+protected:
+  friend class SelectionDAG;
+  StringSDNode(const std::string &val)
+    : SDNode(ISD::STRING, MVT::Other), Value(val) {
+  }
+public:
+  const std::string &getValue() const { return Value; }
+  static bool classof(const StringSDNode *) { return true; }
+  static bool classof(const SDNode *N) {
+    return N->getOpcode() == ISD::STRING;
+  }
+};  
 
 class ConstantSDNode : public SDNode {
   uint64_t Value;
@@ -801,15 +956,19 @@ public:
 
 class GlobalAddressSDNode : public SDNode {
   GlobalValue *TheGlobal;
+  int offset;
 protected:
   friend class SelectionDAG;
-  GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT)
+  GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT,
+                      int o=0)
     : SDNode(isTarget ? ISD::TargetGlobalAddress : ISD::GlobalAddress, VT) {
     TheGlobal = const_cast<GlobalValue*>(GA);
+    offset = o;
   }
 public:
 
   GlobalValue *getGlobal() const { return TheGlobal; }
+  int getOffset() const { return offset; }
 
   static bool classof(const GlobalAddressSDNode *) { return true; }
   static bool classof(const SDNode *N) {
@@ -909,8 +1068,9 @@ class ExternalSymbolSDNode : public SDNode {
   const char *Symbol;
 protected:
   friend class SelectionDAG;
-  ExternalSymbolSDNode(const char *Sym, MVT::ValueType VT)
-    : SDNode(ISD::ExternalSymbol, VT), Symbol(Sym) {
+  ExternalSymbolSDNode(bool isTarget, const char *Sym, MVT::ValueType VT)
+    : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, VT),
+      Symbol(Sym) {
     }
 public:
 
@@ -918,7 +1078,8 @@ public:
 
   static bool classof(const ExternalSymbolSDNode *) { return true; }
   static bool classof(const SDNode *N) {
-    return N->getOpcode() == ISD::ExternalSymbol;
+    return N->getOpcode() == ISD::ExternalSymbol ||
+           N->getOpcode() == ISD::TargetExternalSymbol;
   }
 };
 
@@ -1009,6 +1170,28 @@ template <> struct GraphTraits<SDNode*> {
   }
 };
 
+template<>
+struct ilist_traits<SDNode> {
+  static SDNode *getPrev(const SDNode *N) { return N->Prev; }
+  static SDNode *getNext(const SDNode *N) { return N->Next; }
+  
+  static void setPrev(SDNode *N, SDNode *Prev) { N->Prev = Prev; }
+  static void setNext(SDNode *N, SDNode *Next) { N->Next = Next; }
+  
+  static SDNode *createSentinel() {
+    return new SDNode(ISD::EntryToken, MVT::Other);
+  }
+  static void destroySentinel(SDNode *N) { delete N; }
+  //static SDNode *createNode(const SDNode &V) { return new SDNode(V); }
+  
+  
+  void addNodeToList(SDNode *NTy) {}
+  void removeNodeFromList(SDNode *NTy) {}
+  void transferNodesFromList(iplist<SDNode, ilist_traits> &L2,
+                             const ilist_iterator<SDNode> &X,
+                             const ilist_iterator<SDNode> &Y) {}
+};
+
 } // end llvm namespace
 
 #endif