From 9a2a497284e2233345c4bb9cdc1044d8395fddde Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 17 May 2006 06:01:33 +0000 Subject: [PATCH] Switch PPC over to a call-selection model where the lowering code creates the copyto/fromregs instead of making the PPCISD::CALL selection code create them. This vastly simplifies the selection code, and moves the ABI handling parts into one place. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28346 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp | 124 ++++--------------- lib/Target/PowerPC/PPCISelLowering.cpp | 157 ++++++++++++++++--------- lib/Target/PowerPC/PPCInstrInfo.td | 10 +- 3 files changed, 136 insertions(+), 155 deletions(-) diff --git a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index a9bd05ed537..2a1d2442d81 100644 --- a/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -874,129 +874,55 @@ static bool isCallCompatibleAddress(ConstantSDNode *C) { SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) { SDNode *N = Op.Val; - SDOperand Chain; + SDOperand Chain, Flag; Select(Chain, N->getOperand(0)); + if (N->getNumOperands() == 3) // input flag + Select(Flag, N->getOperand(2)); unsigned CallOpcode; - std::vector CallOperands; - + + std::vector CallArgs; if (GlobalAddressSDNode *GASD = dyn_cast(N->getOperand(1))) { CallOpcode = PPC::BL; - CallOperands.push_back(N->getOperand(1)); + CallArgs.push_back(N->getOperand(1)); } else if (ExternalSymbolSDNode *ESSDN = dyn_cast(N->getOperand(1))) { CallOpcode = PPC::BL; - CallOperands.push_back(N->getOperand(1)); + CallArgs.push_back(N->getOperand(1)); } else if (isa(N->getOperand(1)) && isCallCompatibleAddress(cast(N->getOperand(1)))) { ConstantSDNode *C = cast(N->getOperand(1)); CallOpcode = PPC::BLA; - CallOperands.push_back(getI32Imm((int)C->getValue() >> 2)); + CallArgs.push_back(getI32Imm((int)C->getValue() >> 2)); } else { // Copy the callee address into the CTR register. SDOperand Callee; Select(Callee, N->getOperand(1)); - Chain = SDOperand(CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, Callee, - Chain), 0); + if (Flag.Val) + Chain = SDOperand(CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, MVT::Flag, + Callee, Chain, Flag), 0); + else + Chain = SDOperand(CurDAG->getTargetNode(PPC::MTCTR, MVT::Other, MVT::Flag, + Callee, Chain), 0); + Flag = Chain.getValue(1); // Copy the callee address into R12 on darwin. - SDOperand R12 = CurDAG->getRegister(PPC::R12, MVT::i32); - Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R12, Callee); + Chain = CurDAG->getCopyToReg(Chain, PPC::R12, Callee, Flag); + Flag = Chain.getValue(1); - CallOperands.push_back(R12); CallOpcode = PPC::BCTRL; } - unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; - static const unsigned GPR[] = { - PPC::R3, PPC::R4, PPC::R5, PPC::R6, - PPC::R7, PPC::R8, PPC::R9, PPC::R10, - }; - static const unsigned FPR[] = { - PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, - PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 - }; - static const unsigned VR[] = { - PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, - PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 - }; - - SDOperand InFlag; // Null incoming flag value. - - for (unsigned i = 2, e = N->getNumOperands(); i != e; ++i) { - unsigned DestReg = 0; - MVT::ValueType RegTy = N->getOperand(i).getValueType(); - if (RegTy == MVT::i32) { - assert(GPR_idx < 8 && "Too many int args"); - DestReg = GPR[GPR_idx++]; - } else if (MVT::isFloatingPoint(N->getOperand(i).getValueType())) { - assert(FPR_idx < 13 && "Too many fp args"); - DestReg = FPR[FPR_idx++]; - } else { - assert(MVT::isVector(N->getOperand(i).getValueType()) && "unknown arg!"); - assert(VR_idx < 12 && "Too many vector args"); - DestReg = VR[VR_idx++]; - } - - if (N->getOperand(i).getOpcode() != ISD::UNDEF) { - SDOperand Val; - Select(Val, N->getOperand(i)); - Chain = CurDAG->getCopyToReg(Chain, DestReg, Val, InFlag); - InFlag = Chain.getValue(1); - CallOperands.push_back(CurDAG->getRegister(DestReg, RegTy)); - } - } - - // Finally, once everything is in registers to pass to the call, emit the - // call itself. - if (InFlag.Val) - CallOperands.push_back(InFlag); // Strong dep on register copies. - else - CallOperands.push_back(Chain); // Weak dep on whatever occurs before + // Emit the call itself. + CallArgs.push_back(Chain); + if (Flag.Val) + CallArgs.push_back(Flag); Chain = SDOperand(CurDAG->getTargetNode(CallOpcode, MVT::Other, MVT::Flag, - CallOperands), 0); - - std::vector CallResults; - - // If the call has results, copy the values out of the ret val registers. - switch (N->getValueType(0)) { - default: assert(0 && "Unexpected ret value!"); - case MVT::Other: break; - case MVT::i32: - if (N->getValueType(1) == MVT::i32) { - Chain = CurDAG->getCopyFromReg(Chain, PPC::R4, MVT::i32, - Chain.getValue(1)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, - Chain.getValue(2)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - } else { - Chain = CurDAG->getCopyFromReg(Chain, PPC::R3, MVT::i32, - Chain.getValue(1)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - } - break; - case MVT::f32: - case MVT::f64: - Chain = CurDAG->getCopyFromReg(Chain, PPC::F1, N->getValueType(0), - Chain.getValue(1)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - break; - case MVT::v4f32: - case MVT::v4i32: - case MVT::v8i16: - case MVT::v16i8: - Chain = CurDAG->getCopyFromReg(Chain, PPC::V2, N->getValueType(0), - Chain.getValue(1)).getValue(1); - CallResults.push_back(Chain.getValue(0)); - break; - } - - CallResults.push_back(Chain); - for (unsigned i = 0, e = CallResults.size(); i != e; ++i) - CodeGenMap[Op.getValue(i)] = CallResults[i]; - return CallResults[Op.ResNo]; + CallArgs), 0); + CodeGenMap[Op.getValue(0)] = Chain; + CodeGenMap[Op.getValue(1)] = Chain.getValue(1); + return Chain.getValue(Op.ResNo); } // Select - Convert the specified operand from a target-independent to a diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index afb36175d12..7a24b31c6be 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -925,11 +925,25 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { // must be stored to our stack, and loaded into integer regs as well, if // any integer regs are available for argument passing. unsigned ArgOffset = 24; - unsigned GPR_remaining = 8; - unsigned FPR_remaining = 13; - unsigned VR_remaining = 12; - - std::vector MemOps; + unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; + static const unsigned GPR[] = { + PPC::R3, PPC::R4, PPC::R5, PPC::R6, + PPC::R7, PPC::R8, PPC::R9, PPC::R10, + }; + static const unsigned FPR[] = { + PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, + PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 + }; + static const unsigned VR[] = { + PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, + PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 + }; + const unsigned NumGPRs = sizeof(GPR)/sizeof(GPR[0]); + const unsigned NumFPRs = sizeof(FPR)/sizeof(FPR[0]); + const unsigned NumVRs = sizeof( VR)/sizeof( VR[0]); + + std::vector > RegsToPass; + std::vector MemOpChains; for (unsigned i = 5, e = Op.getNumOperands(); i != e; ++i) { SDOperand Arg = Op.getOperand(i); @@ -940,58 +954,52 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { switch (Arg.getValueType()) { default: assert(0 && "Unexpected ValueType for argument!"); case MVT::i32: - if (GPR_remaining > 0) { - args_to_use.push_back(Arg); - --GPR_remaining; + if (GPR_idx != NumGPRs) { + RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg)); } else { - MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Arg, PtrOff, DAG.getSrcValue(NULL))); + MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, + Arg, PtrOff, DAG.getSrcValue(NULL))); } ArgOffset += 4; break; case MVT::f32: case MVT::f64: - if (FPR_remaining > 0) { - args_to_use.push_back(Arg); - --FPR_remaining; + if (FPR_idx != NumFPRs) { + RegsToPass.push_back(std::make_pair(FPR[FPR_idx++], Arg)); + if (isVarArg) { SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain, Arg, PtrOff, DAG.getSrcValue(NULL)); - MemOps.push_back(Store); + MemOpChains.push_back(Store); + // Float varargs are always shadowed in available integer registers - if (GPR_remaining > 0) { + if (GPR_idx != NumGPRs) { SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, DAG.getSrcValue(NULL)); - MemOps.push_back(Load.getValue(1)); - args_to_use.push_back(Load); - --GPR_remaining; + MemOpChains.push_back(Load.getValue(1)); + RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); } - if (GPR_remaining > 0 && Arg.getValueType() == MVT::f64) { + if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64) { SDOperand ConstFour = DAG.getConstant(4, PtrOff.getValueType()); PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour); SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, DAG.getSrcValue(NULL)); - MemOps.push_back(Load.getValue(1)); - args_to_use.push_back(Load); - --GPR_remaining; + MemOpChains.push_back(Load.getValue(1)); + RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); } } else { // If we have any FPRs remaining, we may also have GPRs remaining. // Args passed in FPRs consume either 1 (f32) or 2 (f64) available // GPRs. - if (GPR_remaining > 0) { - args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32)); - --GPR_remaining; - } - if (GPR_remaining > 0 && Arg.getValueType() == MVT::f64) { - args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32)); - --GPR_remaining; - } + if (GPR_idx != NumGPRs) + ++GPR_idx; + if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64) + ++GPR_idx; } } else { - MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, - Arg, PtrOff, DAG.getSrcValue(NULL))); + MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, + Arg, PtrOff, DAG.getSrcValue(NULL))); } ArgOffset += (Arg.getValueType() == MVT::f32) ? 4 : 8; break; @@ -1000,43 +1008,86 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { case MVT::v8i16: case MVT::v16i8: assert(!isVarArg && "Don't support passing vectors to varargs yet!"); - assert(VR_remaining && + assert(VR_idx != NumVRs && "Don't support passing more than 12 vector args yet!"); - args_to_use.push_back(Arg); - --VR_remaining; + RegsToPass.push_back(std::make_pair(VR[VR_idx++], Arg)); break; } } - if (!MemOps.empty()) - Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps); + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOpChains); - std::vector RetVals(Op.Val->value_begin(), - Op.Val->value_end()); + // Build a sequence of copy-to-reg nodes chained together with token chain + // and flag operands which copy the outgoing args into the appropriate regs. + SDOperand InFlag; + for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { + Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second, + InFlag); + InFlag = Chain.getValue(1); + } // If the callee is a GlobalAddress node (quite common, every direct call is) // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. if (GlobalAddressSDNode *G = dyn_cast(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32); - + Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType()); + + // Create the PPCISD::CALL node itself. + std::vector NodeTys; + NodeTys.push_back(MVT::Other); // Returns a chain + NodeTys.push_back(MVT::Flag); // Returns a flag for retval copy to use. std::vector Ops; Ops.push_back(Chain); Ops.push_back(Callee); - Ops.insert(Ops.end(), args_to_use.begin(), args_to_use.end()); - SDOperand TheCall = DAG.getNode(PPCISD::CALL, RetVals, Ops); + if (InFlag.Val) + Ops.push_back(InFlag); + Chain = DAG.getNode(PPCISD::CALL, NodeTys, Ops); + InFlag = Chain.getValue(1); + + std::vector ResultVals; + NodeTys.clear(); + + // If the call has results, copy the values out of the ret val registers. + switch (Op.Val->getValueType(0)) { + default: assert(0 && "Unexpected ret value!"); + case MVT::Other: break; + case MVT::i32: + if (Op.Val->getValueType(1) == MVT::i32) { + Chain = DAG.getCopyFromReg(Chain, PPC::R4, MVT::i32, InFlag).getValue(1); + ResultVals.push_back(Chain.getValue(0)); + Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, + Chain.getValue(2)).getValue(1); + ResultVals.push_back(Chain.getValue(0)); + NodeTys.push_back(MVT::i32); + } else { + Chain = DAG.getCopyFromReg(Chain, PPC::R3, MVT::i32, InFlag).getValue(1); + ResultVals.push_back(Chain.getValue(0)); + } + NodeTys.push_back(MVT::i32); + break; + case MVT::f32: + case MVT::f64: + Chain = DAG.getCopyFromReg(Chain, PPC::F1, Op.Val->getValueType(0), + InFlag).getValue(1); + ResultVals.push_back(Chain.getValue(0)); + NodeTys.push_back(Op.Val->getValueType(0)); + break; + case MVT::v4f32: + case MVT::v4i32: + case MVT::v8i16: + case MVT::v16i8: + Chain = DAG.getCopyFromReg(Chain, PPC::V2, Op.Val->getValueType(0), + InFlag).getValue(1); + ResultVals.push_back(Chain.getValue(0)); + NodeTys.push_back(Op.Val->getValueType(0)); + break; + } - Chain = TheCall.getValue(TheCall.Val->getNumValues()-1); Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, DAG.getConstant(NumBytes, MVT::i32)); + NodeTys.push_back(MVT::Other); - std::vector RetVT(Op.Val->value_begin(), - Op.Val->value_end()); - Ops.clear(); - - for (unsigned i = 0, e = TheCall.Val->getNumValues()-1; i != e; ++i) - Ops.push_back(SDOperand(TheCall.Val, i)); - Ops.push_back(Chain); - SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, RetVT, Ops); - + ResultVals.push_back(Chain); + SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, NodeTys, ResultVals); return Res.getValue(Op.ResNo); } diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index 8333873f082..e195414fe01 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -72,6 +72,10 @@ def PPCstd_32 : SDNode<"PPCISD::STD_32" , SDTStore, [SDNPHasChain]>; def callseq_start : SDNode<"ISD::CALLSEQ_START", SDT_PPCCallSeq,[SDNPHasChain]>; def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeq,[SDNPHasChain]>; +def SDT_PPCCall : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>; +def call : SDNode<"PPCISD::CALL", SDT_PPCCall, + [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>; + def retflag : SDNode<"PPCISD::RET_FLAG", SDT_PPCRetFlag, [SDNPHasChain, SDNPOptInFlag]>; @@ -303,11 +307,11 @@ let isCall = 1, noResults = 1, PPC970_Unit = 7, LR,CTR, CR0,CR1,CR5,CR6,CR7] in { // Convenient aliases for call instructions - def BL : IForm<18, 0, 1, (ops calltarget:$func, variable_ops), + def BL : IForm<18, 0, 1, (ops calltarget:$func), "bl $func", BrB, []>; - def BLA : IForm<18, 1, 1, (ops aaddr:$func, variable_ops), + def BLA : IForm<18, 1, 1, (ops aaddr:$func), "bla $func", BrB, []>; - def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops variable_ops), "bctrl", BrB, + def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops), "bctrl", BrB, []>; }