diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index c7da77c2fbc..e3d8c80bceb 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2737,83 +2737,89 @@ bool DAGCombiner::CombineToPreIndexedLoadStore(SDNode *N) { } else return false; - if ((Ptr.getOpcode() == ISD::ADD || Ptr.getOpcode() == ISD::SUB) && - Ptr.Val->use_size() > 1) { - SDOperand BasePtr; - SDOperand Offset; - ISD::MemIndexedMode AM = ISD::UNINDEXED; - if (TLI.getPreIndexedAddressParts(N, BasePtr, Offset, AM, DAG)) { - // Try turning it into a pre-indexed load / store except when - // 1) If N is a store and the ptr is either the same as or is a - // predecessor of the value being stored. - // 2) Another use of base ptr is a predecessor of N. If ptr is folded - // that would create a cycle. - // 3) All uses are load / store ops that use it as base ptr. + // If the pointer is not an add/sub, or if it doesn't have multiple uses, bail + // out. There is no reason to make this a preinc/predec. + if ((Ptr.getOpcode() != ISD::ADD && Ptr.getOpcode() != ISD::SUB) || + Ptr.Val->hasOneUse()) + return false; - // Checking #1. - if (!isLoad) { - SDOperand Val = cast(N)->getValue(); - if (Val == Ptr || Ptr.Val->isPredecessor(Val.Val)) - return false; - } + // Ask the target to do addressing mode selection. + SDOperand BasePtr; + SDOperand Offset; + ISD::MemIndexedMode AM = ISD::UNINDEXED; + if (!TLI.getPreIndexedAddressParts(N, BasePtr, Offset, AM, DAG)) + return false; + + // Try turning it into a pre-indexed load / store except when + // 1) If N is a store and the ptr is either the same as or is a + // predecessor of the value being stored. + // 2) Another use of base ptr is a predecessor of N. If ptr is folded + // that would create a cycle. + // 3) All uses are load / store ops that use it as base ptr. - // Now check for #2 and #3. - bool RealUse = false; - for (SDNode::use_iterator I = Ptr.Val->use_begin(), - E = Ptr.Val->use_end(); I != E; ++I) { - SDNode *Use = *I; - if (Use == N) - continue; - if (Use->isPredecessor(N)) - return false; - - if (!((Use->getOpcode() == ISD::LOAD && - cast(Use)->getBasePtr() == Ptr) || - (Use->getOpcode() == ISD::STORE) && - cast(Use)->getBasePtr() == Ptr)) - RealUse = true; - } - if (!RealUse) - return false; - - SDOperand Result = isLoad - ? DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM) - : DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM); - ++PreIndexedNodes; - ++NodesCombined; - DEBUG(std::cerr << "\nReplacing.4 "; N->dump(); - std::cerr << "\nWith: "; Result.Val->dump(&DAG); - std::cerr << '\n'); - std::vector NowDead; - if (isLoad) { - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0), - NowDead); - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2), - NowDead); - } else { - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1), - NowDead); - } - - // Nodes can end up on the worklist more than once. Make sure we do - // not process a node that has been replaced. - 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); - - // Replace the uses of Ptr with uses of the updated base value. - DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(isLoad ? 1 : 0), - NowDead); - removeFromWorkList(Ptr.Val); - for (unsigned i = 0, e = NowDead.size(); i != e; ++i) - removeFromWorkList(NowDead[i]); - DAG.DeleteNode(Ptr.Val); - - return true; - } + // Checking #1. + if (!isLoad) { + SDOperand Val = cast(N)->getValue(); + if (Val == Ptr || Ptr.Val->isPredecessor(Val.Val)) + return false; } - return false; + + // Now check for #2 and #3. + bool RealUse = false; + for (SDNode::use_iterator I = Ptr.Val->use_begin(), + E = Ptr.Val->use_end(); I != E; ++I) { + SDNode *Use = *I; + if (Use == N) + continue; + if (Use->isPredecessor(N)) + return false; + + if (!((Use->getOpcode() == ISD::LOAD && + cast(Use)->getBasePtr() == Ptr) || + (Use->getOpcode() == ISD::STORE) && + cast(Use)->getBasePtr() == Ptr)) + RealUse = true; + } + if (!RealUse) + return false; + + SDOperand Result; + if (isLoad) + Result = DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM); + else + Result = DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM); + ++PreIndexedNodes; + ++NodesCombined; + DEBUG(std::cerr << "\nReplacing.4 "; N->dump(); + std::cerr << "\nWith: "; Result.Val->dump(&DAG); + std::cerr << '\n'); + std::vector NowDead; + if (isLoad) { + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0), + NowDead); + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2), + NowDead); + } else { + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1), + NowDead); + } + + // Nodes can end up on the worklist more than once. Make sure we do + // not process a node that has been replaced. + 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); + + // Replace the uses of Ptr with uses of the updated base value. + DAG.ReplaceAllUsesOfValueWith(Ptr, Result.getValue(isLoad ? 1 : 0), + NowDead); + removeFromWorkList(Ptr.Val); + for (unsigned i = 0, e = NowDead.size(); i != e; ++i) + removeFromWorkList(NowDead[i]); + DAG.DeleteNode(Ptr.Val); + + return true; } /// CombineToPostIndexedLoadStore - Try combine a load / store with a @@ -2844,99 +2850,100 @@ bool DAGCombiner::CombineToPostIndexedLoadStore(SDNode *N) { } else return false; - if (Ptr.Val->use_size() > 1) { - for (SDNode::use_iterator I = Ptr.Val->use_begin(), - E = Ptr.Val->use_end(); I != E; ++I) { - SDNode *Op = *I; - if (Op == N || - (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB)) + if (!Ptr.Val->hasOneUse()) + return false; + + for (SDNode::use_iterator I = Ptr.Val->use_begin(), + E = Ptr.Val->use_end(); I != E; ++I) { + SDNode *Op = *I; + if (Op == N || + (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB)) + continue; + + SDOperand BasePtr; + SDOperand Offset; + ISD::MemIndexedMode AM = ISD::UNINDEXED; + if (TLI.getPostIndexedAddressParts(N, Op, BasePtr, Offset, AM, DAG)) { + if (Ptr == Offset) + std::swap(BasePtr, Offset); + if (Ptr != BasePtr) continue; - SDOperand BasePtr; - SDOperand Offset; - ISD::MemIndexedMode AM = ISD::UNINDEXED; - if (TLI.getPostIndexedAddressParts(N, Op, BasePtr, Offset, AM, DAG)) { - if (Ptr == Offset) - std::swap(BasePtr, Offset); - if (Ptr != BasePtr) + // Try turning it into a post-indexed load / store except when + // 1) All uses are load / store ops that use it as base ptr. + // 2) Op must be independent of N, i.e. Op is neither a predecessor + // nor a successor of N. Otherwise, if Op is folded that would + // create a cycle. + + // Check for #1. + bool TryNext = false; + for (SDNode::use_iterator II = BasePtr.Val->use_begin(), + EE = BasePtr.Val->use_end(); II != EE; ++II) { + SDNode *Use = *II; + if (Use == Ptr.Val) continue; - // Try turning it into a post-indexed load / store except when - // 1) All uses are load / store ops that use it as base ptr. - // 2) Op must be independent of N, i.e. Op is neither a predecessor - // nor a successor of N. Otherwise, if Op is folded that would - // create a cycle. + // If all the uses are load / store addresses, then don't do the + // transformation. + if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB){ + bool RealUse = false; + for (SDNode::use_iterator III = Use->use_begin(), + EEE = Use->use_end(); III != EEE; ++III) { + SDNode *UseUse = *III; + if (!((UseUse->getOpcode() == ISD::LOAD && + cast(UseUse)->getBasePtr().Val == Use) || + (UseUse->getOpcode() == ISD::STORE) && + cast(UseUse)->getBasePtr().Val == Use)) + RealUse = true; + } - // Check for #1. - bool TryNext = false; - for (SDNode::use_iterator II = BasePtr.Val->use_begin(), - EE = BasePtr.Val->use_end(); II != EE; ++II) { - SDNode *Use = *II; - if (Use == Ptr.Val) - continue; - - // If all the uses are load / store addresses, then don't do the - // transformation. - if (Use->getOpcode() == ISD::ADD || Use->getOpcode() == ISD::SUB){ - bool RealUse = false; - for (SDNode::use_iterator III = Use->use_begin(), - EEE = Use->use_end(); III != EEE; ++III) { - SDNode *UseUse = *III; - if (!((UseUse->getOpcode() == ISD::LOAD && - cast(UseUse)->getBasePtr().Val == Use) || - (UseUse->getOpcode() == ISD::STORE) && - cast(UseUse)->getBasePtr().Val == Use)) - RealUse = true; - } - - if (!RealUse) { - TryNext = true; - break; - } + if (!RealUse) { + TryNext = true; + break; } } - if (TryNext) - continue; + } + if (TryNext) + continue; - // Check for #2 - if (!Op->isPredecessor(N) && !N->isPredecessor(Op)) { - SDOperand Result = isLoad - ? DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM) - : DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM); - ++PostIndexedNodes; - ++NodesCombined; - DEBUG(std::cerr << "\nReplacing.5 "; N->dump(); - std::cerr << "\nWith: "; Result.Val->dump(&DAG); - std::cerr << '\n'); - std::vector NowDead; - if (isLoad) { - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0), - NowDead); - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2), - NowDead); - } else { - DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1), - NowDead); - } - - // Nodes can end up on the worklist more than once. Make sure we do - // not process a node that has been replaced. - 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); - - // Replace the uses of Use with uses of the updated base value. - DAG.ReplaceAllUsesOfValueWith(SDOperand(Op, 0), - Result.getValue(isLoad ? 1 : 0), + // Check for #2 + if (!Op->isPredecessor(N) && !N->isPredecessor(Op)) { + SDOperand Result = isLoad + ? DAG.getIndexedLoad(SDOperand(N,0), BasePtr, Offset, AM) + : DAG.getIndexedStore(SDOperand(N,0), BasePtr, Offset, AM); + ++PostIndexedNodes; + ++NodesCombined; + DEBUG(std::cerr << "\nReplacing.5 "; N->dump(); + std::cerr << "\nWith: "; Result.Val->dump(&DAG); + std::cerr << '\n'); + std::vector NowDead; + if (isLoad) { + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(0), + NowDead); + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 1), Result.getValue(2), + NowDead); + } else { + DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result.getValue(1), NowDead); - removeFromWorkList(Op); - for (unsigned i = 0, e = NowDead.size(); i != e; ++i) - removeFromWorkList(NowDead[i]); - DAG.DeleteNode(Op); - - return true; } + + // Nodes can end up on the worklist more than once. Make sure we do + // not process a node that has been replaced. + 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); + + // Replace the uses of Use with uses of the updated base value. + DAG.ReplaceAllUsesOfValueWith(SDOperand(Op, 0), + Result.getValue(isLoad ? 1 : 0), + NowDead); + removeFromWorkList(Op); + for (unsigned i = 0, e = NowDead.size(); i != e; ++i) + removeFromWorkList(NowDead[i]); + DAG.DeleteNode(Op); + + return true; } } }