diff options
author | Dan Gohman <gohman@apple.com> | 2008-09-13 01:54:27 +0000 |
---|---|---|
committer | Dan Gohman <gohman@apple.com> | 2008-09-13 01:54:27 +0000 |
commit | 095cc29f321382e1f7d295e262a28197f92c5491 (patch) | |
tree | be6c4833a95fbd06a8315df342c5ee55aef50473 /lib/CodeGen/SelectionDAG | |
parent | e7de7e3574245fe4cdee3ea895c3aeabca04db63 (diff) | |
download | external_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.cpp | 15 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 39 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp | 11 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 61 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAGPrinter.cpp | 6 |
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()) + "'"; |