Make changes to avoid creating nested CALLSEQ_START/END constructs, which aren't

yet legal according to comments in LegalizeDAG.cpp:227. 

Memcpy nodes created for copying byval arguments are inserted before
CALLSEQ_START.

The two failing tests reported in PR10876 pass after applying this patch.  


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140046 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Akira Hatanaka 2011-09-19 20:26:02 +00:00
parent bcc1a737f5
commit da7f5f1c1d

View File

@ -1799,7 +1799,7 @@ static const unsigned O32IntRegs[] = {
// Write ByVal Arg to arg registers and stack. // Write ByVal Arg to arg registers and stack.
static void static void
WriteByValArg(SDValue& Chain, DebugLoc dl, WriteByValArg(SDValue& ByValChain, SDValue Chain, DebugLoc dl,
SmallVector<std::pair<unsigned, SDValue>, 16>& RegsToPass, SmallVector<std::pair<unsigned, SDValue>, 16>& RegsToPass,
SmallVector<SDValue, 8>& MemOpChains, int& LastFI, SmallVector<SDValue, 8>& MemOpChains, int& LastFI,
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
@ -1882,19 +1882,18 @@ WriteByValArg(SDValue& Chain, DebugLoc dl,
DAG.getConstant(Offset, MVT::i32)); DAG.getConstant(Offset, MVT::i32));
LastFI = MFI->CreateFixedObject(RemainingSize, LocMemOffset, true); LastFI = MFI->CreateFixedObject(RemainingSize, LocMemOffset, true);
SDValue Dst = DAG.getFrameIndex(LastFI, PtrType); SDValue Dst = DAG.getFrameIndex(LastFI, PtrType);
Chain = DAG.getMemcpy(Chain, dl, Dst, Src, ByValChain = DAG.getMemcpy(ByValChain, dl, Dst, Src,
DAG.getConstant(RemainingSize, MVT::i32), DAG.getConstant(RemainingSize, MVT::i32),
std::min(ByValAlign, (unsigned)4), std::min(ByValAlign, (unsigned)4),
/*isVolatile=*/false, /*AlwaysInline=*/false, /*isVolatile=*/false, /*AlwaysInline=*/false,
MachinePointerInfo(0), MachinePointerInfo(0)); MachinePointerInfo(0), MachinePointerInfo(0));
MemOpChains.push_back(Chain);
} }
/// LowerCall - functions arguments are copied from virtual regs to /// LowerCall - functions arguments are copied from virtual regs to
/// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted.
/// TODO: isTailCall. /// TODO: isTailCall.
SDValue SDValue
MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee, MipsTargetLowering::LowerCall(SDValue InChain, SDValue Callee,
CallingConv::ID CallConv, bool isVarArg, CallingConv::ID CallConv, bool isVarArg,
bool &isTailCall, bool &isTailCall,
const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<ISD::OutputArg> &Outs,
@ -1924,8 +1923,13 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
// Get a count of how many bytes are to be pushed on the stack. // Get a count of how many bytes are to be pushed on the stack.
unsigned NextStackOffset = CCInfo.getNextStackOffset(); unsigned NextStackOffset = CCInfo.getNextStackOffset();
Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NextStackOffset, // Chain is the output chain of the last Load/Store or CopyToReg node.
true)); // ByValChain is the output chain of the last Memcpy node created for copying
// byval arguments to the stack.
SDValue Chain, CallSeqStart, ByValChain;
SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true);
Chain = CallSeqStart = DAG.getCALLSEQ_START(InChain, NextStackOffsetVal);
ByValChain = InChain;
// If this is the first call, create a stack frame object that points to // If this is the first call, create a stack frame object that points to
// a location to which .cprestore saves $gp. // a location to which .cprestore saves $gp.
@ -2019,8 +2023,8 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
"No support for ByVal args by ABIs other than O32 yet."); "No support for ByVal args by ABIs other than O32 yet.");
assert(Flags.getByValSize() && assert(Flags.getByValSize() &&
"ByVal args of size 0 should have been ignored by front-end."); "ByVal args of size 0 should have been ignored by front-end.");
WriteByValArg(Chain, dl, RegsToPass, MemOpChains, LastFI, MFI, DAG, Arg, WriteByValArg(ByValChain, Chain, dl, RegsToPass, MemOpChains, LastFI, MFI,
VA, Flags, getPointerTy(), Subtarget->isLittle()); DAG, Arg, VA, Flags, getPointerTy(), Subtarget->isLittle());
continue; continue;
} }
@ -2042,6 +2046,12 @@ MipsTargetLowering::LowerCall(SDValue Chain, SDValue Callee,
if (LastFI) if (LastFI)
MipsFI->extendOutArgFIRange(FirstFI, LastFI); MipsFI->extendOutArgFIRange(FirstFI, LastFI);
// If a memcpy has been created to copy a byval arg to a stack, replace the
// chain input of CallSeqStart with ByValChain.
if (InChain != ByValChain)
DAG.UpdateNodeOperands(CallSeqStart.getNode(), ByValChain,
NextStackOffsetVal);
// Transform all store nodes into one single node because all store // Transform all store nodes into one single node because all store
// nodes are independent of each other. // nodes are independent of each other.
if (!MemOpChains.empty()) if (!MemOpChains.empty())