[llvm-commits] [llvm] r53728 - in /llvm/trunk: include/llvm/CodeGen/ include/llvm/Support/ lib/CodeGen/SelectionDAG/ lib/Target/ARM/ lib/Target/Alpha/ lib/Target/CellSPU/ lib/Target/IA64/ lib/Target/Mips/ lib/Target/PIC16/ lib/Target/PowerPC/ lib/Target/Sparc/ lib/Target/X86/ test/CodeGen/PowerPC/ utils/TableGen/

Dan Gohman gohman at apple.com
Thu Jul 17 12:10:19 PDT 2008


Author: djg
Date: Thu Jul 17 14:10:17 2008
New Revision: 53728

URL: http://llvm.org/viewvc/llvm-project?rev=53728&view=rev
Log:
Add a new function, ReplaceAllUsesOfValuesWith, which handles bulk
replacement of multiple values. This is slightly more efficient
than doing multiple ReplaceAllUsesOfValueWith calls, and theoretically
could be optimized even further. However, an important property of this
new function is that it handles the case where the source value set and
destination value set overlap. This makes it feasible for isel to use
SelectNodeTo in many very common cases, which is advantageous because
SelectNodeTo avoids a temporary node and it doesn't require CSEMap
updates for users of values that don't change position.

Revamp MorphNodeTo, which is what does all the work of SelectNodeTo, to
handle operand lists more efficiently, and to correctly handle a number
of corner cases to which its new wider use exposes it.

This commit also includes a change to the encoding of post-isel opcodes
in SDNodes; now instead of being sandwiched between the target-independent
pre-isel opcodes and the target-dependent pre-isel opcodes, post-isel
opcodes are now represented as negative values. This makes it possible
to test if an opcode is pre-isel or post-isel without having to know
the size of the current target's post-isel instruction set.

These changes speed up llc overall by 3% and reduce memory usage by 10%
on the InstructionCombining.cpp testcase with -fast and -regalloc=local.

Modified:
    llvm/trunk/include/llvm/CodeGen/DAGISelHeader.h
    llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
    llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
    llvm/trunk/include/llvm/Support/Allocator.h
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Alpha/AlphaISelDAGToDAG.cpp
    llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
    llvm/trunk/lib/Target/IA64/IA64ISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp
    llvm/trunk/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
    llvm/trunk/lib/Target/PowerPC/PPCHazardRecognizers.cpp
    llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
    llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp
    llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
    llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
    llvm/trunk/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll
    llvm/trunk/utils/TableGen/DAGISelEmitter.cpp

Modified: llvm/trunk/include/llvm/CodeGen/DAGISelHeader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DAGISelHeader.h?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/DAGISelHeader.h (original)
+++ llvm/trunk/include/llvm/CodeGen/DAGISelHeader.h Thu Jul 17 14:10:17 2008
@@ -124,6 +124,17 @@
   UpdateQueue(ISQU);
 }
 
+/// ReplaceUses - replace all uses of the old nodes F with the use
+/// of the new nodes T.
+void ReplaceUses(const SDOperand *F, const SDOperand *T,
+                 unsigned Num) DISABLE_INLINE {
+  ISelQueueUpdater ISQU(ISelQueue);
+  CurDAG->ReplaceAllUsesOfValuesWith(F, T, Num, &ISQU);
+  for (unsigned i = 0; i != Num; ++i)
+    setSelected(F[i].Val->getNodeId());
+  UpdateQueue(ISQU);
+}
+
 /// ReplaceUses - replace all uses of the old node F with the use
 /// of the new node T.
 void ReplaceUses(SDNode *F, SDNode *T) DISABLE_INLINE {

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Thu Jul 17 14:10:17 2008
@@ -60,6 +60,10 @@
   /// CSE with existing nodes with a duplicate is requested.
   FoldingSet<SDNode> CSEMap;
 
+  /// Allocator - Pool allocation for misc. objects that are created once per
+  /// SelectionDAG.
+  BumpPtrAllocator Allocator;
+
 public:
   SelectionDAG(TargetLowering &tli, MachineFunction &mf, 
                FunctionLoweringInfo &fli, MachineModuleInfo *mmi,
@@ -457,8 +461,7 @@
   /// SelectNodeTo - These are used for target selectors to *mutate* the
   /// specified node to have the specified return type, Target opcode, and
   /// operands.  Note that target opcodes are stored as
-  /// ISD::BUILTIN_OP_END+TargetOpcode in the node opcode field.  The 0th value
-  /// of the resultant node is returned.
+  /// ~TargetOpcode in the node opcode field.  The resultant node is returned.
   SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT);
   SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT, SDOperand Op1);
   SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT VT,
@@ -481,6 +484,29 @@
   SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs,
                        const SDOperand *Ops, unsigned NumOps);
 
+  /// MorphNodeTo - These *mutate* the specified node to have the specified
+  /// return type, opcode, and operands.
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT, SDOperand Op1);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT,
+                      SDOperand Op1, SDOperand Op2);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT,
+                      SDOperand Op1, SDOperand Op2, SDOperand Op3);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT,
+                      const SDOperand *Ops, unsigned NumOps);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1, MVT VT2);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1,
+                      MVT VT2, const SDOperand *Ops, unsigned NumOps);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1,
+                      MVT VT2, MVT VT3, const SDOperand *Ops, unsigned NumOps);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1,
+                      MVT VT2, SDOperand Op1);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1,
+                      MVT VT2, SDOperand Op1, SDOperand Op2);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, MVT VT1,
+                      MVT VT2, SDOperand Op1, SDOperand Op2, SDOperand Op3);
+  SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs,
+                      const SDOperand *Ops, unsigned NumOps);
 
   /// getTargetNode - These are used for target selectors to create a new node
   /// with specified return type(s), target opcode, and operands.
@@ -565,6 +591,13 @@
   void ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To,
                                  DAGUpdateListener *UpdateListener = 0);
 
+  /// ReplaceAllUsesOfValuesWith - Like ReplaceAllUsesOfValueWith, but
+  /// for multiple values at once. This correctly handles the case where
+  /// there is an overlap between the From values and the To values.
+  void ReplaceAllUsesOfValuesWith(const SDOperand *From, const SDOperand *To,
+                                  unsigned Num,
+                                  DAGUpdateListener *UpdateListener = 0);
+
   /// AssignTopologicalOrder - Assign a unique node id for each node in the DAG
   /// based on their topological order. It returns the maximum id and a vector
   /// of the SDNodes* in assigned order by reference.
@@ -654,7 +687,7 @@
   unsigned getMVTAlignment(MVT MemoryVT) const;
   
   // List of non-single value types.
-  std::list<std::vector<MVT> > VTList;
+  std::vector<SDVTList> VTList;
   
   // Maps to auto-CSE operations.
   std::vector<CondCodeSDNode*> CondCodeNodes;

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAGNodes.h Thu Jul 17 14:10:17 2008
@@ -846,7 +846,8 @@
   inline const SDOperand &getOperand(unsigned i) const;
   inline uint64_t getConstantOperandVal(unsigned i) const;
   inline bool isTargetOpcode() const;
-  inline unsigned getTargetOpcode() const;
+  inline bool isMachineOpcode() const;
+  inline unsigned getMachineOpcode() const;
 
   
   /// reachesChainWithoutSideEffects - Return true if this operand (which must
@@ -1028,7 +1029,7 @@
 private:
   /// NodeType - The operation that this node performs.
   ///
-  unsigned short NodeType;
+  short NodeType;
   
   /// OperandsNeedDelete - This is true if OperandList was new[]'d.  If true,
   /// then they will be delete[]'d when the node is destroyed.
@@ -1072,11 +1073,27 @@
   //===--------------------------------------------------------------------===//
   //  Accessors
   //
-  unsigned getOpcode()  const { return NodeType; }
+
+  /// getOpcode - Return the SelectionDAG opcode value for this node. For
+  /// pre-isel nodes (those for which isMachineOpcode returns false), these
+  /// are the opcode values in the ISD and <target>ISD namespaces. For
+  /// post-isel opcodes, see getMachineOpcode.
+  unsigned getOpcode()  const { return (unsigned short)NodeType; }
+
+  /// isTargetOpcode - Test if this node has a target-specific opcode (in the
+  /// <target>ISD namespace).
   bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; }
