Fix a case where LegalizeAllNodesNotLeadingTo could take exponential time.
authorChris Lattner <sabre@nondot.org>
Wed, 26 Jul 2006 23:55:56 +0000 (23:55 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 26 Jul 2006 23:55:56 +0000 (23:55 +0000)
This manifested itself as really long time to compile
Regression/CodeGen/Generic/2003-05-28-ManyArgs.ll on ppc.
This is PR847.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@29313 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

index 6fe5249af1625d12ac974782c2c1b249a2d29063..9d0f65370462b58e04723e349bb58b4f72386159 100644 (file)
@@ -177,7 +177,8 @@ private:
   /// build_vector Mask.  If it's not a legal shuffle, it returns null.
   SDNode *isShuffleLegal(MVT::ValueType VT, SDOperand Mask) const;
   
-  bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest);
+  bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest,
+                                    std::set<SDNode*> &NodesLeadingTo);
 
   void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC);
     
@@ -406,10 +407,18 @@ static SDNode *FindCallStartFromCallEnd(SDNode *Node) {
 /// LegalizeAllNodesNotLeadingTo - Recursively walk the uses of N, looking to
 /// see if any uses can reach Dest.  If no dest operands can get to dest, 
 /// legalize them, legalize ourself, and return false, otherwise, return true.
-bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N, 
-                                                        SDNode *Dest) {
+///
+/// Keep track of the nodes we fine that actually do lead to Dest in
+/// NodesLeadingTo.  This avoids retraversing them exponential number of times.
+///
+bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest,
+                                            std::set<SDNode*> &NodesLeadingTo) {
   if (N == Dest) return true;  // N certainly leads to Dest :)
   
+  // If we've already processed this node and it does lead to Dest, there is no
+  // need to reprocess it.
+  if (NodesLeadingTo.count(N)) return true;
+  
   // If the first result of this node has been already legalized, then it cannot
   // reach N.
   switch (getTypeAction(N->getValueType(0))) {
@@ -429,9 +438,12 @@ bool SelectionDAGLegalize::LegalizeAllNodesNotLeadingTo(SDNode *N,
   bool OperandsLeadToDest = false;
   for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
     OperandsLeadToDest |=     // If an operand leads to Dest, so do we.
-      LegalizeAllNodesNotLeadingTo(N->getOperand(i).Val, Dest);
+      LegalizeAllNodesNotLeadingTo(N->getOperand(i).Val, Dest, NodesLeadingTo);
 
-  if (OperandsLeadToDest) return true;
+  if (OperandsLeadToDest) {
+    NodesLeadingTo.insert(N);
+    return true;
+  }
 
   // Okay, this node looks safe, legalize it and return false.
   HandleOp(SDOperand(N, 0));
@@ -1043,8 +1055,11 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     // Recursively Legalize all of the inputs of the call end that do not lead
     // to this call start.  This ensures that any libcalls that need be inserted
     // are inserted *before* the CALLSEQ_START.
+    {std::set<SDNode*> NodesLeadingTo;
     for (unsigned i = 0, e = CallEnd->getNumOperands(); i != e; ++i)
-      LegalizeAllNodesNotLeadingTo(CallEnd->getOperand(i).Val, Node);
+      LegalizeAllNodesNotLeadingTo(CallEnd->getOperand(i).Val, Node,
+                                   NodesLeadingTo);
+    }
 
     // Now that we legalized all of the inputs (which may have inserted
     // libcalls) create the new CALLSEQ_START node.