From 8ab5fe574a388598b7ca945b4cd12e2485268027 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 16 May 2006 18:18:50 +0000 Subject: [PATCH] Switch the PPC backend over to using FORMAL_ARGUMENTS for formal argument handling. This makes the lower argument code significantly simpler (we only need to handle legal argument types). Incidentally, this also implements support for vector argument registers, so long as they are not on the stack. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@28331 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/PowerPC/PPCISelLowering.cpp | 325 ++++++++++++------------- lib/Target/PowerPC/PPCISelLowering.h | 4 - 2 files changed, 157 insertions(+), 172 deletions(-) diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp index c1d4f403e66..8e010c39918 100644 --- a/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/lib/Target/PowerPC/PPCISelLowering.cpp @@ -727,6 +727,161 @@ static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG, Op.getOperand(1), Op.getOperand(2)); } +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(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + SSARegMap *RegMap = MF.getSSARegMap(); + std::vector ArgValues; + SDOperand Root = Op.getOperand(0); + + unsigned ArgOffset = 24; + unsigned GPR_remaining = 8; + unsigned FPR_remaining = 13; + unsigned VR_remaining = 12; + 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 + }; + + // 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 + // first ones are often in registers. + for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { + SDOperand ArgVal; + bool needsLoad = false; + bool ArgLive = !Op.Val->hasNUsesOfValue(0, ArgNo); + MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); + unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8; + + switch (ObjectVT) { + default: assert(0 && "Unhandled argument type!"); + case MVT::i32: + if (!ArgLive) break; + if (GPR_remaining > 0) { + unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); + MF.addLiveIn(GPR[GPR_idx], VReg); + ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32); + } else { + needsLoad = true; + } + break; + case MVT::f32: + case MVT::f64: + if (!ArgLive) { + if (FPR_remaining > 0) { + --FPR_remaining; + ++FPR_idx; + } + break; + } + if (FPR_remaining > 0) { + unsigned VReg; + if (ObjectVT == MVT::f32) + VReg = RegMap->createVirtualRegister(&PPC::F4RCRegClass); + else + VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass); + MF.addLiveIn(FPR[FPR_idx], VReg); + ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT); + --FPR_remaining; + ++FPR_idx; + } else { + needsLoad = true; + } + break; + case MVT::v4f32: + case MVT::v4i32: + case MVT::v8i16: + case MVT::v16i8: + if (!ArgLive) { + if (VR_remaining > 0) { + --VR_remaining; + ++VR_idx; + } + break; + } + if (VR_remaining > 0) { + unsigned VReg = RegMap->createVirtualRegister(&PPC::VRRCRegClass); + MF.addLiveIn(VR[VR_idx], VReg); + ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT); + --VR_remaining; + ++VR_idx; + } else { + // This should be simple, but requires getting 16-byte aligned stack + // values. + assert(0 && "Loading VR argument not implemented yet!"); + needsLoad = true; + } + break; + } + + // We need to load the argument to a virtual register if we determined above + // that we ran out of physical registers of the appropriate type + if (needsLoad) { + int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); + SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); + ArgVal = DAG.getLoad(ObjectVT, Root, FIN, + DAG.getSrcValue(NULL)); + } + + // Every 4 bytes of argument space consumes one of the GPRs available for + // argument passing. + if (GPR_remaining > 0) { + unsigned delta = (GPR_remaining > 1 && ObjSize == 8) ? 2 : 1; + GPR_remaining -= delta; + GPR_idx += delta; + } + ArgOffset += ObjSize; + + if (ArgVal.Val == 0) + ArgVal = DAG.getNode(ISD::UNDEF, ObjectVT); + ArgValues.push_back(ArgVal); + } + + // If the function takes variable number of arguments, make a frame index for + // 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); + // 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. + std::vector MemOps; + for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) { + unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); + MF.addLiveIn(GPR[GPR_idx], VReg); + SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::i32); + 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); + } + if (!MemOps.empty()) + Root = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps); + } + + ArgValues.push_back(Root); + + // Return the new list of results. + std::vector RetVT(Op.Val->value_begin(), + Op.Val->value_end()); + return DAG.getNode(ISD::MERGE_VALUES, RetVT, ArgValues); +} + static SDOperand LowerRET(SDOperand Op, SelectionDAG &DAG) { SDOperand Copy; switch(Op.getNumOperands()) { @@ -1690,6 +1845,8 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { case ISD::JumpTable: return LowerJumpTable(Op, DAG); case ISD::SETCC: return LowerSETCC(Op, DAG); case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex); + case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG, + VarArgsFrameIndex); case ISD::RET: return LowerRET(Op, DAG); case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG); @@ -1715,174 +1872,6 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { // Other Lowering Code //===----------------------------------------------------------------------===// -std::vector -PPCTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { - // - // add beautiful description of PPC stack frame format, or at least some docs - // - MachineFunction &MF = DAG.getMachineFunction(); - MachineFrameInfo *MFI = MF.getFrameInfo(); - SSARegMap *RegMap = MF.getSSARegMap(); - std::vector ArgValues; - - unsigned ArgOffset = 24; - unsigned GPR_remaining = 8; - unsigned FPR_remaining = 13; - unsigned GPR_idx = 0, FPR_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 - }; - - // Add DAG nodes to load the arguments... On entry to a function on PPC, - // the arguments start at offset 24, although they are likely to be passed - // in registers. - for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { - SDOperand newroot, argt; - unsigned ObjSize; - bool needsLoad = false; - bool ArgLive = !I->use_empty(); - MVT::ValueType ObjectVT = getValueType(I->getType()); - - switch (ObjectVT) { - default: assert(0 && "Unhandled argument type!"); - case MVT::i1: - case MVT::i8: - case MVT::i16: - case MVT::i32: - ObjSize = 4; - if (!ArgLive) break; - if (GPR_remaining > 0) { - unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); - MF.addLiveIn(GPR[GPR_idx], VReg); - argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); - if (ObjectVT != MVT::i32) { - unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext - : ISD::AssertZext; - argt = DAG.getNode(AssertOp, MVT::i32, argt, - DAG.getValueType(ObjectVT)); - argt = DAG.getNode(ISD::TRUNCATE, ObjectVT, argt); - } - } else { - needsLoad = true; - } - break; - case MVT::i64: - ObjSize = 8; - if (!ArgLive) break; - if (GPR_remaining > 0) { - SDOperand argHi, argLo; - unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); - MF.addLiveIn(GPR[GPR_idx], VReg); - argHi = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); - // If we have two or more remaining argument registers, then both halves - // of the i64 can be sourced from there. Otherwise, the lower half will - // have to come off the stack. This can happen when an i64 is preceded - // by 28 bytes of arguments. - if (GPR_remaining > 1) { - unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); - MF.addLiveIn(GPR[GPR_idx+1], VReg); - argLo = DAG.getCopyFromReg(argHi, VReg, MVT::i32); - } else { - int FI = MFI->CreateFixedObject(4, ArgOffset+4); - SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); - argLo = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN, - DAG.getSrcValue(NULL)); - } - // Build the outgoing arg thingy - argt = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, argLo, argHi); - newroot = argLo; - } else { - needsLoad = true; - } - break; - case MVT::f32: - case MVT::f64: - ObjSize = (ObjectVT == MVT::f64) ? 8 : 4; - if (!ArgLive) { - if (FPR_remaining > 0) { - --FPR_remaining; - ++FPR_idx; - } - break; - } - if (FPR_remaining > 0) { - unsigned VReg; - if (ObjectVT == MVT::f32) - VReg = RegMap->createVirtualRegister(&PPC::F4RCRegClass); - else - VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass); - MF.addLiveIn(FPR[FPR_idx], VReg); - argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, ObjectVT); - --FPR_remaining; - ++FPR_idx; - } else { - needsLoad = true; - } - break; - } - - // We need to load the argument to a virtual register if we determined above - // that we ran out of physical registers of the appropriate type - if (needsLoad) { - unsigned SubregOffset = 0; - if (ObjectVT == MVT::i8 || ObjectVT == MVT::i1) SubregOffset = 3; - if (ObjectVT == MVT::i16) SubregOffset = 2; - int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); - SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); - FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, - DAG.getConstant(SubregOffset, MVT::i32)); - argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN, - DAG.getSrcValue(NULL)); - } - - // Every 4 bytes of argument space consumes one of the GPRs available for - // argument passing. - if (GPR_remaining > 0) { - unsigned delta = (GPR_remaining > 1 && ObjSize == 8) ? 2 : 1; - GPR_remaining -= delta; - GPR_idx += delta; - } - ArgOffset += ObjSize; - if (newroot.Val) - DAG.setRoot(newroot.getValue(1)); - - ArgValues.push_back(argt); - } - - // If the function takes variable number of arguments, make a frame index for - // the start of the first vararg value... for expansion of llvm.va_start. - if (F.isVarArg()) { - VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset); - SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32); - // 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. - std::vector MemOps; - for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) { - unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); - MF.addLiveIn(GPR[GPR_idx], VReg); - SDOperand Val = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); - 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, getPointerTy()); - FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff); - } - if (!MemOps.empty()) { - MemOps.push_back(DAG.getRoot()); - DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps)); - } - } - - return ArgValues; -} - std::pair PPCTargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy, bool isVarArg, diff --git a/lib/Target/PowerPC/PPCISelLowering.h b/lib/Target/PowerPC/PPCISelLowering.h index bcd7268b934..f5bfff559bc 100644 --- a/lib/Target/PowerPC/PPCISelLowering.h +++ b/lib/Target/PowerPC/PPCISelLowering.h @@ -166,10 +166,6 @@ namespace llvm { uint64_t &KnownZero, uint64_t &KnownOne, unsigned Depth = 0) const; - /// LowerArguments - This hook must be implemented to indicate how we should - /// lower the arguments for the specified function, into the specified DAG. - virtual std::vector - LowerArguments(Function &F, SelectionDAG &DAG); /// LowerCallTo - This hook lowers an abstract call to a function into an /// actual call.