-  unsigned getTargetOpcode() const {
-    assert(isTargetOpcode() && "Not a target opcode!");
-    return NodeType - ISD::BUILTIN_OP_END;
+
+  /// isMachineOpcode - Test if this node has a post-isel opcode, directly
+  /// corresponding to a MachineInstr opcode.
+  bool isMachineOpcode() const { return NodeType < 0; }
+
+  /// getMachineOpcode - This may only be called if isMachineOpcode returns
+  /// true. It returns the MachineInstr opcode value that the node's opcode
+  /// corresponds to.
+  unsigned getMachineOpcode() const {
+    assert(isMachineOpcode() && "Not a target opcode!");
+    return ~NodeType;
   }
 
   size_t use_size() const { return std::distance(use_begin(), use_end()); }
@@ -1314,17 +1331,9 @@
   }
 
   /// DropOperands - Release the operands and set this node to have
-  /// zero operands.  This should only be used by HandleSDNode to clear
-  /// its operand list.
+  /// zero operands.
   void DropOperands();
   
-  /// 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,
-                   SmallVectorImpl<SDNode *> &DeadNodes);
-  
   void addUser(unsigned i, SDNode *User) {
     assert(User->OperandList[i].getUser() && "Node without parent");
     addUse(User->OperandList[i]);
@@ -1358,8 +1367,11 @@
 inline bool SDOperand::isTargetOpcode() const {
   return Val->isTargetOpcode();
 }
-inline unsigned SDOperand::getTargetOpcode() const {
-  return Val->getTargetOpcode();
+inline bool SDOperand::isMachineOpcode() const {
+  return Val->isMachineOpcode();
+}
+inline unsigned SDOperand::getMachineOpcode() const {
+  return Val->getMachineOpcode();
 }
 inline bool SDOperand::hasOneUse() const {
   return Val->hasNUsesOfValue(1, ResNo);

Modified: llvm/trunk/include/llvm/Support/Allocator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Allocator.h?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Support/Allocator.h (original)
+++ llvm/trunk/include/llvm/Support/Allocator.h Thu Jul 17 14:10:17 2008
@@ -58,6 +58,11 @@
     return static_cast<T*>(Allocate(sizeof(T),AlignOf<T>::Alignment));
   }
   
+  template <typename T>
+  T *Allocate(size_t Num) { 
+    return static_cast<T*>(Allocate(Num * sizeof(T), AlignOf<T>::Alignment));
+  }
+  
   void Deallocate(void * /*Ptr*/) {}
 
   void PrintStats() const;

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAG.cpp Thu Jul 17 14:10:17 2008
@@ -63,8 +63,8 @@
     return;
 
   unsigned ResNo = Use->getOperand(2).ResNo;
-  if (Def->isTargetOpcode()) {
-    const TargetInstrDesc &II = TII->get(Def->getTargetOpcode());
+  if (Def->isMachineOpcode()) {
+    const TargetInstrDesc &II = TII->get(Def->getMachineOpcode());
     if (ResNo >= II.getNumDefs() &&
         II.ImplicitDefs[ResNo - II.getNumDefs()] == Reg) {
       PhysReg = Reg;
@@ -167,8 +167,8 @@
     SUnit *SU = &SUnits[su];
     SDNode *MainNode = SU->Node;
     
-    if (MainNode->isTargetOpcode()) {
-      unsigned Opc = MainNode->getTargetOpcode();
+    if (MainNode->isMachineOpcode()) {
+      unsigned Opc = MainNode->getMachineOpcode();
       const TargetInstrDesc &TID = TII->get(Opc);
       for (unsigned i = 0; i != TID.getNumOperands(); ++i) {
         if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) {
@@ -186,9 +186,9 @@
     
     for (unsigned n = 0, e = SU->FlaggedNodes.size(); n != e; ++n) {
       SDNode *N = SU->FlaggedNodes[n];
-      if (N->isTargetOpcode() &&
-          TII->get(N->getTargetOpcode()).getImplicitDefs() &&
-          CountResults(N) > TII->get(N->getTargetOpcode()).getNumDefs())
+      if (N->isMachineOpcode() &&
+          TII->get(N->getMachineOpcode()).getImplicitDefs() &&
+          CountResults(N) > TII->get(N->getMachineOpcode()).getNumDefs())
         SU->hasPhysRegDefs = true;
       
       for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
@@ -227,8 +227,8 @@
   }
 
   SU->Latency = 0;
-  if (SU->Node->isTargetOpcode()) {
-    unsigned SchedClass = TII->get(SU->Node->getTargetOpcode()).getSchedClass();
+  if (SU->Node->isMachineOpcode()) {
+    unsigned SchedClass = TII->get(SU->Node->getMachineOpcode()).getSchedClass();
     const InstrStage *S = InstrItins.begin(SchedClass);
     const InstrStage *E = InstrItins.end(SchedClass);
     for (; S != E; ++S)
@@ -236,8 +236,8 @@
   }
   for (unsigned i = 0, e = SU->FlaggedNodes.size(); i != e; ++i) {
     SDNode *FNode = SU->FlaggedNodes[i];
-    if (FNode->isTargetOpcode()) {
-      unsigned SchedClass = TII->get(FNode->getTargetOpcode()).getSchedClass();
+    if (FNode->isMachineOpcode()) {
+      unsigned SchedClass = TII->get(FNode->getMachineOpcode()).getSchedClass();
       const InstrStage *S = InstrItins.begin(SchedClass);
       const InstrStage *E = InstrItins.end(SchedClass);
       for (; S != E; ++S)
@@ -501,7 +501,7 @@
 void ScheduleDAG::CreateVirtualRegisters(SDNode *Node, MachineInstr *MI,
                                  const TargetInstrDesc &II,
                                  DenseMap<SDOperand, unsigned> &VRBaseMap) {
-  assert(Node->getTargetOpcode() != TargetInstrInfo::IMPLICIT_DEF &&
+  assert(Node->getMachineOpcode() != TargetInstrInfo::IMPLICIT_DEF &&
          "IMPLICIT_DEF should have been handled as a special case elsewhere!");
 
   for (unsigned i = 0; i < II.getNumDefs(); ++i) {
@@ -544,8 +544,8 @@
 /// of the specified node.
 unsigned ScheduleDAG::getVR(SDOperand Op,
                             DenseMap<SDOperand, unsigned> &VRBaseMap) {
-  if (Op.isTargetOpcode() &&
-      Op.getTargetOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
+  if (Op.isMachineOpcode() &&
+      Op.getMachineOpcode() == TargetInstrInfo::IMPLICIT_DEF) {
     // Add an IMPLICIT_DEF instruction before every use.
     unsigned VReg = getDstOfOnlyCopyToRegUse(Op.Val, Op.ResNo);
     // IMPLICIT_DEF can produce any type of result so its TargetInstrDesc
@@ -572,7 +572,7 @@
                              unsigned IIOpNum,
                              const TargetInstrDesc *II,
                              DenseMap<SDOperand, unsigned> &VRBaseMap) {
-  if (Op.isTargetOpcode()) {
+  if (Op.isMachineOpcode()) {
     // Note that this case is redundant with the final else block, but we
     // include it because it is the most common and it makes the logic
     // simpler here.
@@ -704,7 +704,7 @@
 void ScheduleDAG::EmitSubregNode(SDNode *Node, 
                            DenseMap<SDOperand, unsigned> &VRBaseMap) {
   unsigned VRBase = 0;
-  unsigned Opc = Node->getTargetOpcode();
+  unsigned Opc = Node->getMachineOpcode();
   
   // If the node is only used by a CopyToReg and the dest reg is a vreg, use
   // the CopyToReg'd destination register instead of creating a new vreg.
@@ -799,8 +799,8 @@
 void ScheduleDAG::EmitNode(SDNode *Node, bool IsClone,
                            DenseMap<SDOperand, unsigned> &VRBaseMap) {
   // If machine instruction
-  if (Node->isTargetOpcode()) {
-    unsigned Opc = Node->getTargetOpcode();
+  if (Node->isMachineOpcode()) {
+    unsigned Opc = Node->getMachineOpcode();
     
     // Handle subreg insert/extract specially
     if (Opc == TargetInstrInfo::EXTRACT_SUBREG || 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGList.cpp Thu Jul 17 14:10:17 2008
@@ -206,7 +206,7 @@
       // If this is a pseudo op, like copyfromreg, look to see if there is a
       // real target node flagged to it.  If so, use the target node.
       for (unsigned i = 0, e = CurSUnit->FlaggedNodes.size(); 
-           FoundNode->getOpcode() < ISD::BUILTIN_OP_END && i != e; ++i)
+           !FoundNode->isMachineOpcode() && i != e; ++i)
         FoundNode = CurSUnit->FlaggedNodes[i];
       
       HazardRecognizer::HazardType HT = HazardRec->getHazardType(FoundNode);

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/ScheduleDAGRRList.cpp Thu Jul 17 14:10:17 2008
@@ -216,7 +216,7 @@
     SUnit *SU = Sequence[i];
     if (!SU || !SU->Node) continue;
     if (SU->isCommutable) {
-      unsigned Opc = SU->Node->getTargetOpcode();
+      unsigned Opc = SU->Node->getMachineOpcode();
       const TargetInstrDesc &TID = TII->get(Opc);
       unsigned NumRes = TID.getNumDefs();
       unsigned NumOps = TID.getNumOperands() - NumRes;
@@ -678,7 +678,7 @@
     assert(N->getNodeId() == -1 && "Node already inserted!");
     N->setNodeId(NewSU->NodeNum);
       
-    const TargetInstrDesc &TID = TII->get(N->getTargetOpcode());
+    const TargetInstrDesc &TID = TII->get(N->getMachineOpcode());
     for (unsigned i = 0; i != TID.getNumOperands(); ++i) {
       if (TID.getOperandConstraint(i, TOI::TIED_TO) != -1) {
         NewSU->isTwoAddress = true;
@@ -872,7 +872,7 @@
 /// FIXME: Move to SelectionDAG?
 static MVT getPhysicalRegisterVT(SDNode *N, unsigned Reg,
                                  const TargetInstrInfo *TII) {
-  const TargetInstrDesc &TID = TII->get(N->getTargetOpcode());
+  const TargetInstrDesc &TID = TII->get(N->getMachineOpcode());
   assert(TID.ImplicitDefs && "Physical reg def must be in implicit def list!");
   unsigned NumRes = TID.getNumDefs();
   for (const unsigned *ImpDef = TID.getImplicitDefs(); *ImpDef; ++ImpDef) {
@@ -913,9 +913,9 @@
 
   for (unsigned i = 0, e = SU->FlaggedNodes.size()+1; i != e; ++i) {
     SDNode *Node = (i == 0) ? SU->Node : SU->FlaggedNodes[i-1];
-    if (!Node || !Node->isTargetOpcode())
+    if (!Node || !Node->isMachineOpcode())
       continue;
-    const TargetInstrDesc &TID = TII->get(Node->getTargetOpcode());
+    const TargetInstrDesc &TID = TII->get(Node->getMachineOpcode());
     if (!TID.ImplicitDefs)
       continue;
     for (const unsigned *Reg = TID.ImplicitDefs; *Reg; ++Reg) {
@@ -1673,7 +1673,7 @@
 bool
 BURegReductionPriorityQueue::canClobber(const SUnit *SU, const SUnit *Op) {
   if (SU->isTwoAddress) {
-    unsigned Opc = SU->Node->getTargetOpcode();
+    unsigned Opc = SU->Node->getMachineOpcode();
     const TargetInstrDesc &TID = TII->get(Opc);
     unsigned NumRes = TID.getNumDefs();
     unsigned NumOps = TID.getNumOperands() - NumRes;
@@ -1709,11 +1709,11 @@
                                   const TargetInstrInfo *TII,
                                   const TargetRegisterInfo *TRI) {
   SDNode *N = SuccSU->Node;
-  unsigned NumDefs = TII->get(N->getTargetOpcode()).getNumDefs();
-  const unsigned *ImpDefs = TII->get(N->getTargetOpcode()).getImplicitDefs();
+  unsigned NumDefs = TII->get(N->getMachineOpcode()).getNumDefs();
+  const unsigned *ImpDefs = TII->get(N->getMachineOpcode()).getImplicitDefs();
   assert(ImpDefs && "Caller should check hasPhysRegDefs");
   const unsigned *SUImpDefs =
-    TII->get(SU->Node->getTargetOpcode()).getImplicitDefs();
+    TII->get(SU->Node->getMachineOpcode()).getImplicitDefs();
   if (!SUImpDefs)
     return false;
   for (unsigned i = NumDefs, e = N->getNumValues(); i != e; ++i) {
@@ -1744,10 +1744,10 @@
       continue;
 
     SDNode *Node = SU->Node;
-    if (!Node || !Node->isTargetOpcode() || SU->FlaggedNodes.size() > 0)
+    if (!Node || !Node->isMachineOpcode() || SU->FlaggedNodes.size() > 0)
       continue;
 
-    unsigned Opc = Node->getTargetOpcode();
+    unsigned Opc = Node->getMachineOpcode();
     const TargetInstrDesc &TID = TII->get(Opc);
     unsigned NumRes = TID.getNumDefs();
     unsigned NumOps = TID.getNumOperands() - NumRes;
@@ -1768,7 +1768,7 @@
           // depth and height.
           if (SuccSU->Height < SU->Height && (SU->Height - SuccSU->Height) > 1)
             continue;
-          if (!SuccSU->Node || !SuccSU->Node->isTargetOpcode())
+          if (!SuccSU->Node || !SuccSU->Node->isMachineOpcode())
             continue;
           // Don't constrain nodes with physical register defs if the
           // predecessor can clobber them.
@@ -1778,7 +1778,7 @@
           }
           // Don't constraint extract_subreg / insert_subreg these may be
           // coalesced away. We don't them close to their uses.
-          unsigned SuccOpc = SuccSU->Node->getTargetOpcode();
+          unsigned SuccOpc = SuccSU->Node->getMachineOpcode();
           if (SuccOpc == TargetInstrInfo::EXTRACT_SUBREG ||
               SuccOpc == TargetInstrInfo::INSERT_SUBREG)
             continue;
@@ -1836,8 +1836,8 @@
 bool td_ls_rr_sort::operator()(const SUnit *left, const SUnit *right) const {
   unsigned LPriority = SPQ->getNodePriority(left);
   unsigned RPriority = SPQ->getNodePriority(right);
-  bool LIsTarget = left->Node && left->Node->isTargetOpcode();
-  bool RIsTarget = right->Node && right->Node->isTargetOpcode();
+  bool LIsTarget = left->Node && left->Node->isMachineOpcode();
+  bool RIsTarget = right->Node && right->Node->isMachineOpcode();
   bool LIsFloater = LIsTarget && left->NumPreds == 0;
   bool RIsFloater = RIsTarget && right->NumPreds == 0;
   unsigned LBonus = (LimitedSumOfUnscheduledPredsOfSuccs(left,1) == 1) ? 2 : 0;

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Thu Jul 17 14:10:17 2008
@@ -197,8 +197,8 @@
   SDOperand Zero;
   if (N->getOpcode() == ISD::DBG_LABEL)
     return true;
-  if (N->isTargetOpcode() &&
-      N->getTargetOpcode() == TargetInstrInfo::DBG_LABEL)
+  if (N->isMachineOpcode() &&
+      N->getMachineOpcode() == TargetInstrInfo::DBG_LABEL)
     return true;
   return false;
 }
@@ -532,8 +532,7 @@
 }
 
 void SelectionDAG::RemoveDeadNode(SDNode *N, DAGUpdateListener *UpdateListener){
-  SmallVector<SDNode*, 16> DeadNodes;
-  DeadNodes.push_back(N);
+  SmallVector<SDNode*, 16> DeadNodes(1, N);
   RemoveDeadNodes(DeadNodes, UpdateListener);
 }
 
@@ -3523,31 +3522,33 @@
 }
 
 SDVTList SelectionDAG::getVTList(MVT VT1, MVT VT2) {
-  for (std::list<std::vector<MVT> >::iterator I = VTList.begin(),
-       E = VTList.end(); I != E; ++I) {
-    if (I->size() == 2 && (*I)[0] == VT1 && (*I)[1] == VT2)
-      return makeVTList(&(*I)[0], 2);
-  }
-  std::vector<MVT> V;
-  V.push_back(VT1);
-  V.push_back(VT2);
-  VTList.push_front(V);
-  return makeVTList(&(*VTList.begin())[0], 2);
-}
-SDVTList SelectionDAG::getVTList(MVT VT1, MVT VT2,
-                                 MVT VT3) {
-  for (std::list<std::vector<MVT> >::iterator I = VTList.begin(),
-       E = VTList.end(); I != E; ++I) {
-    if (I->size() == 3 && (*I)[0] == VT1 && (*I)[1] == VT2 &&
-        (*I)[2] == VT3)
-      return makeVTList(&(*I)[0], 3);
-  }
-  std::vector<MVT> V;
-  V.push_back(VT1);
-  V.push_back(VT2);
-  V.push_back(VT3);
-  VTList.push_front(V);
-  return makeVTList(&(*VTList.begin())[0], 3);
+  for (std::vector<SDVTList>::reverse_iterator I = VTList.rbegin(),
+       E = VTList.rend(); I != E; ++I)
+    if (I->NumVTs == 2 && I->VTs[0] == VT1 && I->VTs[1] == VT2)
+      return *I;
+
+  MVT *Array = Allocator.Allocate<MVT>(2);
+  Array[0] = VT1;
+  Array[1] = VT2;
+  SDVTList Result = makeVTList(Array, 2);
+  VTList.push_back(Result);
+  return Result;
+}
+
+SDVTList SelectionDAG::getVTList(MVT VT1, MVT VT2, MVT VT3) {
+  for (std::vector<SDVTList>::reverse_iterator I = VTList.rbegin(),
+       E = VTList.rend(); I != E; ++I)
+    if (I->NumVTs == 3 && I->VTs[0] == VT1 && I->VTs[1] == VT2 &&
+                          I->VTs[2] == VT3)
+      return *I;
+
+  MVT *Array = Allocator.Allocate<MVT>(3);
+  Array[0] = VT1;
+  Array[1] = VT2;
+  Array[2] = VT3;
+  SDVTList Result = makeVTList(Array, 3);
+  VTList.push_back(Result);
+  return Result;
 }
 
 SDVTList SelectionDAG::getVTList(const MVT *VTs, unsigned NumVTs) {
@@ -3559,22 +3560,26 @@
     default: break;
   }
 
-  for (std::list<std::vector<MVT> >::iterator I = VTList.begin(),
-       E = VTList.end(); I != E; ++I) {
-    if (I->size() != NumVTs || VTs[0] != (*I)[0] || VTs[1] != (*I)[1]) continue;
+  for (std::vector<SDVTList>::reverse_iterator I = VTList.rbegin(),
+       E = VTList.rend(); I != E; ++I) {
+    if (I->NumVTs != NumVTs || VTs[0] != I->VTs[0] || VTs[1] != I->VTs[1])
+      continue;
    
     bool NoMatch = false;
     for (unsigned i = 2; i != NumVTs; ++i)
-      if (VTs[i] != (*I)[i]) {
+      if (VTs[i] != I->VTs[i]) {
         NoMatch = true;
         break;
       }
     if (!NoMatch)
-      return makeVTList(&*I->begin(), NumVTs);
+      return *I;
   }
   
-  VTList.push_front(std::vector<MVT>(VTs, VTs+NumVTs));
-  return makeVTList(&*VTList.begin()->begin(), NumVTs);
+  MVT *Array = Allocator.Allocate<MVT>(NumVTs);
+  std::copy(VTs, VTs+NumVTs, Array);
+  SDVTList Result = makeVTList(Array, NumVTs);
+  VTList.push_back(Result);
+  return Result;
 }
 
 
@@ -3711,61 +3716,9 @@
   return InN;
 }
 
-/// 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 SDNode::MorphNodeTo(unsigned Opc, SDVTList L,
-                         const SDOperand *Ops, unsigned NumOps,
-                         SmallVectorImpl<SDNode *> &DeadNodes) {
-  NodeType = Opc;
-  ValueList = L.VTs;
-  NumValues = L.NumVTs;
-  
-  // Clear the operands list, updating used nodes to remove this from their
-  // use list.  Keep track of any operands that become dead as a result.
-  SmallPtrSet<SDNode*, 16> DeadNodeSet;
-  for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) {
-    SDNode *N = I->getVal();
-    N->removeUser(std::distance(op_begin(), I), this);
-    if (N->use_empty())
-      DeadNodeSet.insert(N);
-  }
-
-  // If NumOps is larger than the # of operands we currently have, reallocate
-  // the operand list.
-  if (NumOps > NumOperands) {
-    if (OperandsNeedDelete) {
-      delete [] OperandList;
-    }
-    OperandList = new SDUse[NumOps];
-    OperandsNeedDelete = true;
-  }
-  
-  // Assign the new operands.
-  NumOperands = NumOps;
-  
-  for (unsigned i = 0, e = NumOps; i != e; ++i) {
-    OperandList[i] = Ops[i];
-    OperandList[i].setUser(this);
-    SDNode *N = OperandList[i].getVal();
-    N->addUser(i, this);
-    DeadNodeSet.erase(N);
-  }
-
-  // Clean up any nodes that are still dead after adding the uses for the
-  // new operands.
-  for (SmallPtrSet<SDNode *, 16>::iterator I = DeadNodeSet.begin(),
-       E = DeadNodeSet.end(); I != E; ++I)
-    DeadNodes.push_back(*I);
-}
-
 /// DropOperands - Release the operands and set this node to have
-/// zero operands.  This should only be used by HandleSDNode to clear
-/// its operand list.
+/// zero operands.
 void SDNode::DropOperands() {
-  assert(NodeType == ISD::HANDLENODE &&
-         "DropOperands is for HANDLENODE only!");
-
   // Unlike the code in MorphNodeTo that does this, we don't need to
   // watch for dead nodes here.
   for (op_iterator I = op_begin(), E = op_end(); I != E; ++I)
@@ -3774,112 +3727,257 @@
   NumOperands = 0;
 }
 
-/// SelectNodeTo - These are used for target selectors to *mutate* the
-/// specified node to have the specified return type, Target opcode, and
-/// operands.  Note that target opcodes are stored as
-/// ISD::BUILTIN_OP_END+TargetOpcode in the node opcode field.
+/// SelectNodeTo - These are wrappers around MorphNodeTo that accept a
+/// machine opcode.
 ///
-/// Note that SelectNodeTo returns the resultant node.  If there is already a
-/// node of the specified opcode and operands, it returns that node instead of
-/// the current one.
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT) {
   SDVTList VTs = getVTList(VT);
-  return SelectNodeTo(N, TargetOpc, VTs, 0, 0);
+  return SelectNodeTo(N, MachineOpc, VTs, 0, 0);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT, SDOperand Op1) {
   SDVTList VTs = getVTList(VT);
   SDOperand Ops[] = { Op1 };
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, 1);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, 1);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT, SDOperand Op1,
                                    SDOperand Op2) {
   SDVTList VTs = getVTList(VT);
   SDOperand Ops[] = { Op1, Op2 };
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, 2);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, 2);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT, SDOperand Op1,
                                    SDOperand Op2, SDOperand Op3) {
   SDVTList VTs = getVTList(VT);
   SDOperand Ops[] = { Op1, Op2, Op3 };
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, 3);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, 3);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT, const SDOperand *Ops,
                                    unsigned NumOps) {
   SDVTList VTs = getVTList(VT);
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, NumOps);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT1, MVT VT2, const SDOperand *Ops,
                                    unsigned NumOps) {
   SDVTList VTs = getVTList(VT1, VT2);
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, NumOps);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT1, MVT VT2) {
   SDVTList VTs = getVTList(VT1, VT2);
-  return SelectNodeTo(N, TargetOpc, VTs, (SDOperand *)0, 0);
+  return SelectNodeTo(N, MachineOpc, VTs, (SDOperand *)0, 0);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT1, MVT VT2, MVT VT3,
                                    const SDOperand *Ops, unsigned NumOps) {
   SDVTList VTs = getVTList(VT1, VT2, VT3);
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, NumOps);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, NumOps);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc, 
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, 
                                    MVT VT1, MVT VT2,
                                    SDOperand Op1) {
   SDVTList VTs = getVTList(VT1, VT2);
   SDOperand Ops[] = { Op1 };
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, 1);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, 1);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc, 
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc, 
                                    MVT VT1, MVT VT2,
                                    SDOperand Op1, SDOperand Op2) {
   SDVTList VTs = getVTList(VT1, VT2);
   SDOperand Ops[] = { Op1, Op2 };
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, 2);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, 2);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    MVT VT1, MVT VT2,
                                    SDOperand Op1, SDOperand Op2, 
                                    SDOperand Op3) {
   SDVTList VTs = getVTList(VT1, VT2);
   SDOperand Ops[] = { Op1, Op2, Op3 };
-  return SelectNodeTo(N, TargetOpc, VTs, Ops, 3);
+  return SelectNodeTo(N, MachineOpc, VTs, Ops, 3);
 }
 
-SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
+SDNode *SelectionDAG::SelectNodeTo(SDNode *N, unsigned MachineOpc,
                                    SDVTList VTs, const SDOperand *Ops,
                                    unsigned NumOps) {
+  return MorphNodeTo(N, ~MachineOpc, VTs, Ops, NumOps);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT) {
+  SDVTList VTs = getVTList(VT);
+  return MorphNodeTo(N, Opc, VTs, 0, 0);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT, SDOperand Op1) {
+  SDVTList VTs = getVTList(VT);
+  SDOperand Ops[] = { Op1 };
+  return MorphNodeTo(N, Opc, VTs, Ops, 1);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT, SDOperand Op1,
+                                  SDOperand Op2) {
+  SDVTList VTs = getVTList(VT);
+  SDOperand Ops[] = { Op1, Op2 };
+  return MorphNodeTo(N, Opc, VTs, Ops, 2);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT, SDOperand Op1,
+                                  SDOperand Op2, SDOperand Op3) {
+  SDVTList VTs = getVTList(VT);
+  SDOperand Ops[] = { Op1, Op2, Op3 };
+  return MorphNodeTo(N, Opc, VTs, Ops, 3);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT, const SDOperand *Ops,
+                                  unsigned NumOps) {
+  SDVTList VTs = getVTList(VT);
+  return MorphNodeTo(N, Opc, VTs, Ops, NumOps);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT1, MVT VT2, const SDOperand *Ops,
+                                  unsigned NumOps) {
+  SDVTList VTs = getVTList(VT1, VT2);
+  return MorphNodeTo(N, Opc, VTs, Ops, NumOps);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT1, MVT VT2) {
+  SDVTList VTs = getVTList(VT1, VT2);
+  return MorphNodeTo(N, Opc, VTs, (SDOperand *)0, 0);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT1, MVT VT2, MVT VT3,
+                                  const SDOperand *Ops, unsigned NumOps) {
+  SDVTList VTs = getVTList(VT1, VT2, VT3);
+  return MorphNodeTo(N, Opc, VTs, Ops, NumOps);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, 
+                                  MVT VT1, MVT VT2,
+                                  SDOperand Op1) {
+  SDVTList VTs = getVTList(VT1, VT2);
+  SDOperand Ops[] = { Op1 };
+  return MorphNodeTo(N, Opc, VTs, Ops, 1);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc, 
+                                  MVT VT1, MVT VT2,
+                                  SDOperand Op1, SDOperand Op2) {
+  SDVTList VTs = getVTList(VT1, VT2);
+  SDOperand Ops[] = { Op1, Op2 };
+  return MorphNodeTo(N, Opc, VTs, Ops, 2);
+}
+
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  MVT VT1, MVT VT2,
+                                  SDOperand Op1, SDOperand Op2, 
+                                  SDOperand Op3) {
+  SDVTList VTs = getVTList(VT1, VT2);
+  SDOperand Ops[] = { Op1, Op2, Op3 };
+  return MorphNodeTo(N, Opc, VTs, Ops, 3);
+}
+
+/// MorphNodeTo - These *mutate* the specified node to have the specified
+/// return type, opcode, and operands.
+///
+/// Note that MorphNodeTo returns the resultant node.  If there is already a
+/// node of the specified opcode and operands, it returns that node instead of
+/// the current one.
+///
+/// Using MorphNodeTo is faster than creating a new node and swapping it in
+/// with ReplaceAllUsesWith both because it often avoids allocating a new
+/// node, and because it doesn't require CSE recalulation for any of
+/// the node's users.
+///
+SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
+                                  SDVTList VTs, const SDOperand *Ops,
+                                  unsigned NumOps) {
   // If an identical node already exists, use it.
-  FoldingSetNodeID ID;
-  AddNodeIDNode(ID, ISD::BUILTIN_OP_END+TargetOpc, VTs, Ops, NumOps);
   void *IP = 0;
-  if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP))
-    return ON;
+  if (VTs.VTs[VTs.NumVTs-1] != MVT::Flag) {
+    FoldingSetNodeID ID;
+    AddNodeIDNode(ID, Opc, VTs, Ops, NumOps);
+    if (SDNode *ON = CSEMap.FindNodeOrInsertPos(ID, IP))
+      return ON;
+  }
 
   RemoveNodeFromCSEMaps(N);
 
+  // Start the morphing.
+  N->NodeType = Opc;
+  N->ValueList = VTs.VTs;
+  N->NumValues = VTs.NumVTs;
+  
+  // Clear the operands list, updating used nodes to remove this from their
+  // use list.  Keep track of any operands that become dead as a result.
+  SmallPtrSet<SDNode*, 16> DeadNodeSet;
+  for (SDNode::op_iterator B = N->op_begin(), I = B, E = N->op_end();
+       I != E; ++I) {
+    SDNode *Used = I->getVal();
+    Used->removeUser(std::distance(B, I), N);
+    if (Used->use_empty())
+      DeadNodeSet.insert(Used);
+  }
+
+  // If NumOps is larger than the # of operands we currently have, reallocate
+  // the operand list.
+  if (NumOps > N->NumOperands) {
+    if (N->OperandsNeedDelete)
+      delete[] N->OperandList;
+    if (N->isMachineOpcode()) {
+      // We're creating a final node that will live unmorphed for the
+      // remainder of this SelectionDAG's duration, so we can allocate the
+      // operands directly out of the pool with no recycling metadata.
+      N->OperandList = Allocator.Allocate<SDUse>(NumOps);
+      N->OperandsNeedDelete = false;
+    } else {
+      N->OperandList = new SDUse[NumOps];
+      N->OperandsNeedDelete = true;
+    }
+  }
+  
+  // Assign the new operands.
+  N->NumOperands = NumOps;
+  for (unsigned i = 0, e = NumOps; i != e; ++i) {
+    N->OperandList[i] = Ops[i];
+    N->OperandList[i].setUser(N);
+    SDNode *ToUse = N->OperandList[i].getVal();
+    ToUse->addUser(i, N);
+    DeadNodeSet.erase(ToUse);
+  }
+
+  // Delete any nodes that are still dead after adding the uses for the
+  // new operands.
   SmallVector<SDNode *, 16> DeadNodes;
-  N->MorphNodeTo(ISD::BUILTIN_OP_END+TargetOpc, VTs, Ops, NumOps, DeadNodes);
+  for (SmallPtrSet<SDNode *, 16>::iterator I = DeadNodeSet.begin(),
+       E = DeadNodeSet.end(); I != E; ++I)
+    if ((*I)->use_empty())
+      DeadNodes.push_back(*I);
   RemoveDeadNodes(DeadNodes);
 
-  CSEMap.InsertNode(N, IP);   // Memoize the new node.
+  if (IP)
+    CSEMap.InsertNode(N, IP);   // Memoize the new node.
   return N;
 }
 
@@ -3891,70 +3989,70 @@
 /// node of the specified opcode and operands, it returns that node instead of
 /// the current one.
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT) {
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VT).Val;
+  return getNode(~Opcode, VT).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT, SDOperand Op1) {
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Op1).Val;
+  return getNode(~Opcode, VT, Op1).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT,
                                     SDOperand Op1, SDOperand Op2) {
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Op1, Op2).Val;
+  return getNode(~Opcode, VT, Op1, Op2).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT,
                                     SDOperand Op1, SDOperand Op2,
                                     SDOperand Op3) {
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Op1, Op2, Op3).Val;
+  return getNode(~Opcode, VT, Op1, Op2, Op3).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT,
                                     const SDOperand *Ops, unsigned NumOps) {
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VT, Ops, NumOps).Val;
+  return getNode(~Opcode, VT, Ops, NumOps).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2);
   SDOperand Op;
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 2, &Op, 0).Val;
+  return getNode(~Opcode, VTs, 2, &Op, 0).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1,
                                     MVT VT2, SDOperand Op1) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2);
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 2, &Op1, 1).Val;
+  return getNode(~Opcode, VTs, 2, &Op1, 1).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1,
                                     MVT VT2, SDOperand Op1,
                                     SDOperand Op2) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2);
   SDOperand Ops[] = { Op1, Op2 };
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 2, Ops, 2).Val;
+  return getNode(~Opcode, VTs, 2, Ops, 2).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1,
                                     MVT VT2, SDOperand Op1,
                                     SDOperand Op2, SDOperand Op3) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2);
   SDOperand Ops[] = { Op1, Op2, Op3 };
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 2, Ops, 3).Val;
+  return getNode(~Opcode, VTs, 2, Ops, 3).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2,
                                     const SDOperand *Ops, unsigned NumOps) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2);
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 2, Ops, NumOps).Val;
+  return getNode(~Opcode, VTs, 2, Ops, NumOps).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3,
                                     SDOperand Op1, SDOperand Op2) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3);
   SDOperand Ops[] = { Op1, Op2 };
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, 2).Val;
+  return getNode(~Opcode, VTs, 3, Ops, 2).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3,
                                     SDOperand Op1, SDOperand Op2,
                                     SDOperand Op3) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3);
   SDOperand Ops[] = { Op1, Op2, Op3 };
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, 3).Val;
+  return getNode(~Opcode, VTs, 3, Ops, 3).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1, MVT VT2, MVT VT3,
                                     const SDOperand *Ops, unsigned NumOps) {
   const MVT *VTs = getNodeValueTypes(VT1, VT2, VT3);
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, NumOps).Val;
+  return getNode(~Opcode, VTs, 3, Ops, NumOps).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT VT1,
                                     MVT VT2, MVT VT3, MVT VT4,
