[llvm-commits] [llvm] r62964 - in /llvm/trunk: include/llvm/CodeGen/SelectionDAG.h lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Dan Gohman
gohman at apple.com
Sun Jan 25 08:29:12 PST 2009
Author: djg
Date: Sun Jan 25 10:29:12 2009
New Revision: 62964
URL: http://llvm.org/viewvc/llvm-project?rev=62964&view=rev
Log:
Eliminate the loop that searches through each of the operands
of each use in the SelectionDAG ReplaceAllUses* functions. Thanks
to Chris for spotting this opportunity.
Also, factor out code from all 5 of the ReplaceAllUses* functions
into AddNonLeafNodeToCSEMaps, which is now renamed
AddModifiedNodeToCSEMaps to more accurately reflect its purpose.
Modified:
llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=62964&r1=62963&r2=62964&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Sun Jan 25 10:29:12 2009
@@ -800,7 +800,7 @@
private:
bool RemoveNodeFromCSEMaps(SDNode *N);
- SDNode *AddNonLeafNodeToCSEMaps(SDNode *N);
+ void AddModifiedNodeToCSEMaps(SDNode *N, DAGUpdateListener *UpdateListener);
SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op, void *&InsertPos);
SDNode *FindModifiedNodeSlot(SDNode *N, SDValue Op1, SDValue Op2,
void *&InsertPos);
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=62964&r1=62963&r2=62964&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Sun Jan 25 10:29:12 2009
@@ -651,20 +651,36 @@
return Erased;
}
-/// AddNonLeafNodeToCSEMaps - Add the specified node back to the CSE maps. It
-/// has been taken out and modified in some way. If the specified node already
-/// exists in the CSE maps, do not modify the maps, but return the existing node
-/// instead. If it doesn't exist, add it and return null.
+/// AddModifiedNodeToCSEMaps - The specified node has been removed from the CSE
+/// maps and modified in place. Add it back to the CSE maps, unless an identical
+/// node already exists, in which case transfer all its users to the existing
+/// node. This transfer can potentially trigger recursive merging.
///
-SDNode *SelectionDAG::AddNonLeafNodeToCSEMaps(SDNode *N) {
- assert(N->getNumOperands() && "This is a leaf node!");
+void
+SelectionDAG::AddModifiedNodeToCSEMaps(SDNode *N,
+ DAGUpdateListener *UpdateListener) {
+ // For node types that aren't CSE'd, just act as if no identical node
+ // already exists.
+ if (!doNotCSE(N)) {
+ SDNode *Existing = CSEMap.GetOrInsertNode(N);
+ if (Existing != N) {
+ // If there was already an existing matching node, use ReplaceAllUsesWith
+ // to replace the dead one with the existing one. This can cause
+ // recursive merging of other unrelated nodes down the line.
+ ReplaceAllUsesWith(N, Existing, UpdateListener);
- if (doNotCSE(N))
- return 0;
+ // N is now dead. Inform the listener if it exists and delete it.
+ if (UpdateListener)
+ UpdateListener->NodeDeleted(N, Existing);
+ DeleteNodeNotInCSEMaps(N);
+ return;
+ }
+ }
- SDNode *New = CSEMap.GetOrInsertNode(N);
- if (New != N) return New; // Node already existed.
- return 0;
+ // If the node doesn't already exist, we updated it. Inform a listener if
+ // it exists.
+ if (UpdateListener)
+ UpdateListener->NodeUpdated(N);
}
/// FindModifiedNodeSlot - Find a slot for the specified node if its operands
@@ -3900,8 +3916,7 @@
// Now we update the operands.
N->OperandList[0].getVal()->removeUser(0, N);
- N->OperandList[0] = Op;
- N->OperandList[0].setUser(N);
+ N->OperandList[0].getSDValue() = Op;
Op.getNode()->addUser(0, N);
// If this gets put into a CSE map, add it.
@@ -3931,14 +3946,12 @@
// Now we update the operands.
if (N->OperandList[0] != Op1) {
N->OperandList[0].getVal()->removeUser(0, N);
- N->OperandList[0] = Op1;
- N->OperandList[0].setUser(N);
+ N->OperandList[0].getSDValue() = Op1;
Op1.getNode()->addUser(0, N);
}
if (N->OperandList[1] != Op2) {
N->OperandList[1].getVal()->removeUser(1, N);
- N->OperandList[1] = Op2;
- N->OperandList[1].setUser(N);
+ N->OperandList[1].getSDValue() = Op2;
Op2.getNode()->addUser(1, N);
}
@@ -3999,8 +4012,7 @@
for (unsigned i = 0; i != NumOps; ++i) {
if (N->OperandList[i] != Ops[i]) {
N->OperandList[i].getVal()->removeUser(i, N);
- N->OperandList[i] = Ops[i];
- N->OperandList[i].setUser(N);
+ N->OperandList[i].getSDValue() = Ops[i];
Ops[i].getNode()->addUser(i, N);
}
}
@@ -4272,7 +4284,7 @@
// Assign the new operands.
N->NumOperands = NumOps;
for (unsigned i = 0, e = NumOps; i != e; ++i) {
- N->OperandList[i] = Ops[i];
+ N->OperandList[i].getSDValue() = Ops[i];
N->OperandList[i].setUser(N);
SDNode *ToUse = N->OperandList[i].getVal();
ToUse->addUser(i, N);
@@ -4410,43 +4422,35 @@
"Cannot replace with this method!");
assert(From != To.getNode() && "Cannot replace uses of with self");
- // Iterate over all the existing uses of From. This specifically avoids
- // visiting any new uses of From that arise while the replacement is
- // happening, because any such uses would be the result of CSE: If an
- // existing node looks like From after one of its operands is replaced
- // by To, we don't want to replace of all its users with To too.
- // See PR3018 for more info.
+ // Iterate over all the existing uses of From. New uses will be added
+ // to the beginning of the use list, which we avoid visiting.
+ // This specifically avoids visiting uses of From that arise while the
+ // replacement is happening, because any such uses would be the result
+ // of CSE: If an existing node looks like From after one of its operands
+ // is replaced by To, we don't want to replace of all its users with To
+ // too. See PR3018 for more info.
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
while (UI != UE) {
- SDNode *U = *UI;
- do ++UI; while (UI != UE && *UI == U);
+ SDNode *User = *UI;
// This node is about to morph, remove its old self from the CSE maps.
- RemoveNodeFromCSEMaps(U);
- int operandNum = 0;
- for (SDNode::op_iterator I = U->op_begin(), E = U->op_end();
- I != E; ++I, ++operandNum)
- if (I->getVal() == From) {
- From->removeUser(operandNum, U);
- *I = To;
- I->setUser(U);
- To.getNode()->addUser(operandNum, U);
- }
-
- // 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, UpdateListener);
- // U is now dead. Inform the listener if it exists and delete it.
- if (UpdateListener)
- UpdateListener->NodeDeleted(U, Existing);
- DeleteNodeNotInCSEMaps(U);
- } else {
- // If the node doesn't already exist, we updated it. Inform a listener if
- // it exists.
- if (UpdateListener)
- UpdateListener->NodeUpdated(U);
- }
+ RemoveNodeFromCSEMaps(User);
+
+ // A user can appear in a use list multiple times, and when this
+ // happens the uses are usually next to each other in the list.
+ // To help reduce the number of CSE recomputations, process all
+ // the uses of this user that we can find this way.
+ do {
+ unsigned operandNum = UI.getOperandNo();
+ ++UI;
+ From->removeUser(operandNum, User);
+ User->OperandList[operandNum].getSDValue() = To;
+ To.getNode()->addUser(operandNum, User);
+ } while (UI != UE && *UI == User);
+
+ // Now that we have modified User, add it back to the CSE maps. If it
+ // already exists there, recursively merge the results together.
+ AddModifiedNodeToCSEMaps(User, UpdateListener);
}
}
@@ -4470,34 +4474,26 @@
// the ReplaceAllUsesWith above.
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
while (UI != UE) {
- SDNode *U = *UI;
- do ++UI; while (UI != UE && *UI == U);
+ SDNode *User = *UI;
// This node is about to morph, remove its old self from the CSE maps.
- RemoveNodeFromCSEMaps(U);
- int operandNum = 0;
- for (SDNode::op_iterator I = U->op_begin(), E = U->op_end();
- I != E; ++I, ++operandNum)
- if (I->getVal() == From) {
- From->removeUser(operandNum, U);
- I->getSDValue().setNode(To);
- To->addUser(operandNum, U);
- }
+ RemoveNodeFromCSEMaps(User);
- // 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, UpdateListener);
- // U is now dead. Inform the listener if it exists and delete it.
- if (UpdateListener)
- UpdateListener->NodeDeleted(U, Existing);
- DeleteNodeNotInCSEMaps(U);
- } else {
- // If the node doesn't already exist, we updated it. Inform a listener if
- // it exists.
- if (UpdateListener)
- UpdateListener->NodeUpdated(U);
- }
+ // A user can appear in a use list multiple times, and when this
+ // happens the uses are usually next to each other in the list.
+ // To help reduce the number of CSE recomputations, process all
+ // the uses of this user that we can find this way.
+ do {
+ unsigned operandNum = UI.getOperandNo();
+ ++UI;
+ From->removeUser(operandNum, User);
+ User->OperandList[operandNum].getSDValue().setNode(To);
+ To->addUser(operandNum, User);
+ } while (UI != UE && *UI == User);
+
+ // Now that we have modified User, add it back to the CSE maps. If it
+ // already exists there, recursively merge the results together.
+ AddModifiedNodeToCSEMaps(User, UpdateListener);
}
}
@@ -4516,36 +4512,28 @@
// the ReplaceAllUsesWith above.
SDNode::use_iterator UI = From->use_begin(), UE = From->use_end();
while (UI != UE) {
- SDNode *U = *UI;
- do ++UI; while (UI != UE && *UI == U);
+ SDNode *User = *UI;
// This node is about to morph, remove its old self from the CSE maps.
- RemoveNodeFromCSEMaps(U);
- int operandNum = 0;
- for (SDNode::op_iterator I = U->op_begin(), E = U->op_end();
- I != E; ++I, ++operandNum)
- if (I->getVal() == From) {
- const SDValue &ToOp = To[I->getSDValue().getResNo()];
- From->removeUser(operandNum, U);
- *I = ToOp;
- I->setUser(U);
- ToOp.getNode()->addUser(operandNum, U);
- }
+ RemoveNodeFromCSEMaps(User);
- // 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, UpdateListener);
- // U is now dead. Inform the listener if it exists and delete it.
- if (UpdateListener)
- UpdateListener->NodeDeleted(U, Existing);
- DeleteNodeNotInCSEMaps(U);
- } else {
- // If the node doesn't already exist, we updated it. Inform a listener if
- // it exists.
- if (UpdateListener)
- UpdateListener->NodeUpdated(U);
- }
+ // A user can appear in a use list multiple times, and when this
+ // happens the uses are usually next to each other in the list.
+ // To help reduce the number of CSE recomputations, process all
+ // the uses of this user that we can find this way.
+ do {
+ unsigned operandNum = UI.getOperandNo();
+ const SDValue &ToOp =
+ To[User->OperandList[operandNum].getSDValue().getResNo()];
+ ++UI;
+ From->removeUser(operandNum, User);
+ User->OperandList[operandNum].getSDValue() = ToOp;
+ ToOp.getNode()->addUser(operandNum, User);
+ } while (UI != UE && *UI == User);
+
+ // Now that we have modified User, add it back to the CSE maps. If it
+ // already exists there, recursively merge the results together.
+ AddModifiedNodeToCSEMaps(User, UpdateListener);
}
}
@@ -4563,57 +4551,62 @@
return;
}
- // Get all of the users of From.getNode(). We want these in a nice,
- // deterministically ordered and uniqued set, so we use a SmallSetVector.
- SmallSetVector<SDNode*, 16> Users(From.getNode()->use_begin(), From.getNode()->use_end());
+ // Iterate over just the existing users of From. See the comments in
+ // the ReplaceAllUsesWith above.
+ SDNode::use_iterator UI = From.getNode()->use_begin(),
+ UE = From.getNode()->use_end();
+ while (UI != UE) {
+ SDNode *User = *UI;
+ bool UserRemovedFromCSEMaps = false;
- 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();
-
- // Scan for an operand that matches From.
- SDNode::op_iterator Op = User->op_begin(), E = User->op_end();
- for (; Op != E; ++Op)
- if (*Op == From) break;
-
- // If there are no matches, the user must use some other result of From.
- if (Op == E) continue;
-
- // 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" in case there are multiple uses.
- for (; Op != E; ++Op) {
- if (*Op == From) {
- From.getNode()->removeUser(Op-User->op_begin(), User);
- *Op = To;
- Op->setUser(User);
- To.getNode()->addUser(Op-User->op_begin(), User);
+ // A user can appear in a use list multiple times, and when this
+ // happens the uses are usually next to each other in the list.
+ // To help reduce the number of CSE recomputations, process all
+ // the uses of this user that we can find this way.
+ do {
+ unsigned operandNum = UI.getOperandNo();
+
+ // Skip uses of different values from the same node.
+ if (User->OperandList[operandNum].getSDValue().getResNo() !=
+ From.getResNo()) {
+ ++UI;
+ continue;
}
- }
-
+
+ // If this node hasn't been modified yet, it's still in the CSE maps,
+ // so remove its old self from the CSE maps.
+ if (!UserRemovedFromCSEMaps) {
+ RemoveNodeFromCSEMaps(User);
+ UserRemovedFromCSEMaps = true;
+ }
+
+ ++UI;
+ From.getNode()->removeUser(operandNum, User);
+ User->OperandList[operandNum].getSDValue() = To;
+ To.getNode()->addUser(operandNum, User);
+ } while (UI != UE && *UI == User);
+
+ // We are iterating over all uses of the From node, so if a use
+ // doesn't use the specific value, no changes are made.
+ if (!UserRemovedFromCSEMaps)
+ continue;
+
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
- SDNode *Existing = AddNonLeafNodeToCSEMaps(User);
- if (!Existing) {
- if (UpdateListener) UpdateListener->NodeUpdated(User);
- continue; // Continue on to next user.
- }
-
- // If there was already an existing matching node, use ReplaceAllUsesWith
- // to replace the dead one with the existing one. This can cause
- // recursive merging of other unrelated nodes down the line.
- ReplaceAllUsesWith(User, Existing, UpdateListener);
-
- // User is now dead. Notify a listener if present.
- if (UpdateListener) UpdateListener->NodeDeleted(User, Existing);
- DeleteNodeNotInCSEMaps(User);
+ AddModifiedNodeToCSEMaps(User, UpdateListener);
}
}
+namespace {
+ /// UseMemo - This class is used by SelectionDAG::ReplaceAllUsesOfValuesWith
+ /// to record information about a use.
+ struct UseMemo {
+ SDNode *User;
+ unsigned Index;
+ unsigned operandNum;
+ };
+}
+
/// ReplaceAllUsesOfValuesWith - Replace any uses of From with To, leaving
/// uses of other values produced by From.getVal() alone. The same value may
/// appear in both the From and To list. The Deleted vector is
@@ -4626,57 +4619,47 @@
if (Num == 1)
return ReplaceAllUsesOfValueWith(*From, *To, UpdateListener);
- SmallVector<std::pair<SDNode *, unsigned>, 16> Users;
- for (unsigned i = 0; i != Num; ++i)
- for (SDNode::use_iterator UI = From[i].getNode()->use_begin(),
- E = From[i].getNode()->use_end(); UI != E; ++UI)
- Users.push_back(std::make_pair(*UI, i));
+ // Read up all the uses and make records of them. This helps
+ // processing new uses that are introduced during the
+ // replacement process.
+ SmallVector<UseMemo, 4> Uses;
+ for (unsigned i = 0; i != Num; ++i) {
+ unsigned FromResNo = From[i].getResNo();
+ SDNode *FromNode = From[i].getNode();
+ for (SDNode::use_iterator UI = FromNode->use_begin(),
+ E = FromNode->use_end(); UI != E; ++UI)
+ if (UI.getUse().getSDValue().getResNo() == FromResNo) {
+ UseMemo Memo = { *UI, i, UI.getOperandNo() };
+ Uses.push_back(Memo);
+ }
+ }
- while (!Users.empty()) {
+ for (unsigned UseIndex = 0, UseIndexEnd = Uses.size();
+ UseIndex != UseIndexEnd; ) {
// We know that this user uses some value of From. If it is the right
// value, update it.
- SDNode *User = Users.back().first;
- unsigned i = Users.back().second;
- Users.pop_back();
-
- // Scan for an operand that matches From.
- SDNode::op_iterator Op = User->op_begin(), E = User->op_end();
- for (; Op != E; ++Op)
- if (*Op == From[i]) break;
-
- // If there are no matches, the user must use some other result of From.
- if (Op == E) continue;
-
- // Okay, we know this user needs to be updated. Remove its old self
- // from the CSE maps.
+ SDNode *User = Uses[UseIndex].User;
+
+ // This node is about to morph, remove its old self from the CSE maps.
RemoveNodeFromCSEMaps(User);
-
- // Update all operands that match "From" in case there are multiple uses.
- for (; Op != E; ++Op) {
- if (*Op == From[i]) {
- From[i].getNode()->removeUser(Op-User->op_begin(), User);
- *Op = To[i];
- Op->setUser(User);
- To[i].getNode()->addUser(Op-User->op_begin(), User);
- }
- }
-
+
+ // A user can appear in a use list multiple times, and when this
+ // happens the uses are usually next to each other in the list.
+ // To help reduce the number of CSE recomputations, process all
+ // the uses of this user that we can find this way.
+ do {
+ unsigned i = Uses[UseIndex].Index;
+ unsigned operandNum = Uses[UseIndex].operandNum;
+ ++UseIndex;
+
+ From[i].getNode()->removeUser(operandNum, User);
+ User->OperandList[operandNum].getSDValue() = To[i];
+ To[i].getNode()->addUser(operandNum, User);
+ } while (UseIndex != UseIndexEnd && Uses[UseIndex].User == User);
+
// Now that we have modified User, add it back to the CSE maps. If it
// already exists there, recursively merge the results together.
- SDNode *Existing = AddNonLeafNodeToCSEMaps(User);
- if (!Existing) {
- if (UpdateListener) UpdateListener->NodeUpdated(User);
- continue; // Continue on to next user.
- }
-
- // If there was already an existing matching node, use ReplaceAllUsesWith
- // to replace the dead one with the existing one. This can cause
- // recursive merging of other unrelated nodes down the line.
- ReplaceAllUsesWith(User, Existing, UpdateListener);
-
- // User is now dead. Notify a listener if present.
- if (UpdateListener) UpdateListener->NodeDeleted(User, Existing);
- DeleteNodeNotInCSEMaps(User);
+ AddModifiedNodeToCSEMaps(User, UpdateListener);
}
}
More information about the llvm-commits
mailing list