Define CallSDNode, an SDNode subclass for use with ISD::CALL.
Currently it just holds the calling convention and flags
for isVarArgs and isTailCall.
And it has several utility methods, which eliminate magic
5+2*i and similar index computations in several places.
CallSDNodes are not CSE'd. Teach UpdateNodeOperands to handle
nodes that are not CSE'd gracefully.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@56183 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 6ebd514..921d7b0 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -595,13 +595,13 @@
/// correspond to it. This is useful when we're about to delete or repurpose
/// the node. We don't want future request for structurally identical nodes
/// to return N anymore.
-void SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
+bool SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
bool Erased = false;
switch (N->getOpcode()) {
case ISD::EntryToken:
assert(0 && "EntryToken should not be in CSEMaps!");
- return;
- case ISD::HANDLENODE: return; // noop.
+ return false;
+ case ISD::HANDLENODE: return false; // noop.
case ISD::CONDCODE:
assert(CondCodeNodes[cast<CondCodeSDNode>(N)->get()] &&
"Cond code doesn't exist!");
@@ -635,7 +635,8 @@
// flag result (which cannot be CSE'd) or is one of the special cases that are
// not subject to CSE.
if (!Erased && N->getValueType(N->getNumValues()-1) != MVT::Flag &&
- !N->isTargetOpcode() &&
+ !N->isMachineOpcode() &&
+ N->getOpcode() != ISD::CALL &&
N->getOpcode() != ISD::DBG_LABEL &&
N->getOpcode() != ISD::DBG_STOPPOINT &&
N->getOpcode() != ISD::EH_LABEL &&
@@ -645,6 +646,7 @@
assert(0 && "Node is not in map!");
}
#endif
+ return Erased;
}
/// AddNonLeafNodeToCSEMaps - Add the specified node back to the CSE maps. It
@@ -660,6 +662,7 @@
switch (N->getOpcode()) {
default: break;
+ case ISD::CALL:
case ISD::HANDLENODE:
case ISD::DBG_LABEL:
case ISD::DBG_STOPPOINT:
@@ -3304,6 +3307,21 @@
}
SDValue
+SelectionDAG::getCall(unsigned CallingConv, bool IsVarArgs, bool IsTailCall,
+ SDVTList VTs,
+ const SDValue *Operands, unsigned NumOperands) {
+ // Do not CSE calls. Note that in addition to being a compile-time
+ // optimization (since attempting CSE of calls is unlikely to be
+ // meaningful), we actually depend on this behavior. CallSDNode can
+ // be mutated, which is only safe if calls are not CSE'd.
+ SDNode *N = NodeAllocator.Allocate<CallSDNode>();
+ new (N) CallSDNode(CallingConv, IsVarArgs, IsTailCall,
+ VTs, Operands, NumOperands);
+ AllNodes.push_back(N);
+ return SDValue(N, 0);
+}
+
+SDValue
SelectionDAG::getLoad(ISD::MemIndexedMode AM, ISD::LoadExtType ExtType,
MVT VT, SDValue Chain,
SDValue Ptr, SDValue Offset,
@@ -3761,7 +3779,8 @@
// Nope it doesn't. Remove the node from its current place in the maps.
if (InsertPos)
- RemoveNodeFromCSEMaps(N);
+ if (!RemoveNodeFromCSEMaps(N))
+ InsertPos = 0;
// Now we update the operands.
N->OperandList[0].getVal()->removeUser(0, N);
@@ -3790,7 +3809,8 @@
// Nope it doesn't. Remove the node from its current place in the maps.
if (InsertPos)
- RemoveNodeFromCSEMaps(N);
+ if (!RemoveNodeFromCSEMaps(N))
+ InsertPos = 0;
// Now we update the operands.
if (N->OperandList[0] != Op1) {
@@ -3856,7 +3876,8 @@
// Nope it doesn't. Remove the node from its current place in the maps.
if (InsertPos)
- RemoveNodeFromCSEMaps(N);
+ if (!RemoveNodeFromCSEMaps(N))
+ InsertPos = 0;
// Now we update the operands.
for (unsigned i = 0; i != NumOps; ++i) {
@@ -4079,7 +4100,8 @@
return ON;
}
- RemoveNodeFromCSEMaps(N);
+ if (!RemoveNodeFromCSEMaps(N))
+ IP = 0;
// Start the morphing.
N->NodeType = Opc;
@@ -4582,6 +4604,7 @@
void LoadSDNode::ANCHOR() {}
void StoreSDNode::ANCHOR() {}
void AtomicSDNode::ANCHOR() {}
+void CallSDNode::ANCHOR() {}
HandleSDNode::~HandleSDNode() {
DropOperands();