[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Jim Laskey jlaskey at apple.com
Wed Oct 4 09:53:42 PDT 2006



Changes in directory llvm/lib/CodeGen/SelectionDAG:

DAGCombiner.cpp updated: 1.205 -> 1.206
---
Log message:

More extensive alias analysis.

---
Diffs of the changes:  (+206 -204)

 DAGCombiner.cpp |  410 ++++++++++++++++++++++++++++----------------------------
 1 files changed, 206 insertions(+), 204 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.205 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.206
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.205	Tue Oct  3 19:52:21 2006
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp	Wed Oct  4 11:53:27 2006
@@ -50,7 +50,7 @@
 static cl::opt<bool>
   CombinerAA("combiner-alias-analysis", cl::Hidden,
              cl::desc("Turn on alias analysis turning testing"));
- 
+             
 class VISIBILITY_HIDDEN DAGCombiner {
     SelectionDAG &DAG;
     TargetLowering &TLI;
@@ -66,7 +66,7 @@
     void AddUsersToWorkList(SDNode *N) {
       for (SDNode::use_iterator UI = N->use_begin(), UE = N->use_end();
            UI != UE; ++UI)
-        WorkList.push_back(*UI);
+        AddToWorkList(*UI);
     }
 
     /// removeFromWorkList - remove all instances of N from the worklist.
@@ -77,14 +77,17 @@
     }
     
   public:
+    /// AddToWorkList - Add to the work list making sure it's instance is at the
+    /// the back (next to be processed.)
     void AddToWorkList(SDNode *N) {
+      removeFromWorkList(N);
       WorkList.push_back(N);
     }
-    
+
     SDOperand CombineTo(SDNode *N, const SDOperand *To, unsigned NumTo) {
       assert(N->getNumValues() == NumTo && "Broken CombineTo call!");
       ++NodesCombined;
-      DEBUG(std::cerr << "\nReplacing "; N->dump();
+      DEBUG(std::cerr << "\nReplacing.1 "; N->dump();
             std::cerr << "\nWith: "; To[0].Val->dump(&DAG);
             std::cerr << " and " << NumTo-1 << " other values\n");
       std::vector<SDNode*> NowDead;
@@ -92,12 +95,12 @@
       
       // Push the new nodes and any users onto the worklist
       for (unsigned i = 0, e = NumTo; i != e; ++i) {
-        WorkList.push_back(To[i].Val);
+        AddToWorkList(To[i].Val);
         AddUsersToWorkList(To[i].Val);
       }
       
-      // Nodes can end up on the worklist more than once.  Make sure we do
-      // not process a node that has been replaced.
+      // Nodes can be reintroduced into the worklist.  Make sure we do not
+      // process a node that has been replaced.
       removeFromWorkList(N);
       for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
         removeFromWorkList(NowDead[i]);
@@ -128,11 +131,11 @@
         return false;
 
       // Revisit the node.
-      WorkList.push_back(Op.Val);
+      AddToWorkList(Op.Val);
       
       // Replace the old value with the new one.
       ++NodesCombined;
-      DEBUG(std::cerr << "\nReplacing "; TLO.Old.Val->dump();
+      DEBUG(std::cerr << "\nReplacing.2 "; TLO.Old.Val->dump();
             std::cerr << "\nWith: "; TLO.New.Val->dump(&DAG);
             std::cerr << '\n');
 
@@ -140,7 +143,7 @@
       DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, NowDead);
       
       // Push the new node and any (possibly new) users onto the worklist.
-      WorkList.push_back(TLO.New.Val);
+      AddToWorkList(TLO.New.Val);
       AddUsersToWorkList(TLO.New.Val);
       
       // Nodes can end up on the worklist more than once.  Make sure we do
@@ -240,13 +243,12 @@
     SDOperand BuildUDIV(SDNode *N);
     SDNode *MatchRotate(SDOperand LHS, SDOperand RHS);
     
-    /// FindBaseOffset - Return true if we can determine base and offset
-    /// information from a given pointer operand.  Provides base and offset as a
-    /// result.
+    /// FindBaseOffset - Return true if base is known not to alias with anything
+    /// but itself.  Provides base object and offset as results.
     static bool FindBaseOffset(SDOperand Ptr,
                                SDOperand &Object, int64_t &Offset);
     
-    /// isAlias - Return true if there is the possibility that the two addresses
+    /// isAlias - Return true if there is any possibility that the two addresses
     /// overlap.
     static bool isAlias(SDOperand Ptr1, int64_t Size1, SDOperand SrcValue1,
                         SDOperand Ptr2, int64_t Size2, SDOperand SrcValue2);
@@ -256,12 +258,13 @@
     static void FindAliasInfo(SDNode *N,
                            SDOperand &Ptr, int64_t &Size, SDOperand &SrcValue);
     
-    /// hasChain - Return true if Op has a chain.  Provides chain if present.
-    ///
-    static bool hasChain(SDOperand Op, SDOperand &Chain);
- 
+    /// GatherAllAliases - Walk up chain skipping non-aliasing memory nodes,
+    /// looking for aliasing nodes and adding them to the Aliases vector.
+    void GatherAllAliases(SDNode *N, SDOperand Chain,
+                          SmallVector<SDOperand, 8> &Aliases);
+
     /// FindBetterChain - Walk up chain skipping non-aliasing memory nodes,
-    /// looking for a better chain.
+    /// looking for a better chain (aliasing node.)
     SDOperand FindBetterChain(SDNode *N, SDOperand Chain);
     
 public:
@@ -388,7 +391,7 @@
   /// DagCombineInfo - Expose the DAG combiner to the target combiner impls.
   TargetLowering::DAGCombinerInfo 
     DagCombineInfo(DAG, !RunningAfterLegalize, this);
-  
+
   // while the worklist isn't empty, inspect the node on the end of it and
   // try and combine it.
   while (!WorkList.empty()) {
@@ -400,9 +403,8 @@
     // reduced number of uses, allowing other xforms.
     if (N->use_empty() && N != &Dummy) {
       for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
-        WorkList.push_back(N->getOperand(i).Val);
+        AddToWorkList(N->getOperand(i).Val);
       
-      removeFromWorkList(N);
       DAG.DeleteNode(N);
       continue;
     }
@@ -429,7 +431,7 @@
                RV.Val->getOpcode() != ISD::DELETED_NODE &&
                "Node was deleted but visit returned new node!");
 
-        DEBUG(std::cerr << "\nReplacing "; N->dump();
+        DEBUG(std::cerr << "\nReplacing.3 "; N->dump();
               std::cerr << "\nWith: "; RV.Val->dump(&DAG);
               std::cerr << '\n');
         std::vector<SDNode*> NowDead;
@@ -442,11 +444,11 @@
         }
           
         // Push the new node and any users onto the worklist
-        WorkList.push_back(RV.Val);
+        AddToWorkList(RV.Val);
         AddUsersToWorkList(RV.Val);
           
-        // Nodes can end up on the worklist more than once.  Make sure we do
-        // not process a node that has been replaced.
+        // Nodes can be reintroduced into the worklist.  Make sure we do not
+        // process a node that has been replaced.
         removeFromWorkList(N);
         for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
           removeFromWorkList(NowDead[i]);
@@ -455,6 +457,8 @@
         DAG.DeleteNode(N);
       }
     }
+    
+//    DetectCycle();
   }
   
   // If the root changed (e.g. it was a dead load, update the root).
