summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2006-07-26 23:55:56 +0000
committerChris Lattner <sabre@nondot.org>2006-07-26 23:55:56 +0000
commit4488f0c303bc9fd9216960aafd87e8d36437e90e (patch)
tree4c9a19d85b91f495c0b69ead0b43ed381666a181
parent9384400d83d7894b8db6756cb7f9ea573ec3ab87 (diff)
downloadllvm-4488f0c303bc9fd9216960aafd87e8d36437e90e.tar.gz
Fix a case where LegalizeAllNodesNotLeadingTo could take exponential time.
This manifested itself as really long time to compile Regression/CodeGen/Generic/2003-05-28-ManyArgs.ll on ppc. This is PR847. llvm-svn: 29313
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp27
1 files changed, 21 insertions, 6 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index 6fe5249af162..9d0f65370462 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -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.