From c91a4757b60094ade6fc82afde7f94bbe1988a7d Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Mon, 26 Jun 2006 22:48:35 +0000 Subject: [PATCH] Improve PPC64 calling convention support git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28919 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelLowering.cpp | 121 +++++++++++++++++-------- 1 file changed, 84 insertions(+), 37 deletions(-) diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index cb5ee26d79b..59f7848d6ef 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -733,8 +733,8 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG, Op.getOperand(1), Op.getOperand(2)); } -static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, - int &VarArgsFrameIndex) { +static SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG, + int &VarArgsFrameIndex) { // TODO: add description of PPC stack frame format, or at least some docs. // MachineFunction &MF = DAG.getMachineFunction(); @@ -748,10 +748,15 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, const unsigned Num_FPR_Regs = 13; const unsigned Num_VR_Regs = 12; unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; - static const unsigned GPR[] = { + + static const unsigned GPR_32[] = { // 32-bit registers. PPC::R3, PPC::R4, PPC::R5, PPC::R6, PPC::R7, PPC::R8, PPC::R9, PPC::R10, }; + static const unsigned GPR_64[] = { // 64-bit registers. + PPC::X3, PPC::X4, PPC::X5, PPC::X6, + PPC::X7, PPC::X8, PPC::X9, PPC::X10, + }; 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 @@ -760,6 +765,10 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 }; + + MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = PtrVT == MVT::i64; + const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; // Add DAG nodes to load the arguments or copy them out of registers. On // entry to a function on PPC, the arguments start at offset 24, although the @@ -771,12 +780,11 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8; unsigned CurArgOffset = ArgOffset; - switch (ObjectVT) { default: assert(0 && "Unhandled argument type!"); case MVT::i32: // All int arguments reserve stack space. - ArgOffset += 4; + ArgOffset += isPPC64 ? 8 : 4; if (GPR_idx != Num_GPR_Regs) { unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); @@ -787,6 +795,19 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, needsLoad = true; } break; + case MVT::i64: // PPC64 + // All int arguments reserve stack space. + ArgOffset += 8; + + if (GPR_idx != Num_GPR_Regs) { + unsigned VReg = RegMap->createVirtualRegister(&PPC::G8RCRegClass); + MF.addLiveIn(GPR[GPR_idx], VReg); + ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64); + ++GPR_idx; + } else { + needsLoad = true; + } + break; case MVT::f32: case MVT::f64: // All FP arguments reserve stack space. @@ -838,7 +859,7 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, // slot. if (!Op.Val->hasNUsesOfValue(0, ArgNo)) { int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset); - SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); + SDOperand FIN = DAG.getFrameIndex(FI, PtrVT); ArgVal = DAG.getLoad(ObjectVT, Root, FIN, DAG.getSrcValue(NULL)); } else { @@ -854,8 +875,9 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, // the start of the first vararg value... for expansion of llvm.va_start. bool isVarArg = cast(Op.getOperand(2))->getValue() != 0; if (isVarArg) { - VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset); - SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32); + VarArgsFrameIndex = MFI->CreateFixedObject(MVT::getSizeInBits(PtrVT)/8, + ArgOffset); + SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); // If this function is vararg, store any remaining integer argument regs // to their spots on the stack so that they may be loaded by deferencing the // result of va_next. @@ -863,13 +885,13 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, for (; GPR_idx != Num_GPR_Regs; ++GPR_idx) { unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); MF.addLiveIn(GPR[GPR_idx], VReg); - SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32); + SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT); SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), Val, FIN, DAG.getSrcValue(NULL)); MemOps.push_back(Store); // Increment the address by four for the next argument to store - SDOperand PtrOff = DAG.getConstant(4, MVT::i32); - FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff); + SDOperand PtrOff = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8, PtrVT); + FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff); } if (!MemOps.empty()) Root = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps); @@ -883,11 +905,6 @@ static SDOperand LowerFORMAL_ARGUMENTS_32(SDOperand Op, SelectionDAG &DAG, return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues); } -static SDOperand LowerFORMAL_ARGUMENTS_64(SDOperand Op, SelectionDAG &DAG, - int &VarArgsFrameIndex) { - return LowerFORMAL_ARGUMENTS_32(Op, DAG, VarArgsFrameIndex); -} - /// isCallCompatibleAddress - Return the immediate to use if the specified /// 32-bit value is representable in the immediate field of a BxA instruction. static SDNode *isBLACompatibleAddress(SDOperand Op, SelectionDAG &DAG) { @@ -911,14 +928,19 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { SDOperand Callee = Op.getOperand(4); unsigned NumOps = (Op.getNumOperands() - 5) / 2; + MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); + bool isPPC64 = PtrVT == MVT::i64; + unsigned PtrByteSize = isPPC64 ? 8 : 4; + + // args_to_use will accumulate outgoing args for the PPCISD::CALL case in // SelectExpr to use to put the arguments in the appropriate registers. std::vector args_to_use; // Count how many bytes are to be pushed on the stack, including the linkage - // area, and parameter passing area. We start with 24 bytes, which is + // area, and parameter passing area. We start with 24/48 bytes, which is // prereserved space for [SP][CR][LR][3 x unused]. - unsigned NumBytes = 24; + unsigned NumBytes = 6*PtrByteSize; // Add up all the space actually used. for (unsigned i = 0; i != NumOps; ++i) @@ -929,29 +951,37 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { // Because we cannot tell if this is needed on the caller side, we have to // conservatively assume that it is needed. As such, make sure we have at // least enough stack space for the caller to store the 8 GPRs. - if (NumBytes < 24+8*4) - NumBytes = 24+8*4; + if (NumBytes < 6*PtrByteSize+8*PtrByteSize) + NumBytes = 6*PtrByteSize+8*PtrByteSize; // Adjust the stack pointer for the new arguments... // These operations are automatically eliminated by the prolog/epilog pass Chain = DAG.getCALLSEQ_START(Chain, - DAG.getConstant(NumBytes, MVT::i32)); + DAG.getConstant(NumBytes, PtrVT)); // Set up a copy of the stack pointer for use loading and storing any // arguments that may not fit in the registers available for argument // passing. - SDOperand StackPtr = DAG.getRegister(PPC::R1, MVT::i32); + SDOperand StackPtr; + if (isPPC64) + StackPtr = DAG.getRegister(PPC::X1, MVT::i64); + else + StackPtr = DAG.getRegister(PPC::R1, MVT::i32); // Figure out which arguments are going to go in registers, and which in // memory. Also, if this is a vararg function, floating point operations // 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 ArgOffset = 6*PtrByteSize; unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; - static const unsigned GPR[] = { + static const unsigned GPR_32[] = { // 32-bit registers. PPC::R3, PPC::R4, PPC::R5, PPC::R6, PPC::R7, PPC::R8, PPC::R9, PPC::R10, }; + static const unsigned GPR_64[] = { // 64-bit registers. + PPC::X3, PPC::X4, PPC::X5, PPC::X6, + PPC::X7, PPC::X8, PPC::X9, PPC::X10, + }; 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 @@ -960,10 +990,12 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { 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 NumGPRs = sizeof(GPR_32)/sizeof(GPR_32[0]); const unsigned NumFPRs = sizeof(FPR)/sizeof(FPR[0]); const unsigned NumVRs = sizeof( VR)/sizeof( VR[0]); + const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; + std::vector > RegsToPass; std::vector MemOpChains; for (unsigned i = 0; i != NumOps; ++i) { @@ -972,17 +1004,27 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { // PtrOff will be used to store the current argument to the stack if a // register cannot be found for it. SDOperand PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType()); - PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff); + PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff); + + // On PPC64, promote integers to 64-bit values. + if (isPPC64 && Arg.getValueType() == MVT::i32) { + unsigned ExtOp = ISD::ZERO_EXTEND; + if (cast(Op.getOperand(5+2*i+1))->getValue()) + ExtOp = ISD::SIGN_EXTEND; + Arg = DAG.getNode(ExtOp, MVT::i64, Arg); + } + switch (Arg.getValueType()) { default: assert(0 && "Unexpected ValueType for argument!"); case MVT::i32: + case MVT::i64: if (GPR_idx != NumGPRs) { RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg)); } else { MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, Arg, PtrOff, DAG.getSrcValue(NULL))); } - ArgOffset += 4; + ArgOffset += PtrByteSize; break; case MVT::f32: case MVT::f64: @@ -997,15 +1039,15 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { // Float varargs are always shadowed in available integer registers if (GPR_idx != NumGPRs) { - SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, + SDOperand Load = DAG.getLoad(PtrVT, Store, PtrOff, DAG.getSrcValue(NULL)); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); } 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, + PtrOff = DAG.getNode(ISD::ADD, PtrVT, PtrOff, ConstFour); + SDOperand Load = DAG.getLoad(PtrVT, Store, PtrOff, DAG.getSrcValue(NULL)); MemOpChains.push_back(Load.getValue(1)); RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); @@ -1016,14 +1058,17 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { // GPRs. if (GPR_idx != NumGPRs) ++GPR_idx; - if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64) + if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && !isPPC64) ++GPR_idx; } } else { MemOpChains.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, Arg, PtrOff, DAG.getSrcValue(NULL))); } - ArgOffset += (Arg.getValueType() == MVT::f32) ? 4 : 8; + if (isPPC64) + ArgOffset += 8; + else + ArgOffset += Arg.getValueType() == MVT::f32 ? 4 : 8; break; case MVT::v4f32: case MVT::v4i32: @@ -1127,6 +1172,11 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { } NodeTys.push_back(MVT::i32); break; + case MVT::i64: + Chain = DAG.getCopyFromReg(Chain, PPC::X3, MVT::i64, InFlag).getValue(1); + ResultVals.push_back(Chain.getValue(0)); + NodeTys.push_back(MVT::i64); + break; case MVT::f32: case MVT::f64: Chain = DAG.getCopyFromReg(Chain, PPC::F1, Op.Val->getValueType(0), @@ -1146,7 +1196,7 @@ static SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG) { } Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, - DAG.getConstant(NumBytes, MVT::i32)); + DAG.getConstant(NumBytes, PtrVT)); NodeTys.push_back(MVT::Other); // If the function returns void, just return the chain. @@ -2136,10 +2186,7 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { case ISD::SETCC: return LowerSETCC(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex); case ISD::FORMAL_ARGUMENTS: - if (getPointerTy() == MVT::i32) - return LowerFORMAL_ARGUMENTS_32(Op, DAG, VarArgsFrameIndex); - else - return LowerFORMAL_ARGUMENTS_64(Op, DAG, VarArgsFrameIndex); + return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex); case ISD::CALL: return LowerCALL(Op, DAG); case ISD::RET: return LowerRET(Op, DAG);