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

Chris Lattner lattner at cs.uiuc.edu
Mon Oct 10 15:04:59 PDT 2005



Changes in directory llvm/lib/CodeGen/SelectionDAG:

DAGCombiner.cpp updated: 1.27 -> 1.28
---
Log message:

Add support for CombineTo, allowing the dag combiner to replace nodes with
multiple results.

Use this support to implement trivial store->load forwarding, implementing
CodeGen/PowerPC/store-load-fwd.ll.  Though this is the most simple case and
can be extended in the future, it is still useful.  For example, it speeds
up 197.parser by 6.2% by avoiding an LSU reject in xalloc:

        stw r6, lo16(l5_end_of_array)(r2)
        addi r2, r5, -4
        stwx r5, r4, r2
-       lwzx r5, r4, r2
-       rlwinm r5, r5, 0, 0, 30
        stwx r5, r4, r2
        lwz r2, -4(r4)
        ori r2, r2, 1



---
Diffs of the changes:  (+56 -2)

 DAGCombiner.cpp |   58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 56 insertions(+), 2 deletions(-)


Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.27 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.28
--- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp:1.27	Mon Oct 10 16:26:48 2005
+++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp	Mon Oct 10 17:04:48 2005
@@ -23,7 +23,6 @@
 // FIXME: select C, pow2, pow2 -> something smart
 // FIXME: trunc(select X, Y, Z) -> select X, trunc(Y), trunc(Z)
 // FIXME: (select C, load A, load B) -> load (select C, A, B)
-// FIXME: store -> load -> forward substitute
 // FIXME: Dead stores -> nuke
 // FIXME: shr X, (and Y,31) -> shr X, Y
 // FIXME: TRUNC (LOAD)   -> EXT_LOAD/LOAD(smaller)
@@ -36,6 +35,7 @@
 // FIXME: divide by zero is currently left unfolded.  do we want to turn this
 //        into an undef?
 // FIXME: select ne (select cc, 1, 0), 0, true, false -> select cc, true, false
+// FIXME: reassociate (X+C)+Y  into (X+Y)+C  if the inner expression has one use
 // 
 //===----------------------------------------------------------------------===//
 
@@ -76,6 +76,37 @@
                      WorkList.end());
     }
     
+    SDOperand CombineTo(SDNode *N, const std::vector<SDOperand> &To) {
+      DEBUG(std::cerr << "\nReplacing "; N->dump();
+            std::cerr << "\nWith: "; To[0].Val->dump();
+            std::cerr << " and " << To.size()-1 << " other values\n");
+      std::vector<SDNode*> NowDead;
+      DAG.ReplaceAllUsesWith(N, To, &NowDead);
+      
+      // Push the new nodes and any users onto the worklist
+      for (unsigned i = 0, e = To.size(); i != e; ++i) {
+        WorkList.push_back(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.
+      removeFromWorkList(N);
+      for (unsigned i = 0, e = NowDead.size(); i != e; ++i)
+        removeFromWorkList(NowDead[i]);
+      
+      // Finally, since the node is now dead, remove it from the graph.
+      DAG.DeleteNode(N);
+      return SDOperand(N, 0);
+    }
+    
+    SDOperand CombineTo(SDNode *N, SDOperand Res0, SDOperand Res1) {
+      std::vector<SDOperand> To;
+      To.push_back(Res0);
+      To.push_back(Res1);
+      return CombineTo(N, To);
+    }
+    
     /// visit - call the node-specific routine that knows how to fold each
     /// particular type of node.
     SDOperand visit(SDNode *N);
@@ -84,6 +115,7 @@
     // node types.  The semantics are as follows:
     // Return Value:
     //   SDOperand.Val == 0   - No change was made
+    //   SDOperand.Val == N   - N was replaced, is dead, and is already handled.
     //   otherwise            - N should be replaced by the returned Operand.
     //
     SDOperand visitTokenFactor(SDNode *N);
@@ -132,6 +164,8 @@
     SDOperand visitBR_CC(SDNode *N);
     SDOperand visitBRTWOWAY_CC(SDNode *N);
 
+    SDOperand visitLOAD(SDNode *N);
+
     SDOperand SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2);
     SDOperand SimplifySelectCC(SDOperand N0, SDOperand N1, SDOperand N2, 
                                SDOperand N3, ISD::CondCode CC);
@@ -334,7 +368,8 @@
         DEBUG(std::cerr << "\nReplacing "; N->dump();
               std::cerr << "\nWith: "; RV.Val->dump();
               std::cerr << '\n');
-        DAG.ReplaceAllUsesWith(N, std::vector<SDOperand>(1, RV));
+        std::vector<SDNode*> NowDead;
+        DAG.ReplaceAllUsesWith(N, std::vector<SDOperand>(1, RV), &NowDead);
           
         // Push the new node and any users onto the worklist
         WorkList.push_back(RV.Val);
@@ -343,6 +378,8 @@
         // Nodes can end up on the worklist more than once.  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]);
         
         // Finally, since the node is now dead, remove it from the graph.
         DAG.DeleteNode(N);
@@ -401,6 +438,7 @@
   case ISD::BRCONDTWOWAY:       return visitBRCONDTWOWAY(N);
   case ISD::BR_CC:              return visitBR_CC(N);
   case ISD::BRTWOWAY_CC:        return visitBRTWOWAY_CC(N);
+  case ISD::LOAD:               return visitLOAD(N);
   }
   return SDOperand();
 }
@@ -1513,6 +1551,22 @@
   return SDOperand();
 }
 
+SDOperand DAGCombiner::visitLOAD(SDNode *N) {
+  SDOperand Chain    = N->getOperand(0);
+  SDOperand Ptr      = N->getOperand(1);
+  SDOperand SrcValue = N->getOperand(2);
+  
+  // If this load is directly stored, replace the load value with the stored
+  // value.
+  // TODO: Handle store large -> read small portion.
+  // TODO: Handle TRUNCSTORE/EXTLOAD
+  if (Chain.getOpcode() == ISD::STORE && Chain.getOperand(2) == Ptr &&
+      Chain.getOperand(1).getValueType() == N->getValueType(0))
+    return CombineTo(N, Chain.getOperand(1), Chain);
+  
+  return SDOperand();
+}
+
 SDOperand DAGCombiner::SimplifySelect(SDOperand N0, SDOperand N1, SDOperand N2){
   assert(N0.getOpcode() ==ISD::SETCC && "First argument must be a SetCC node!");
   






More information about the llvm-commits mailing list