From 012f241987a017ea74d34d4c126997f84902ef61 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Fri, 17 Feb 2006 21:58:01 +0000 Subject: [PATCH] Fix a tricky issue in the SimplifyDemandedBits code where CombineTo wasn't exactly the API we wanted to call into. This fixes the crash on crafty last night. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26269 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 43 ++++++++++++---- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 61 +++++++++++++++++++++++ 2 files changed, 95 insertions(+), 9 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index f1d0a9b5065..4f7df4f4361 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -99,15 +99,40 @@ namespace { return SDOperand(N, 0); } - bool DemandedBitsAreZero(SDOperand Op, uint64_t DemandedMask) { + /// SimplifyDemandedBits - Check the specified integer node value to see if + /// it can be simplified or if things is uses can be simplified by bit + /// propagation. If so, return true. + bool SimplifyDemandedBits(SDOperand Op) { TargetLowering::TargetLoweringOpt TLO(DAG); uint64_t KnownZero, KnownOne; - if (TLI.SimplifyDemandedBits(Op, DemandedMask, KnownZero, KnownOne, TLO)){ - WorkList.push_back(Op.Val); - CombineTo(TLO.Old.Val, TLO.New); - return true; - } - return false; + uint64_t Demanded = MVT::getIntVTBitMask(Op.getValueType()); + if (!TLI.SimplifyDemandedBits(Op, Demanded, KnownZero, KnownOne, TLO)) + return false; + + // Revisit the node. + WorkList.push_back(Op.Val); + + // Replace the old value with the new one. + ++NodesCombined; + DEBUG(std::cerr << "\nReplacing "; TLO.Old.Val->dump(); + std::cerr << "\nWith: "; TLO.New.Val->dump()); + + std::vector NowDead; + DAG.ReplaceAllUsesOfValueWith(TLO.Old, TLO.New, NowDead); + + // Push the new node and any (now) users onto the worklist. + WorkList.push_back(TLO.New.Val); + AddUsersToWorkList(TLO.New.Val); + + // Nodes can end up on the worklist more than once. Make sure we do + // not process a node that has been replaced. + removeFromWorkList(TLO.Old.Val); + 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(TLO.Old.Val); + return true; } SDOperand CombineTo(SDNode *N, SDOperand Res) { @@ -985,7 +1010,7 @@ SDOperand DAGCombiner::visitAND(SDNode *N) { } // fold (and (sign_extend_inreg x, i16 to i32), 1) -> (and x, 1) // fold (and (sra)) -> (and (srl)) when possible. - if (DemandedBitsAreZero(SDOperand(N, 0), MVT::getIntVTBitMask(VT))) + if (SimplifyDemandedBits(SDOperand(N, 0))) return SDOperand(); // fold (zext_inreg (extload x)) -> (zextload x) if (N0.getOpcode() == ISD::EXTLOAD) { @@ -1267,7 +1292,7 @@ SDOperand DAGCombiner::visitSHL(SDNode *N) { // if (shl x, c) is known to be zero, return 0 if (TLI.MaskedValueIsZero(SDOperand(N, 0), MVT::getIntVTBitMask(VT))) return DAG.getConstant(0, VT); - if (DemandedBitsAreZero(SDOperand(N,0), MVT::getIntVTBitMask(VT))) + if (SimplifyDemandedBits(SDOperand(N, 0))) return SDOperand(); // fold (shl (shl x, c1), c2) -> 0 or (shl x, c1+c2) if (N1C && N0.getOpcode() == ISD::SHL && diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 5fc09671c6c..bb66825cd3d 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -21,6 +21,7 @@ #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include #include @@ -2403,6 +2404,66 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, } } +/// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving +/// uses of other values produced by From.Val alone. The Deleted vector is +/// handled the same was as for ReplaceAllUsesWith. +void SelectionDAG::ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To, + std::vector &Deleted) { + assert(From != To && "Cannot replace a value with itself"); + // Handle the simple, trivial, case efficiently. + if (From.Val->getNumValues() == 1 && To.Val->getNumValues() == 1) { + ReplaceAllUsesWith(From, To, &Deleted); + return; + } + + // Get all of the users in a nice, deterministically ordered, uniqued set. + SetVector Users(From.Val->use_begin(), From.Val->use_end()); + + while (!Users.empty()) { + // We know that this user uses some value of From. If it is the right + // value, update it. + SDNode *User = Users.back(); + Users.pop_back(); + + for (SDOperand *Op = User->OperandList, + *E = User->OperandList+User->NumOperands; Op != E; ++Op) { + if (*Op == From) { + // Okay, we know this user needs to be updated. Remove its old self + // from the CSE maps. + RemoveNodeFromCSEMaps(User); + + // Update all operands that match "From". + for (; Op != E; ++Op) { + if (*Op == From) { + From.Val->removeUser(User); + *Op = To; + To.Val->addUser(User); + } + } + + // Now that we have modified User, add it back to the CSE maps. If it + // already exists there, recursively merge the results together. + if (SDNode *Existing = AddNonLeafNodeToCSEMaps(User)) { + unsigned NumDeleted = Deleted.size(); + ReplaceAllUsesWith(User, Existing, &Deleted); + + // User is now dead. + Deleted.push_back(User); + DeleteNodeNotInCSEMaps(User); + + // We have to be careful here, because ReplaceAllUsesWith could have + // deleted a user of From, which means there may be dangling pointers + // in the "Users" setvector. Scan over the deleted node pointers and + // remove them from the setvector. + for (unsigned i = NumDeleted, e = Deleted.size(); i != e; ++i) + Users.remove(Deleted[i]); + } + break; // Exit the operand scanning loop. + } + } + } +} + //===----------------------------------------------------------------------===// // SDNode Class