@@ -3965,13 +4063,13 @@
   VTList.push_back(VT3);
   VTList.push_back(VT4);
   const MVT *VTs = getNodeValueTypes(VTList);
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 4, Ops, NumOps).Val;
+  return getNode(~Opcode, VTs, 4, Ops, NumOps).Val;
 }
 SDNode *SelectionDAG::getTargetNode(unsigned Opcode,
                                     const std::vector<MVT> &ResultTys,
                                     const SDOperand *Ops, unsigned NumOps) {
   const MVT *VTs = getNodeValueTypes(ResultTys);
-  return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, ResultTys.size(),
+  return getNode(~Opcode, VTs, ResultTys.size(),
                  Ops, NumOps).Val;
 }
 
@@ -4043,13 +4141,14 @@
 ///
 void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To,
                                       DAGUpdateListener *UpdateListener) {
-  assert(From != To && "Cannot replace uses of with self");
-  assert(From->getNumValues() == To->getNumValues() &&
+  assert(From->getVTList().VTs == To->getVTList().VTs &&
+         From->getNumValues() == To->getNumValues() &&
          "Cannot use this version of ReplaceAllUsesWith!");
-  if (From->getNumValues() == 1)   // If possible, use the faster version.
-    return ReplaceAllUsesWith(SDOperand(From, 0), SDOperand(To, 0),
-                              UpdateListener);
-  
+
+  // Handle the trivial case.
+  if (From == To)
+    return;
+
   while (!From->use_empty()) {
     SDNode::use_iterator UI = From->use_begin();
     SDNode *U = UI->getUser();
@@ -4127,36 +4226,14 @@
   }
 }
 
-namespace {
-  /// ChainedSetUpdaterListener - This class is a DAGUpdateListener that removes
-  /// any deleted nodes from the set passed into its constructor and recursively
-  /// notifies another update listener if specified.
-  class ChainedSetUpdaterListener : 
-  public SelectionDAG::DAGUpdateListener {
-    SmallSetVector<SDNode*, 16> &Set;
-    SelectionDAG::DAGUpdateListener *Chain;
-  public:
-    ChainedSetUpdaterListener(SmallSetVector<SDNode*, 16> &set,
-                              SelectionDAG::DAGUpdateListener *chain)
-      : Set(set), Chain(chain) {}
- 
-    virtual void NodeDeleted(SDNode *N, SDNode *E) {
-      Set.remove(N);
-      if (Chain) Chain->NodeDeleted(N, E);
-    }
-    virtual void NodeUpdated(SDNode *N) {
-      if (Chain) Chain->NodeUpdated(N);
-    }
-  };
-}
-
 /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving
 /// uses of other values produced by From.Val alone.  The Deleted vector is
 /// handled the same way as for ReplaceAllUsesWith.
 void SelectionDAG::ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To,
                                              DAGUpdateListener *UpdateListener){
-  assert(From != To && "Cannot replace a value with itself");
-  
+  // Handle the really simple, really trivial case efficiently.
+  if (From == To) return;
+
   // Handle the simple, trivial, case efficiently.
   if (From.Val->getNumValues() == 1) {
     ReplaceAllUsesWith(From, To, UpdateListener);
@@ -4174,11 +4251,6 @@
     Users.insert(User);
   }
 
-  // When one of the recursive merges deletes nodes from the graph, we need to
-  // make sure that UpdateListener is notified *and* that the node is removed
-  // from Users if present.  CSUL does this.
-  ChainedSetUpdaterListener CSUL(Users, UpdateListener);
-  
   while (!Users.empty()) {
     // We know that this user uses some value of From.  If it is the right
     // value, update it.
@@ -4217,10 +4289,74 @@
     
     // If there was already an existing matching node, use ReplaceAllUsesWith
     // to replace the dead one with the existing one.  This can cause
-    // recursive merging of other unrelated nodes down the line.  The merging
-    // can cause deletion of nodes that used the old value.  To handle this, we
-    // use CSUL to remove them from the Users set.
-    ReplaceAllUsesWith(User, Existing, &CSUL);
+    // recursive merging of other unrelated nodes down the line.
+    ReplaceAllUsesWith(User, Existing, UpdateListener);
+    
+    // User is now dead.  Notify a listener if present.
+    if (UpdateListener) UpdateListener->NodeDeleted(User, Existing);
+    DeleteNodeNotInCSEMaps(User);
+  }
+}
+
+/// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving
+/// uses of other values produced by From.Val alone.  The same value may
+/// appear in both the From and To list.  The Deleted vector is
+/// handled the same way as for ReplaceAllUsesWith.
+void SelectionDAG::ReplaceAllUsesOfValuesWith(const SDOperand *From,
+                                              const SDOperand *To,
+                                              unsigned Num,
+                                              DAGUpdateListener *UpdateListener){
+  // Handle the simple, trivial case efficiently.
+  if (Num == 1)
+    return ReplaceAllUsesOfValueWith(*From, *To, UpdateListener);
+
+  SmallVector<std::pair<SDNode *, unsigned>, 16> Users;
+  for (unsigned i = 0; i != Num; ++i)
+    for (SDNode::use_iterator UI = From[i].Val->use_begin(), 
+         E = From[i].Val->use_end(); UI != E; ++UI)
+      Users.push_back(std::make_pair(UI->getUser(), i));
+
+  while (!Users.empty()) {
+    // We know that this user uses some value of From.  If it is the right
+    // value, update it.
+    SDNode *User = Users.back().first;
+    unsigned i = Users.back().second;
+    Users.pop_back();
+    
+    // Scan for an operand that matches From.
+    SDNode::op_iterator Op = User->op_begin(), E = User->op_end();
+    for (; Op != E; ++Op)
+      if (*Op == From[i]) break;
+    
+    // If there are no matches, the user must use some other result of From.
+    if (Op == E) continue;
+      
+    // Okay, we know this user needs to be updated.  Remove its old self
+    // from the CSE maps.
+    RemoveNodeFromCSEMaps(User);
+    
+    // Update all operands that match "From" in case there are multiple uses.
+    for (; Op != E; ++Op) {
+      if (*Op == From[i]) {
+        From[i].Val->removeUser(Op-User->op_begin(), User);
+        *Op = To[i];
+        Op->setUser(User);
+        To[i].Val->addUser(Op-User->op_begin(), User);
+      }
+    }
+               
+    // Now that we have modified User, add it back to the CSE maps.  If it
+    // already exists there, recursively merge the results together.
+    SDNode *Existing = AddNonLeafNodeToCSEMaps(User);
+    if (!Existing) {
+      if (UpdateListener) UpdateListener->NodeUpdated(User);
+      continue;  // Continue on to next user.
+    }
+    
+    // If there was already an existing matching node, use ReplaceAllUsesWith
+    // to replace the dead one with the existing one.  This can cause
+    // recursive merging of other unrelated nodes down the line.
+    ReplaceAllUsesWith(User, Existing, UpdateListener);
     
     // User is now dead.  Notify a listener if present.
     if (UpdateListener) UpdateListener->NodeDeleted(User, Existing);
@@ -4507,21 +4643,25 @@
   default:
     if (getOpcode() < ISD::BUILTIN_OP_END)
       return "<<Unknown DAG Node>>";
-    else {
-      if (G) {
+    if (isMachineOpcode()) {
+      if (G)
         if (const TargetInstrInfo *TII = G->getTarget().getInstrInfo())
-          if (getOpcode()-ISD::BUILTIN_OP_END < TII->getNumOpcodes())
-            return TII->get(getOpcode()-ISD::BUILTIN_OP_END).getName();
-
-        TargetLowering &TLI = G->getTargetLoweringInfo();
-        const char *Name =
-          TLI.getTargetNodeName(getOpcode());
-        if (Name) return Name;
-      }
-
+          if (getMachineOpcode() < TII->getNumOpcodes())
+            return TII->get(getMachineOpcode()).getName();
+      return "<<Unknown Machine Node>>";
+    }
+    if (G) {
+      TargetLowering &TLI = G->getTargetLoweringInfo();
+      const char *Name = TLI.getTargetNodeName(getOpcode());
+      if (Name) return Name;
       return "<<Unknown Target Node>>";
     }
+    return "<<Unknown Node>>";
    
+#ifndef NDEBUG
+  case ISD::DELETED_NODE:
+    return "<<Deleted Node!>>";
+#endif
   case ISD::PREFETCH:      return "Prefetch";
   case ISD::MEMBARRIER:    return "MemBarrier";
   case ISD::ATOMIC_CMP_SWAP:  return "AtomicCmpSwap";

Modified: llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -530,9 +530,8 @@
 
 SDNode *ARMDAGToDAGISel::Select(SDOperand Op) {
   SDNode *N = Op.Val;
-  unsigned Opcode = N->getOpcode();
 
-  if (Opcode >= ISD::BUILTIN_OP_END && Opcode < ARMISD::FIRST_NUMBER)
+  if (N->isMachineOpcode())
     return NULL;   // Already selected.
 
   switch (N->getOpcode()) {

Modified: llvm/trunk/lib/Target/Alpha/AlphaISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Alpha/AlphaISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Alpha/AlphaISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Alpha/AlphaISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -244,8 +244,7 @@
 // target-specific node if it hasn't already been changed.
 SDNode *AlphaDAGToDAGISel::Select(SDOperand Op) {
   SDNode *N = Op.Val;
-  if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
-      N->getOpcode() < AlphaISD::FIRST_NUMBER) {
+  if (N->isMachineOpcode()) {
     return NULL;   // Already selected.
   }
 

Modified: llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/CellSPU/SPUISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -587,7 +587,7 @@
   MVT OpVT = Op.getValueType();
   SDOperand Ops[8];
 
-  if (Opc >= ISD::BUILTIN_OP_END && Opc < SPUISD::FIRST_NUMBER) {
+  if (N->isMachineOpcode()) {
     return NULL;   // Already selected.
   } else if (Opc == ISD::FrameIndex) {
     // Selects to (add $sp, FI * stackSlotSize)

Modified: llvm/trunk/lib/Target/IA64/IA64ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/IA64/IA64ISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/IA64/IA64ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/IA64/IA64ISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -305,8 +305,7 @@
 // target-specific node if it hasn't already been changed.
 SDNode *IA64DAGToDAGISel::Select(SDOperand Op) {
   SDNode *N = Op.Val;
-  if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
-      N->getOpcode() < IA64ISD::FIRST_NUMBER)
+  if (N->isMachineOpcode())
     return NULL;   // Already selected.
 
   switch (N->getOpcode()) {

Modified: llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -205,7 +205,7 @@
   #endif
 
   // If we have a custom node, we already have selected!
-  if (Opcode >= ISD::BUILTIN_OP_END && Opcode < MipsISD::FIRST_NUMBER) {
+  if (Node->isMachineOpcode()) {
     #ifndef NDEBUG
     DOUT << std::string(Indent-2, ' ') << "== ";
     DEBUG(Node->dump(CurDAG));

Modified: llvm/trunk/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -239,7 +239,7 @@
 #endif
 
   // If we have a custom node, we already have selected!
-  if (Opcode >= ISD::BUILTIN_OP_END && Opcode < PIC16ISD::FIRST_NUMBER) {
+  if (Node->isMachineOpcode()) {
 #ifndef NDEBUG
     DOUT << std::string(Indent-2, ' ') << "== ";
     DEBUG(Node->dump(CurDAG));

Modified: llvm/trunk/lib/Target/PowerPC/PPCHazardRecognizers.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCHazardRecognizers.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCHazardRecognizers.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCHazardRecognizers.cpp Thu Jul 17 14:10:17 2008
@@ -64,11 +64,11 @@
                                      bool &isFirst, bool &isSingle,
                                      bool &isCracked,
                                      bool &isLoad, bool &isStore) {
-  if (Opcode < ISD::BUILTIN_OP_END) {
+  if ((int)Opcode >= 0) {
     isFirst = isSingle = isCracked = isLoad = isStore = false;
     return PPCII::PPC970_Pseudo;
   }
-  Opcode -= ISD::BUILTIN_OP_END;
+  Opcode = ~Opcode;
   
   const TargetInstrDesc &TID = TII.get(Opcode);
   
@@ -125,7 +125,7 @@
     GetInstrType(Node->getOpcode(), isFirst, isSingle, isCracked,
                  isLoad, isStore);
   if (InstrType == PPCII::PPC970_Pseudo) return NoHazard;  
-  unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
+  unsigned Opcode = Node->getMachineOpcode();
 
   // We can only issue a PPC970_First/PPC970_Single instruction (such as
   // crand/mtspr/etc) if this is the first cycle of the dispatch group.
@@ -223,7 +223,7 @@
     GetInstrType(Node->getOpcode(), isFirst, isSingle, isCracked,
                  isLoad, isStore);
   if (InstrType == PPCII::PPC970_Pseudo) return;  
-  unsigned Opcode = Node->getOpcode()-ISD::BUILTIN_OP_END;
+  unsigned Opcode = Node->getMachineOpcode();
 
   // Update structural hazard information.
   if (Opcode == PPC::MTCTR) HasCTRSet = true;

Modified: llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -775,8 +775,7 @@
 // target-specific node if it hasn't already been changed.
 SDNode *PPCDAGToDAGISel::Select(SDOperand Op) {
   SDNode *N = Op.Val;
-  if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
-      N->getOpcode() < PPCISD::FIRST_NUMBER)
+  if (N->isMachineOpcode())
     return NULL;   // Already selected.
 
   switch (N->getOpcode()) {
@@ -962,7 +961,8 @@
       AddToISelQueue(Offset);
       SDOperand Ops[] = { Offset, Base, Chain };
       // FIXME: PPC64
-      return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32,
+      return CurDAG->getTargetNode(Opcode, LD->getValueType(0),
+                                   PPCLowering.getPointerTy(),
                                    MVT::Other, Ops, 3);
     } else {
       assert(0 && "R+R preindex loads not supported yet!");

Modified: llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Sparc/SparcISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -137,8 +137,7 @@
 
 SDNode *SparcDAGToDAGISel::Select(SDOperand Op) {
   SDNode *N = Op.Val;
-  if (N->getOpcode() >= ISD::BUILTIN_OP_END &&
-      N->getOpcode() < SPISD::FIRST_NUMBER)
+  if (N->isMachineOpcode())
     return NULL;   // Already selected.
 
   switch (N->getOpcode()) {

Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Thu Jul 17 14:10:17 2008
@@ -1159,7 +1159,7 @@
   Indent += 2;
 #endif
 
-  if (Opcode >= ISD::BUILTIN_OP_END && Opcode < X86ISD::FIRST_NUMBER) {
+  if (Node->isMachineOpcode()) {
 #ifndef NDEBUG
     DOUT << std::string(Indent-2, ' ') << "== ";
     DEBUG(Node->dump(CurDAG));

Modified: llvm/trunk/lib/Target/X86/X86InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86InstrInfo.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86InstrInfo.cpp Thu Jul 17 14:10:17 2008
@@ -2239,11 +2239,11 @@
 bool
 X86InstrInfo::unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
                                      SmallVectorImpl<SDNode*> &NewNodes) const {
-  if (!N->isTargetOpcode())
+  if (!N->isMachineOpcode())
     return false;
 
   DenseMap<unsigned*, std::pair<unsigned,unsigned> >::iterator I =
-    MemOp2RegOpTable.find((unsigned*)N->getTargetOpcode());
+    MemOp2RegOpTable.find((unsigned*)N->getMachineOpcode());
   if (I == MemOp2RegOpTable.end())
     return false;
   unsigned Opc = I->second.first;

Modified: llvm/trunk/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll (original)
+++ llvm/trunk/test/CodeGen/PowerPC/LargeAbsoluteAddr.ll Thu Jul 17 14:10:17 2008
@@ -1,7 +1,7 @@
 ; RUN: llvm-as < %s | llc -march=ppc32 -mtriple=powerpc-apple-darwin | \
-; RUN:   grep {stw r2, 32751}
+; RUN:   grep {stw r3, 32751}
 ; RUN: llvm-as < %s | llc -march=ppc64 -mtriple=powerpc-apple-darwin | \
-; RUN:   grep {stw r2, 32751}
+; RUN:   grep {stw r3, 32751}
 ; RUN: llvm-as < %s | llc -march=ppc64 -mtriple=powerpc-apple-darwin | \
 ; RUN:   grep {std r2, 9024}
 

Modified: llvm/trunk/utils/TableGen/DAGISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DAGISelEmitter.cpp?rev=53728&r1=53727&r2=53728&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/DAGISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/DAGISelEmitter.cpp Thu Jul 17 14:10:17 2008
@@ -1157,7 +1157,8 @@
       if (!isRoot)
         Code += "), 0";
 
-      bool NeedReplace = false;
+      std::vector<std::string> ReplaceFroms;
+      std::vector<std::string> ReplaceTos;
       if (!isRoot) {
         NodeOps.push_back("Tmp" + utostr(ResNo));
       } else {
@@ -1176,33 +1177,35 @@
 
       if (FoldedChains.size() > 0) {
         std::string Code;
-        for (unsigned j = 0, e = FoldedChains.size(); j < e; j++)
-          After.push_back("ReplaceUses(SDOperand(" +
-                          FoldedChains[j].first + ".Val, " + 
-                          utostr(FoldedChains[j].second) +
-                          "), SDOperand(ResNode, " +
-                          utostr(NumResults+NumDstRegs) + "));");
-        NeedReplace = true;
+        for (unsigned j = 0, e = FoldedChains.size(); j < e; j++) {
+          ReplaceFroms.push_back("SDOperand(" +
+                                 FoldedChains[j].first + ".Val, " +
+                                 utostr(FoldedChains[j].second) +
+                                 ")");
+          ReplaceTos.push_back("SDOperand(ResNode, " +
+                               utostr(NumResults+NumDstRegs) + ")");
+        }
       }
 
       if (NodeHasOutFlag) {
         if (FoldedFlag.first != "") {
-          After.push_back("ReplaceUses(SDOperand(" + FoldedFlag.first +
-                          ".Val, " +
-                          utostr(FoldedFlag.second) + "), InFlag);");
+          ReplaceFroms.push_back("SDOperand(" + FoldedFlag.first + ".Val, " +
+                                 utostr(FoldedFlag.second) + ")");
+          ReplaceTos.push_back("InFlag");
         } else {
           assert(NodeHasProperty(Pattern, SDNPOutFlag, CGP));
-          After.push_back("ReplaceUses(SDOperand(N.Val, " +
-                          utostr(NumPatResults + (unsigned)InputHasChain)
-                          +"), InFlag);");
+          ReplaceFroms.push_back("SDOperand(N.Val, " +
+                                 utostr(NumPatResults + (unsigned)InputHasChain)
+                                 + ")");
+          ReplaceTos.push_back("InFlag");
         }
-        NeedReplace = true;
       }
 
-      if (NeedReplace && InputHasChain) {
-        After.push_back("ReplaceUses(SDOperand(N.Val, " + 
-                        utostr(NumPatResults) + "), SDOperand(" + ChainName
-                        + ".Val, " + ChainName + ".ResNo" + "));");
+      if (!ReplaceFroms.empty() && InputHasChain) {
+        ReplaceFroms.push_back("SDOperand(N.Val, " +
+                               utostr(NumPatResults) + ")");
+        ReplaceTos.push_back("SDOperand(" + ChainName + ".Val, " +
+                             ChainName + ".ResNo" + ")");
         ChainAssignmentNeeded |= NodeHasChain;
       }
 
@@ -1211,13 +1214,15 @@
         ;
       } else if (InputHasChain && !NodeHasChain) {
         // One of the inner node produces a chain.
-        if (NodeHasOutFlag)
-          After.push_back("ReplaceUses(SDOperand(N.Val, " +
-                          utostr(NumPatResults+1) +
-                          "), SDOperand(ResNode, N.ResNo-1));");
-        After.push_back("ReplaceUses(SDOperand(N.Val, " +
-                        utostr(NumPatResults) + "), " + ChainName + ");");
-        NeedReplace = true;
+        if (NodeHasOutFlag) {
+          ReplaceFroms.push_back("SDOperand(N.Val, " +
+                                 utostr(NumPatResults+1) +
+                                 ")");
+          ReplaceTos.push_back("SDOperand(ResNode, N.ResNo-1)");
+        }
+        ReplaceFroms.push_back("SDOperand(N.Val, " +
+                               utostr(NumPatResults) + ")");
+        ReplaceTos.push_back(ChainName);
       }
       }
 
@@ -1234,21 +1239,31 @@
         After.push_front(ChainAssign);
       }
 
-      // Use getTargetNode or SelectNodeTo? The safe choice is getTargetNode,
-      // but SelectNodeTo can be faster.
-      //
-      // SelectNodeTo is not safe in a non-root context, or if there is any
-      // replacement of results needed.
+      if (ReplaceFroms.size() == 1) {
+        After.push_back("ReplaceUses(" + ReplaceFroms[0] + ", " +
+                        ReplaceTos[0] + ");");
+      } else if (!ReplaceFroms.empty()) {
+        After.push_back("const SDOperand Froms[] = {");
+        for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
+          After.push_back("  " + ReplaceFroms[i] + (i + 1 != e ? "," : ""));
+        After.push_back("};");
+        After.push_back("const SDOperand Tos[] = {");
+        for (unsigned i = 0, e = ReplaceFroms.size(); i != e; ++i)
+          After.push_back("  " + ReplaceTos[i] + (i + 1 != e ? "," : ""));
+        After.push_back("};");
+        After.push_back("ReplaceUses(Froms, Tos, " +
+                        itostr(ReplaceFroms.size()) + ");");
+      }
+
+      // We prefer to use SelectNodeTo since it avoids allocation when
+      // possible and it avoids CSE map recalculation for the node's
+      // users, however it's tricky to use in a non-root context.
       //
-      // SelectNodeTo is not profitable if it would require a dynamically
-      // allocated operand list in a situation where getTargetNode would be
-      // able to reuse a co-allocated operand list (as in a unary, binary or
-      // ternary SDNode, for example).
+      // We also don't use if the pattern replacement is being used to
+      // jettison a chain result, since morphing the node in place
+      // would leave users of the chain dangling.
       //
-      if (!isRoot || NeedReplace ||
-          (!IsVariadic && AllOps.size() < 4 &&
-           Pattern->getNumChildren() + InputHasChain + NodeHasInFlag <
-             AllOps.size())) {
+      if (!isRoot || (InputHasChain && !NodeHasChain)) {
         Code = "CurDAG->getTargetNode(" + Code;
       } else {
         Code = "CurDAG->SelectNodeTo(N.Val, " + Code;
@@ -1952,9 +1967,7 @@
 
   OS << "// The main instruction selector code.\n"
      << "SDNode *SelectCode(SDOperand N) {\n"
-     << "  if (N.getOpcode() >= ISD::BUILTIN_OP_END &&\n"
-     << "      N.getOpcode() < (ISD::BUILTIN_OP_END+" << InstNS
-     << "INSTRUCTION_LIST_END)) {\n"
+     << "  if (N.isMachineOpcode()) {\n"
      << "    return NULL;   // Already selected.\n"
      << "  }\n\n"
      << "  MVT::SimpleValueType NVT = N.Val->getValueType(0).getSimpleVT();\n"





More information about the llvm-commits mailing list