[llvm-commits] [llvm] r48028 - /llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
Dale Johannesen
dalej at apple.com
Fri Mar 7 12:27:40 PST 2008
Author: johannes
Date: Fri Mar 7 14:27:40 2008
New Revision: 48028
URL: http://llvm.org/viewvc/llvm-project?rev=48028&view=rev
Log:
Next bits of PPC byval handling. Basically functional
but there are bugs.
Modified:
llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
Modified: llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp?rev=48028&r1=48027&r2=48028&view=diff
==============================================================================
--- llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/PowerPC/PPCISelLowering.cpp Fri Mar 7 14:27:40 2008
@@ -1347,6 +1347,8 @@
// represented with two words (long long or double) must be copied to an
// even GPR_idx value or to an even ArgOffset value.
+ SmallVector<SDOperand, 8> MemOps;
+
for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) {
SDOperand ArgVal;
bool needsLoad = false;
@@ -1355,12 +1357,50 @@
unsigned ArgSize = ObjSize;
unsigned Flags = cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue();
unsigned AlignFlag = 1 << ISD::ParamFlags::OrigAlignmentOffs;
+ unsigned isByVal = Flags & ISD::ParamFlags::ByVal;
// See if next argument requires stack alignment in ELF
bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) &&
(cast<ConstantSDNode>(Op.getOperand(ArgNo+4))->getValue() & AlignFlag) &&
(!(Flags & AlignFlag)));
unsigned CurArgOffset = ArgOffset;
+
+ // FIXME alignment for ELF may not be right
+ // FIXME the codegen can be much improved in some cases.
+ // We do not have to keep everything in memory.
+ if (isByVal) {
+ // Double word align in ELF
+ if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2);
+ // ObjSize is the true size, ArgSize rounded up to multiple of registers.
+ ObjSize = (Flags & ISD::ParamFlags::ByValSize) >>
+ ISD::ParamFlags::ByValSizeOffs;
+ ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize;
+ // The value of the object is its address.
+ int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset);
+ SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+ ArgValues.push_back(FIN);
+ for (unsigned j = 0; j < ArgSize; j += PtrByteSize) {
+ // Store whatever pieces of the object are in registers
+ // to memory. ArgVal will be address of the beginning of
+ // the object.
+ if (GPR_idx != Num_GPR_Regs) {
+ unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass);
+ RegInfo.addLiveIn(GPR[GPR_idx], VReg);
+ int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset);
+ SDOperand FIN = DAG.getFrameIndex(FI, PtrVT);
+ SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT);
+ SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0);
+ MemOps.push_back(Store);
+ ++GPR_idx;
+ if (isMachoABI) ArgOffset += PtrByteSize;
+ } else {
+ ArgOffset += ArgSize - (ArgOffset-CurArgOffset);
+ break;
+ }
+ }
+ continue;
+ }
+
switch (ObjectVT) {
default: assert(0 && "Unhandled argument type!");
case MVT::i32:
@@ -1453,7 +1493,7 @@
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<ConstantSDNode>(Op.getOperand(2))->getValue() != 0;
@@ -1481,8 +1521,6 @@
depth);
SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT);
- SmallVector<SDOperand, 8> MemOps;
-
// In ELF 32 ABI, the fixed integer arguments of a variadic function are
// stored to the VarArgsFrameIndex on the stack.
if (isELF32_ABI) {
@@ -1542,11 +1580,11 @@
FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff);
}
}
-
- if (!MemOps.empty())
- Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
}
+ if (!MemOps.empty())
+ Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size());
+
ArgValues.push_back(Root);
// Return the new list of results.
@@ -1705,10 +1743,37 @@
}
// FIXME Elf untested, what are alignment rules?
+ // FIXME memcpy is used way more than necessary. Correctness first.
if (Flags & ISD::ParamFlags::ByVal) {
unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >>
ISD::ParamFlags::ByValSizeOffs;
if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2);
+ if (Size==1 || Size==2) {
+ // Very small objects are passed right-justified.
+ // Everything else is passed left-justified.
+ MVT::ValueType VT = (Size==1) ? MVT::i8 : MVT::i16;
+ if (GPR_idx != NumGPRs) {
+ SDOperand Load = DAG.getExtLoad(ISD::EXTLOAD, PtrVT, Chain, Arg,
+ NULL, 0, VT);
+ MemOpChains.push_back(Load.getValue(1));
+ RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load));
+ if (isMachoABI)
+ ArgOffset += PtrByteSize;
+ } else {
+ SDOperand Const = DAG.getConstant(4 - Size, PtrOff.getValueType());
+ SDOperand AddPtr = DAG.getNode(ISD::ADD, PtrVT, PtrOff, Const);
+ SDOperand MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr,
+ CallSeqStart.Val->getOperand(0),
+ Flags, DAG, Size);
+ // This must go outside the CALLSEQ_START..END.
+ SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
+ CallSeqStart.Val->getOperand(1));
+ DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
+ Chain = CallSeqStart = NewCallSeqStart;
+ ArgOffset += PtrByteSize;
+ }
+ continue;
+ }
for (unsigned j=0; j<Size; j+=PtrByteSize) {
SDOperand Const = DAG.getConstant(j, PtrOff.getValueType());
SDOperand AddArg = DAG.getNode(ISD::ADD, PtrVT, Arg, Const);
@@ -1727,8 +1792,9 @@
SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall,
CallSeqStart.Val->getOperand(1));
DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val);
- CallSeqStart = NewCallSeqStart;
+ Chain = CallSeqStart = NewCallSeqStart;
ArgOffset += ((Size - j + 3)/4)*4;
+ break;
}
}
continue;
More information about the llvm-commits
mailing list