aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/SelectionDAG
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2008-09-13 01:54:27 +0000
committerDan Gohman <gohman@apple.com>2008-09-13 01:54:27 +0000
commit095cc29f321382e1f7d295e262a28197f92c5491 (patch)
treebe6c4833a95fbd06a8315df342c5ee55aef50473 /lib/CodeGen/SelectionDAG
parente7de7e3574245fe4cdee3ea895c3aeabca04db63 (diff)
downloadexternal_llvm-095cc29f321382e1f7d295e262a28197f92c5491.zip
external_llvm-095cc29f321382e1f7d295e262a28197f92c5491.tar.gz
external_llvm-095cc29f321382e1f7d295e262a28197f92c5491.tar.bz2
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
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r--lib/CodeGen/SelectionDAG/CallingConvLower.cpp15
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp39
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp11
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp61
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp6
5 files changed, 73 insertions, 59 deletions
diff --git a/lib/CodeGen/SelectionDAG/CallingConvLower.cpp b/lib/CodeGen/SelectionDAG/CallingConvLower.cpp
index 5987e0c..a6f52dd 100644
--- a/lib/CodeGen/SelectionDAG/CallingConvLower.cpp
+++ b/lib/CodeGen/SelectionDAG/CallingConvLower.cpp
@@ -91,12 +91,11 @@ void CCState::AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn) {
/// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info
/// about the passed values into this state.
-void CCState::AnalyzeCallOperands(SDNode *TheCall, CCAssignFn Fn) {
- unsigned NumOps = (TheCall->getNumOperands() - 5) / 2;
+void CCState::AnalyzeCallOperands(CallSDNode *TheCall, CCAssignFn Fn) {
+ unsigned NumOps = TheCall->getNumArgs();
for (unsigned i = 0; i != NumOps; ++i) {
- MVT ArgVT = TheCall->getOperand(5+2*i).getValueType();
- ISD::ArgFlagsTy ArgFlags =
- cast<ARG_FLAGSSDNode>(TheCall->getOperand(5+2*i+1))->getArgFlags();
+ MVT ArgVT = TheCall->getArg(i).getValueType();
+ ISD::ArgFlagsTy ArgFlags = TheCall->getArgFlags(i);
if (Fn(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, *this)) {
cerr << "Call operand #" << i << " has unhandled type "
<< ArgVT.getMVTString() << "\n";
@@ -124,9 +123,9 @@ void CCState::AnalyzeCallOperands(SmallVectorImpl<MVT> &ArgVTs,
/// AnalyzeCallResult - Analyze the return values of an ISD::CALL node,
/// incorporating info about the passed values into this state.
-void CCState::AnalyzeCallResult(SDNode *TheCall, CCAssignFn Fn) {
- for (unsigned i = 0, e = TheCall->getNumValues() - 1; i != e; ++i) {
- MVT VT = TheCall->getValueType(i);
+void CCState::AnalyzeCallResult(CallSDNode *TheCall, CCAssignFn Fn) {
+ for (unsigned i = 0, e = TheCall->getNumRetVals(); i != e; ++i) {
+ MVT VT = TheCall->getRetValType(i);
if (Fn(i, VT, VT, CCValAssign::Full, ISD::ArgFlagsTy(), *this)) {
cerr << "Call result #" << i << " has unhandled type "
<< VT.getMVTString() << "\n";
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 @@ void SelectionDAG::DeleteNodeNotInCSEMaps(SDNode *N) {
/// 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 @@ void SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
// 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 @@ void SelectionDAG::RemoveNodeFromCSEMaps(SDNode *N) {
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 @@ SDNode *SelectionDAG::AddNonLeafNodeToCSEMaps(SDNode *N) {
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::getMergeValues(const SDValue *Ops, unsigned NumOps,
}
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 @@ SDValue SelectionDAG::UpdateNodeOperands(SDValue InN, SDValue Op) {
// 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 @@ UpdateNodeOperands(SDValue InN, SDValue Op1, SDValue Op2) {
// 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 @@ UpdateNodeOperands(SDValue InN, const SDValue *Ops, unsigned NumOps) {
// 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 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
return ON;
}
- RemoveNodeFromCSEMaps(N);
+ if (!RemoveNodeFromCSEMaps(N))
+ IP = 0;
// Start the morphing.
N->NodeType = Opc;
@@ -4582,6 +4604,7 @@ void MemSDNode::ANCHOR() {}
void LoadSDNode::ANCHOR() {}
void StoreSDNode::ANCHOR() {}
void AtomicSDNode::ANCHOR() {}
+void CallSDNode::ANCHOR() {}
HandleSDNode::~HandleSDNode() {
DropOperands();
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index a95a50b..599f0dd 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -5325,9 +5325,6 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
ArgListTy &Args, SelectionDAG &DAG) {
SmallVector<SDValue, 32> Ops;
Ops.push_back(Chain); // Op#0 - Chain
- Ops.push_back(DAG.getConstant(CallingConv, getPointerTy())); // Op#1 - CC
- Ops.push_back(DAG.getConstant(isVarArg, getPointerTy())); // Op#2 - VarArg
- Ops.push_back(DAG.getConstant(isTailCall, getPointerTy())); // Op#3 - Tail
Ops.push_back(Callee);
// Handle all of the outgoing arguments.
@@ -5412,10 +5409,10 @@ TargetLowering::LowerCallTo(SDValue Chain, const Type *RetTy,
LoweredRetTys.push_back(MVT::Other); // Always has a chain.
// Create the CALL node.
- SDValue Res = DAG.getNode(ISD::CALL,
- DAG.getVTList(&LoweredRetTys[0],
- LoweredRetTys.size()),
- &Ops[0], Ops.size());
+ SDValue Res = DAG.getCall(CallingConv, isVarArg, isTailCall,
+ DAG.getVTList(&LoweredRetTys[0],
+ LoweredRetTys.size()),
+ &Ops[0], Ops.size());
Chain = Res.getValue(LoweredRetTys.size() - 1);
// Gather up the call result into a single value.
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 3159db4..fa17510 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -402,56 +402,45 @@ static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
for (SelectionDAG::allnodes_iterator BE = DAG.allnodes_begin(),
BI = DAG.allnodes_end(); BI != BE; ) {
--BI;
- if (BI->getOpcode() == ISD::CALL) {
+ if (CallSDNode *TheCall = dyn_cast<CallSDNode>(BI)) {
SDValue OpRet(Ret, 0);
SDValue OpCall(BI, 0);
- bool isMarkedTailCall =
- cast<ConstantSDNode>(OpCall.getOperand(3))->getZExtValue() != 0;
+ bool isMarkedTailCall = TheCall->isTailCall();
// If CALL node has tail call attribute set to true and the call is not
// eligible (no RET or the target rejects) the attribute is fixed to
// false. The TargetLowering::IsEligibleForTailCallOptimization function
// must correctly identify tail call optimizable calls.
if (!isMarkedTailCall) continue;
if (Ret==NULL ||
- !TLI.IsEligibleForTailCallOptimization(OpCall, OpRet, DAG)) {
- // Not eligible. Mark CALL node as non tail call.
- SmallVector<SDValue, 32> Ops;
- unsigned idx=0;
- for(SDNode::op_iterator I =OpCall.getNode()->op_begin(),
- E = OpCall.getNode()->op_end(); I != E; I++, idx++) {
- if (idx!=3)
- Ops.push_back(*I);
- else
- Ops.push_back(DAG.getConstant(false, TLI.getPointerTy()));
- }
- DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size());
+ !TLI.IsEligibleForTailCallOptimization(TheCall, OpRet, DAG)) {
+ // Not eligible. Mark CALL node as non tail call. Note that we
+ // can modify the call node in place since calls are not CSE'd.
+ TheCall->setNotTailCall();
} else {
// Look for tail call clobbered arguments. Emit a series of
// copyto/copyfrom virtual register nodes to protect them.
SmallVector<SDValue, 32> Ops;
- SDValue Chain = OpCall.getOperand(0), InFlag;
- unsigned idx=0;
- for(SDNode::op_iterator I = OpCall.getNode()->op_begin(),
- E = OpCall.getNode()->op_end(); I != E; I++, idx++) {
- SDValue Arg = *I;
- if (idx > 4 && (idx % 2)) {
- bool isByVal = cast<ARG_FLAGSSDNode>(OpCall.getOperand(idx+1))->
- getArgFlags().isByVal();
- MachineFunction &MF = DAG.getMachineFunction();
- MachineFrameInfo *MFI = MF.getFrameInfo();
- if (!isByVal &&
- IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) {
- MVT VT = Arg.getValueType();
- unsigned VReg = MF.getRegInfo().
- createVirtualRegister(TLI.getRegClassFor(VT));
- Chain = DAG.getCopyToReg(Chain, VReg, Arg, InFlag);
- InFlag = Chain.getValue(1);
- Arg = DAG.getCopyFromReg(Chain, VReg, VT, InFlag);
- Chain = Arg.getValue(1);
- InFlag = Arg.getValue(2);
- }
+ SDValue Chain = TheCall->getChain(), InFlag;
+ Ops.push_back(Chain);
+ Ops.push_back(TheCall->getCallee());
+ for (unsigned i = 0, e = TheCall->getNumArgs(); i != e; ++i) {
+ SDValue Arg = TheCall->getArg(i);
+ bool isByVal = TheCall->getArgFlags(i).isByVal();
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ if (!isByVal &&
+ IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) {
+ MVT VT = Arg.getValueType();
+ unsigned VReg = MF.getRegInfo().
+ createVirtualRegister(TLI.getRegClassFor(VT));
+ Chain = DAG.getCopyToReg(Chain, VReg, Arg, InFlag);
+ InFlag = Chain.getValue(1);
+ Arg = DAG.getCopyFromReg(Chain, VReg, VT, InFlag);
+ Chain = Arg.getValue(1);
+ InFlag = Arg.getValue(2);
}
Ops.push_back(Arg);
+ Ops.push_back(TheCall->getArgFlagsVal(i));
}
// Link in chain of CopyTo/CopyFromReg.
Ops[0] = Chain;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp
index f2cd3c1..570caa9 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp
@@ -179,6 +179,12 @@ std::string DOTGraphTraits<SelectionDAG*>::getNodeLabel(const SDNode *Node,
Op += ":" + utostr(D->getColumn());
} else if (const LabelSDNode *L = dyn_cast<LabelSDNode>(Node)) {
Op += ": LabelID=" + utostr(L->getLabelID());
+ } else if (const CallSDNode *C = dyn_cast<CallSDNode>(Node)) {
+ Op += ": CallingConv=" + utostr(C->getCallingConv());
+ if (C->isVarArg())
+ Op += ", isVarArg";
+ if (C->isTailCall())
+ Op += ", isTailCall";
} else if (const ExternalSymbolSDNode *ES =
dyn_cast<ExternalSymbolSDNode>(Node)) {
Op += "'" + std::string(ES->getSymbol()) + "'";