@@ -531,80 +535,65 @@
 }
 
 SDOperand DAGCombiner::visitTokenFactor(SDNode *N) {
-  // If the token factor has two operands and one is the entry token, replace
-  // the token factor with the other operand.
-  if (N->getNumOperands() == 2) {
-    if (N->getOperand(0).getOpcode() == ISD::EntryToken ||
-        N->getOperand(0) == N->getOperand(1))
-      return N->getOperand(1);
-    if (N->getOperand(1).getOpcode() == ISD::EntryToken)
-      return N->getOperand(0);
-  }
-  
-  SmallVector<SDNode *, 8> TFs;   // Set of token factor nodes.
+  SmallVector<SDNode *, 8> TFs;   // List of token factors to visit.
   SmallVector<SDOperand, 8> Ops;  // Ops for replacing token factor.
-
-  // Add this ndoe to the token factor set.
+  bool Changed = false;           // If we should replace this token factor.
+  std::set<SDNode *> Visited;     // Visited node set.
+  
+  // Start out with this token factor.
   TFs.push_back(N);
-
-  // Separate token factors from other operands.
-  for (unsigned i = 0, ie = N->getNumOperands(); i != ie; ++i) {
-    SDOperand Op = N->getOperand(i);
-    if (Op.getOpcode() == ISD::TokenFactor)
-      TFs.push_back(Op.Val);
-    else if (Op.getOpcode() != ISD::EntryToken)
-      Ops.push_back(Op);
-  }
-  
-  // If there are token factor operands.
-  if (TFs.size() > 1) {
-    bool Changed = false; // If we should replace this token factor.
-    
-    // For each token factor.
-    for (unsigned j = 1, je = TFs.size(); j != je; ++j) {
-      SDNode *TF = TFs[j];
-      bool CanMerge = true; // Can we merge this token factor.
-      
-      if (CombinerAA) {
-        if (!TF->hasOneUse()) {
-          // Check to see if all users point to members of the token factor set.
-          for (SDNode::use_iterator UI = TF->use_begin(), UE = TF->use_end();
-               CanMerge && UI != UE; ++UI) {
-            SDNode *User = *UI;
-            CanMerge = User->getOpcode() == ISD::TokenFactor &&
-                       std::find(TFs.begin(), TFs.end(), User) != TFs.end();
-          }
-        }
-      } else {
-        CanMerge = TF->hasOneUse();
-      }
-      
-      // If it's valid to merge.
-      if (CanMerge) {
-        // Remove dead token factor node.
-        AddToWorkList(TF); 
+  
+  while (!TFs.empty()) {
+    SDNode *TF = TFs.back();
+    TFs.pop_back();
+  
+    // Check each of the operands.
+    for (unsigned i = 0, ie = TF->getNumOperands(); i != ie; ++i) {
+      SDOperand Op = TF->getOperand(i);
+      
+      // Don't bother if we've seen this node before.
+      if (Visited.find(Op.Val) != Visited.end()) continue;
+      Visited.insert(Op.Val);
+      
+      switch (Op.getOpcode()) {
+      case ISD::EntryToken:
+        // Entry tokens don't need to be added to the list (picked up later.)
+        break;
         
-        // Make sure we don't duplicate operands.
-        unsigned m = Ops.size(); // Number of prior operands.
-        for (unsigned l = 0, le = TF->getNumOperands(); l != le; ++l) {
-          SDOperand Op = TF->getOperand(l);
-          if (std::find(Ops.begin(), Ops.end(), Op) == Ops.end())
-            Ops.push_back(Op);
+      case ISD::TokenFactor:
+        // FIXME - Old code only merged when use of one.
+        if (CombinerAA || Op.hasOneUse()) {
+          // Queue up for processing.
+          TFs.push_back(Op.Val);
+          // Clean up in case the token factor is removed.
+          AddToWorkList(Op.Val);
+          Changed = true;
+          break;
         }
+        // Fall thru
+        
+      default:
+        Ops.push_back(Op);
         Changed = true;
-      } else  {
-        // Can't merge this token factor.
-        Ops.push_back(SDOperand(TF, 0));
+        break;
       }
     }
-    
-    // If we've change things around then replace token factor.
-    if (Changed) {
-      return DAG.getNode(ISD::TokenFactor, MVT::Other, &Ops[0], Ops.size());
+  }
+
+  SDOperand Result;
+
+  // If we've change things around then replace token factor.
+  if (Changed) {
+    if (Ops.size() == 0) {
+      // The entry token is the only possible outcome.
+      Result = DAG.getEntryNode();
+    } else {
+      // New and improved token factor.
+      Result = DAG.getNode(ISD::TokenFactor, MVT::Other, &Ops[0], Ops.size());
     }
   }
   
-  return SDOperand();
+  return Result;
 }
 
 SDOperand DAGCombiner::visitADD(SDNode *N) {
@@ -2622,7 +2611,7 @@
   SDOperand Chain    = N->getOperand(0);
   SDOperand Ptr      = N->getOperand(1);
   SDOperand SrcValue = N->getOperand(2);
-
+  
   // If there are no uses of the loaded value, change uses of the chain value
   // into uses of the chain input (i.e. delete the dead load).
   if (N->hasNUsesOfValue(0, 0))
@@ -2635,27 +2624,23 @@
   if (Chain.getOpcode() == ISD::STORE && Chain.getOperand(2) == Ptr &&
       Chain.getOperand(1).getValueType() == N->getValueType(0))
     return CombineTo(N, Chain.getOperand(1), Chain);
-  
-  // We can only move the load if it has a user of it's chain result.  Otherwise
-  // there is no place to attach it's old chain.
+    
   if (CombinerAA) { 
     // Walk up chain skipping non-aliasing memory nodes.
     SDOperand BetterChain = FindBetterChain(N, Chain);
     
-    // If the there is a better chain.
+    // If there is a better chain.
     if (Chain != BetterChain) {
       // Replace the chain to void dependency.
       SDOperand ReplLoad = DAG.getLoad(N->getValueType(0), BetterChain, Ptr,
                                        SrcValue);
 
-      // Create token factor to keep chain around.
+      // Create token factor to keep old chain connected.
       SDOperand Token = DAG.getNode(ISD::TokenFactor, MVT::Other,
                                     Chain, ReplLoad.getValue(1));
-
-      // Replace uses with load and token factor.
-      CombineTo(N, ReplLoad.getValue(0), Token);
-
-      return SDOperand(N, 0);
+      
+      // Replace uses with load result and token factor.
+      return CombineTo(N, ReplLoad.getValue(0), Token);
     }
   }
 
@@ -2720,23 +2705,14 @@
     // Walk up chain skipping non-aliasing memory nodes.
     SDOperand BetterChain = FindBetterChain(N, Chain);
     
-    // If the there is a better chain.
+    // If there is a better chain.
     if (Chain != BetterChain) {
-      // Replace the chain to void dependency.
+      // Replace the chain to avoid dependency.
       SDOperand ReplStore = DAG.getNode(ISD::STORE, MVT::Other,
                                         BetterChain, Value, Ptr,
                                         SrcValue);
       // Create token to keep both nodes around.
-      SDOperand Token = DAG.getNode(ISD::TokenFactor, MVT::Other,
-                                    Chain, ReplStore);
-
-      // Make sure we merge token factors.
-      AddUsersToWorkList(N);
-      
-      // Old chain needs to be cleaned up.
-      AddToWorkList(Chain.Val);
-         
-      return Token;
+      return DAG.getNode(ISD::TokenFactor, MVT::Other, Chain, ReplStore);
     }
   }
   
@@ -3946,30 +3922,37 @@
   return S;
 }
 
-/// FindBaseOffset - Return true if we can determine base and offset information
-/// from a given pointer operand.  Provides base and offset as a result.
+/// FindBaseOffset - Return true if base is known not to alias with anything
+/// but itself.  Provides base object and offset as results.
 bool DAGCombiner::FindBaseOffset(SDOperand Ptr,
                                  SDOperand &Object, int64_t &Offset) {
-  
-  // Is it a frame variable, global or constant.
-  if (isa<FrameIndexSDNode>(Ptr) ||
-      isa<ConstantPoolSDNode>(Ptr) ||
-      isa<GlobalAddressSDNode>(Ptr)) {
-    Object = Ptr; Offset = 0;
-    return true;
-  } else if (Ptr.getOpcode() == ISD::ADD &&
-             FindBaseOffset(Ptr.getOperand(0), Object, Offset)) {
-    // If it's an add of an simple constant then include it in the offset.
+  // If it's an adding or subtracting a simple constant then add the constant
+  // to the offset.
+  if (Ptr.getOpcode() == ISD::ADD) {
     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Ptr.getOperand(1))) {
+      bool IsNonAliasing = FindBaseOffset(Ptr.getOperand(0), Object, Offset);
       Offset += C->getValue();
-      return true;
+      return IsNonAliasing;
+    }
+  } else if (Ptr.getOpcode() == ISD::SUB) {
+  // FIXME - Aren't all subtract constants converted to add negative constant.
+    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Ptr.getOperand(1))) {
+      bool IsNonAliasing = FindBaseOffset(Ptr.getOperand(0), Object, Offset);
+      Offset -= C->getValue();
+      return IsNonAliasing;
     }
   }
-                                 
-  return false;                               
+  
+  // Primitive operation.
+  Object = Ptr; Offset = 0;
+  
+  // If it's any of the following then it can't alias with anything but itself.
+  return isa<FrameIndexSDNode>(Ptr) ||
+         isa<ConstantPoolSDNode>(Ptr) ||
+         isa<GlobalAddressSDNode>(Ptr);
 }
 
-/// isAlias - Return true if there is the possibility that the two addresses
+/// isAlias - Return true if there is any possibility that the two addresses
 /// overlap.
 bool DAGCombiner::isAlias(SDOperand Ptr1, int64_t Size1,
                           SDOperand SrcValue1,
@@ -3978,22 +3961,20 @@
   // If they are the same then they must be aliases.
   if (Ptr1 == Ptr2) return true;
   
-  // Gather base offset information.  Objects can be frame variables, globals
-  // or constants.
+  // Gather base node and offset information.
   SDOperand Object1, Object2;
   int64_t Offset1, Offset2;
-  if (FindBaseOffset(Ptr1, Object1, Offset1) &&
-      FindBaseOffset(Ptr2, Object2, Offset2)) {
-    // If they have a different base address, then they can't alias.
-    if (Object1 != Object2) return false;
-    
+  bool IsNonAliasing1 = FindBaseOffset(Ptr1, Object1, Offset1);
+  bool IsNonAliasing2 = FindBaseOffset(Ptr2, Object2, Offset2);
+  
+  // If they have a same base address then...
+  if (Object1 == Object2) {
     // Check to see if the addresses overlap.
-    if ((Offset1 + Size1) <= Offset2 || (Offset2 + Size2) <= Offset1)
-      return false;
+    return !((Offset1 + Size1) <= Offset2 || (Offset2 + Size2) <= Offset1);
   }
   
-  // Otherwise we don't know and have to play it safe.
-  return true;
+  // Otherwise they alias if they are both non aliasing.
+  return !IsNonAliasing1 && IsNonAliasing2;
 }
 
 /// FindAliasInfo - Extracts the relevant alias information from the memory
@@ -4012,87 +3993,108 @@
     SrcValue = N->getOperand(3);
     break;
   default:
-    assert(0 && "getAliasInfo expected a memory op");
+    assert(0 && "FindAliasInfo expected a memory operand");
   }
 }
 
