Fix a bug nate ran into with replacealluseswith. In the recursive cse case,

we were losing a node, causing an assertion to fail.  Now we eagerly delete
discovered CSE's, and provide an optional vector to keep track of these
discovered equivalences.

llvm-svn: 23255
This commit is contained in:
Chris Lattner 2005-09-07 05:37:01 +00:00
parent 3852fd0e49
commit fe883adfd2
1 changed files with 45 additions and 15 deletions

View File

@ -27,6 +27,11 @@
#include <algorithm>
using namespace llvm;
// Temporary boolean for testing the dag combiner
namespace llvm {
extern bool CombinerEnabled;
}
static bool isCommutativeBinOp(unsigned Opcode) {
switch (Opcode) {
case ISD::ADD:
@ -234,6 +239,13 @@ void SelectionDAG::DeleteNode(SDNode *N) {
// First take this out of the appropriate CSE map.
RemoveNodeFromCSEMaps(N);
// Finally, remove uses due to operands of this node, remove from the
// AllNodes list, and delete the node.
DeleteNodeNotInCSEMaps(N);
}
void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
// Remove it from the AllNodes list.
for (std::vector<SDNode*>::iterator I = AllNodes.begin(); ; ++I) {
assert(I != AllNodes.end() && "Node not in AllNodes list??");
@ -1244,6 +1256,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N2.Val);
if (N1C) {
if (N2C) {
if (!CombinerEnabled) {
uint64_t C1 = N1C->getValue(), C2 = N2C->getValue();
switch (Opcode) {
case ISD::ADD: return getConstant(C1 + C2, VT);
@ -1271,7 +1284,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
case ISD::SRA : return getConstant(N1C->getSignExtended() >>(int)C2, VT);
default: break;
}
}
} else { // Cannonicalize constant to RHS if commutative
if (isCommutativeBinOp(Opcode)) {
std::swap(N1C, N2C);
@ -1279,6 +1292,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
}
}
if (!CombinerEnabled) {
switch (Opcode) {
default: break;
case ISD::SHL: // shl 0, X -> 0
@ -1295,6 +1309,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
SDOperand Tmp = getNode(ISD::TRUNCATE, cast<VTSDNode>(N2)->getVT(), N1);
return getNode(ISD::SIGN_EXTEND, VT, Tmp);
}
}
}
if (N2C) {
@ -1478,6 +1493,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
ConstantFPSDNode *N2CFP = dyn_cast<ConstantFPSDNode>(N2.Val);
if (N1CFP) {
if (N2CFP) {
if (!CombinerEnabled) {
double C1 = N1CFP->getValue(), C2 = N2CFP->getValue();
switch (Opcode) {
case ISD::ADD: return getConstantFP(C1 + C2, VT);
@ -1491,7 +1507,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
break;
default: break;
}
}
} else { // Cannonicalize constant to RHS if commutative
if (isCommutativeBinOp(Opcode)) {
std::swap(N1CFP, N2CFP);
@ -1507,10 +1523,12 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
// Finally, fold operations that do not require constants.
switch (Opcode) {
case ISD::TokenFactor:
if (!CombinerEnabled) {
if (N1.getOpcode() == ISD::EntryToken)
return N2;
if (N2.getOpcode() == ISD::EntryToken)
return N1;
}
break;
case ISD::AND:
@ -2075,7 +2093,8 @@ void SelectionDAG::SelectNodeTo(SDNode *N, unsigned TargetOpc,
///
/// This version assumes From/To have a single result value.
///
void SelectionDAG::ReplaceAllUsesWith(SDOperand FromN, SDOperand ToN) {
void SelectionDAG::ReplaceAllUsesWith(SDOperand FromN, SDOperand ToN,
std::vector<SDNode*> *Deleted) {
SDNode *From = FromN.Val, *To = ToN.Val;
assert(From->getNumValues() == 1 && To->getNumValues() == 1 &&
"Cannot replace with this method!");
@ -2097,9 +2116,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDOperand FromN, SDOperand ToN) {
// Now that we have modified U, add it back to the CSE maps. If it already
// exists there, recursively merge the results together.
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U))
ReplaceAllUsesWith(U, Existing);
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) {
ReplaceAllUsesWith(U, Existing, Deleted);
// U is now dead.
if (Deleted) Deleted->push_back(U);
DeleteNodeNotInCSEMaps(U);
}
}
}
@ -2109,12 +2131,13 @@ void SelectionDAG::ReplaceAllUsesWith(SDOperand FromN, SDOperand ToN) {
/// This version assumes From/To have matching types and numbers of result
/// values.
///
void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To,
std::vector<SDNode*> *Deleted) {
assert(From != To && "Cannot replace uses of with self");
assert(From->getNumValues() == To->getNumValues() &&
"Cannot use this version of ReplaceAllUsesWith!");
if (From->getNumValues() == 1) { // If possible, use the faster version.
ReplaceAllUsesWith(SDOperand(From, 0), SDOperand(To, 0));
ReplaceAllUsesWith(SDOperand(From, 0), SDOperand(To, 0), Deleted);
return;
}
@ -2134,9 +2157,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
// Now that we have modified U, add it back to the CSE maps. If it already
// exists there, recursively merge the results together.
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U))
ReplaceAllUsesWith(U, Existing);
// U is now dead.
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) {
ReplaceAllUsesWith(U, Existing, Deleted);
// U is now dead.
if (Deleted) Deleted->push_back(U);
DeleteNodeNotInCSEMaps(U);
}
}
}
@ -2146,12 +2172,13 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From, SDNode *To) {
/// This version can replace From with any result values. To must match the
/// number and types of values returned by From.
void SelectionDAG::ReplaceAllUsesWith(SDNode *From,
const std::vector<SDOperand> &To) {
const std::vector<SDOperand> &To,
std::vector<SDNode*> *Deleted) {
assert(From->getNumValues() == To.size() &&
"Incorrect number of values to replace with!");
if (To.size() == 1 && To[0].Val->getNumValues() == 1) {
// Degenerate case handled above.
ReplaceAllUsesWith(SDOperand(From, 0), To[0]);
ReplaceAllUsesWith(SDOperand(From, 0), To[0], Deleted);
return;
}
@ -2172,9 +2199,12 @@ void SelectionDAG::ReplaceAllUsesWith(SDNode *From,
// Now that we have modified U, add it back to the CSE maps. If it already
// exists there, recursively merge the results together.
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U))
ReplaceAllUsesWith(U, Existing);
// U is now dead.
if (SDNode *Existing = AddNonLeafNodeToCSEMaps(U)) {
ReplaceAllUsesWith(U, Existing, Deleted);
// U is now dead.
if (Deleted) Deleted->push_back(U);
DeleteNodeNotInCSEMaps(U);
}
}
}