-/// hasChain - Return true if Op has a chain.  Provides chain if present.
-///
-bool DAGCombiner::hasChain(SDOperand Op, SDOperand &Chain) {
-  if (Op.getNumOperands() == 0) return false;
-  Chain = Op.getOperand(0);
-  return Chain.getValueType() == MVT::Other;
-}
-
-/// FindBetterChain - Walk up chain skipping non-aliasing memory nodes, looking
-/// for a better chain.
-SDOperand DAGCombiner::FindBetterChain(SDNode *N, SDOperand Chain) {
+/// GatherAllAliases - Walk up chain skipping non-aliasing memory nodes,
+/// looking for aliasing nodes and adding them to the Aliases vector.
+void DAGCombiner::GatherAllAliases(SDNode *N, SDOperand Chain,
+                                   SmallVector<SDOperand, 8> &Aliases) {
+  SmallVector<SDOperand, 8> Ops;        // List of operands to visit.
+  std::set<SDNode *> Visited;           // Visited node set.
+  
   // Get alias information for node.
   SDOperand Ptr;
   int64_t Size;
   SDOperand SrcValue;
   FindAliasInfo(N, Ptr, Size, SrcValue);
 
-  // While we don't encounter any aliasing memory nodes walk up chain.
-  while (true) {
-    switch (Chain.getOpcode()) {
-    case ISD::EntryToken:
-      // Entry token is ideal chain operand.
-      return Chain;
-    case ISD::LOAD:
-    case ISD::STORE: {
-      // Get alias information for chain.
-      SDOperand ChainPtr;
-      int64_t ChainSize;
-      SDOperand ChainSrcValue;
-      FindAliasInfo(Chain.Val, ChainPtr, ChainSize, ChainSrcValue);
-      
-      // If chain is alias then stop here, otherwise continue up chain.
-      if (isAlias(Ptr, Size, SrcValue, ChainPtr, ChainSize, ChainSrcValue))
-        return Chain;
-      else
-        Chain = Chain.getOperand(0);
-      
-      break;
-    }
-    case ISD::TokenFactor: {
-      // Continue up each of token factor operand and accumulate results in
-      // a new token factor.  CSE will handle duplicate elimination.
-      SmallVector<SDOperand, 8> Ops;  // Ops for replacing token factor.
-      bool Change = false;
-      
-      // For each token factor operand. 
-      for (unsigned i = 0, e = Chain.getNumOperands(); i != e; ++i) {
-        SDOperand Op = Chain.getOperand(i);
-        SDOperand OpChain = FindBetterChain(N, Op);
+  // Starting off.
+  Ops.push_back(Chain);
+  
+  // While there are nodes to process.
+  while (!Ops.empty()) {
+    SDOperand Op = Ops.back();
+    Ops.pop_back();
+    
+    for (bool Done = false; !Done;) {
+      // Don't bother if we've been before.
+      if (Visited.find(Op.Val) != Visited.end()) break;
+      Visited.insert(Op.Val);
+    
+      // Assume we're done.
+      Done = true;
+
+      switch (Op.getOpcode()) {
+      case ISD::EntryToken:
+        // Entry token is ideal chain operand, but handled in FindBetterChain.
+        break;
         
-        // Make sure we don't duplicate an operand.
-        if (OpChain.getOpcode() != ISD::EntryToken &&
-            std::find(Ops.begin(), Ops.end(), OpChain) == Ops.end()) {
-          Ops.push_back(OpChain);
-        }
+      case ISD::LOAD:
+      case ISD::STORE: {
+        // Get alias information for Op.
+        SDOperand OpPtr;
+        int64_t OpSize;
+        SDOperand OpSrcValue;
+        FindAliasInfo(Op.Val, OpPtr, OpSize, OpSrcValue);
         
-        // If we added a new operand.
-        Change = Change || Op != OpChain; 
+        // If chain is alias then stop here.
+        if (isAlias(Ptr, Size, SrcValue, OpPtr, OpSize, OpSrcValue)) {
+          Aliases.push_back(Op);
+        } else {
+          // Otherwise walk up the chain.
+          // Clean up old chain.
+          AddToWorkList(Op.Val);
+          // Try up further.
+          Op = Op.getOperand(0);      
+          // We're not done yet.
+          Done = false;
+        }
+        break;
       }
       
-      // If we have new operands.
-      if (Change) {
-        // Create a specialized token factor for this chain. getNode CSE will
-        // handle duplicates. If it's a single operand, getNode will just
-        // return the opernand instead of a new token factor.
-        return DAG.getNode(ISD::TokenFactor, MVT::Other, &Ops[0], Ops.size());
+      case ISD::TokenFactor:
+        // Queue up operands in reverse order to maintain prior order.
+        for (unsigned n = Op.getNumOperands(); n;)
+          Ops.push_back(Op.getOperand(--n));
+        // Eliminate the token factor if we can.
+        AddToWorkList(Op.Val);
+        break;
+        
+      default:
+        // For all other instructions we will just have to take what we can get.
+        Aliases.push_back(Op);
+        break;
       }
-      
-      // Leave things alone.
-      return Chain;
-    }
-    // For all other instructions we will just have to take what we can get.
-    default: return Chain;
     }
   }
+}
+
+/// FindBetterChain - Walk up chain skipping non-aliasing memory nodes, looking
+/// for a better chain (aliasing node.)
+SDOperand DAGCombiner::FindBetterChain(SDNode *N, SDOperand OldChain) {
+  SmallVector<SDOperand, 8> Aliases;  // Ops for replacing token factor.
+  
+  // Accumulate all the aliases to this node.
+  GatherAllAliases(N, OldChain, Aliases);
+  
+  if (Aliases.size() == 0) {
+    // If no operands then chain to entry token.
+    return DAG.getEntryNode();
+  } else if (Aliases.size() == 1) {
+    // If a single operand then chain to it.  We don't need to revisit it.
+    return Aliases[0];
+  }
+
+  // Construct a custom tailored token factor.
+  SDOperand NewChain = DAG.getNode(ISD::TokenFactor, MVT::Other,
+                                   &Aliases[0], Aliases.size());
+
+  // Make sure the old chain gets cleaned up.
+  if (NewChain != OldChain) AddToWorkList(OldChain.Val);
   
-  return Chain;
+  return NewChain;
 }
 
 // SelectionDAG::Combine - This is the entry point for the file.






More information about the llvm-commits mailing list