Author: arnolds Date: Fri Jan 11 10:49:42 2008 New Revision: 45867 URL: http://llvm.org/viewvc/llvm-project?rev=45867&view=rev Log: Improve tail call optimized call's argument lowering. Before this commit all arguments where moved to the stack slot where they would reside on a normal function call before the lowering to the tail call stack slot. This was done to prevent arguments overwriting each other. Now only arguments sourcing from a FORMAL_ARGUMENTS node or a CopyFromReg node with virtual register (could also be a caller's argument) are lowered indirectly.
--This line, and those below, will be ignored-- M X86/X86ISelLowering.cpp M X86/README.txt Modified: llvm/trunk/lib/Target/X86/README.txt llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Modified: llvm/trunk/lib/Target/X86/README.txt URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/README.txt?rev=45867&r1=45866&r2=45867&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/README.txt (original) +++ llvm/trunk/lib/Target/X86/README.txt Fri Jan 11 10:49:42 2008 @@ -1330,10 +1330,11 @@ Tail call optimization improvements: Tail call optimization currently pushes all arguments on the top of the stack (their normal place for -non-tail call optimized calls) before moving them to actual stack -slot. This is done to prevent overwriting of parameters (see example -below) that might be used, since the arguments of the callee -overwrites caller's arguments. +non-tail call optimized calls) that source from the callers arguments +or that source from a virtual register (also possibly sourcing from +callers arguments). +This is done to prevent overwriting of parameters (see example +below) that might be used later. example: @@ -1352,13 +1353,6 @@ Possible optimizations: - - Only push those arguments to the top of the stack that are actual - parameters of the caller function and have no local value in the - caller. - - In the above example local does not need to be pushed onto the top - of the stack as it is definitely not a caller's function - parameter. - Analyse the actual parameters of the callee to see which would overwrite a caller parameter which is used by the callee and only @@ -1380,35 +1374,6 @@ Here we need to push the arguments because they overwrite each other. - - Code for lowering directly onto callers arguments: -+ SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass; -+ SmallVector<SDOperand, 8> MemOpChains; -+ -+ SDOperand FramePtr; -+ SDOperand PtrOff; -+ SDOperand FIN; -+ int FI = 0; -+ // Walk the register/memloc assignments, inserting copies/loads. -+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { -+ CCValAssign &VA = ArgLocs[i]; -+ SDOperand Arg = Op.getOperand(5+2*VA.getValNo()); -+ -+ .... -+ -+ if (VA.isRegLoc()) { -+ RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); -+ } else { -+ assert(VA.isMemLoc()); -+ // create frame index -+ int32_t Offset = VA.getLocMemOffset()+FPDiff; -+ uint32_t OpSize = (MVT::getSizeInBits(VA.getLocVT())+7)/8; -+ FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset); -+ FIN = DAG.getFrameIndex(FI, MVT::i32); -+ // store relative to framepointer -+ MemOpChains.push_back(DAG.getStore(Chain, Arg, FIN, NULL, 0)); -+ } -+ } //===---------------------------------------------------------------------===// main () Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=45867&r1=45866&r2=45867&view=diff ============================================================================== --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original) +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Fri Jan 11 10:49:42 2008 @@ -1007,6 +1007,45 @@ return None; } + +// IsPossiblyOverriddenArgumentOfTailCall - Check if the operand could possibly +// be overridden when lowering the outgoing arguments in a tail call. Currently +// the implementation of this call is very conservative and assumes all +// arguments sourcing from FORMAL_ARGUMENTS or a CopyFromReg with virtual +// registers would be overridden by direct lowering. +// Possible improvement: +// Check FORMAL_ARGUMENTS corresponding MERGE_VALUES for CopyFromReg nodes +// indicating inreg passed arguments which also need not be lowered to a safe +// stack slot. +static bool IsPossiblyOverriddenArgumentOfTailCall(SDOperand Op) { + RegisterSDNode * OpReg = NULL; + if (Op.getOpcode() == ISD::FORMAL_ARGUMENTS || + (Op.getOpcode()== ISD::CopyFromReg && + (OpReg = cast<RegisterSDNode>(Op.getOperand(1))) && + OpReg->getReg() >= MRegisterInfo::FirstVirtualRegister)) + return true; + return false; +} + +// GetMemCpyWithFlags - Create a MemCpy using function's parameter flag. +static SDOperand +GetMemCpyWithFlags(SelectionDAG &DAG, unsigned Flags, SDOperand From, + SDOperand To, SDOperand Chain) { + + unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >> + ISD::ParamFlags::ByValAlignOffs); + + unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >> + ISD::ParamFlags::ByValSizeOffs; + + SDOperand AlignNode = DAG.getConstant(Align, MVT::i32); + SDOperand SizeNode = DAG.getConstant(Size, MVT::i32); + SDOperand AlwaysInline = DAG.getConstant(1, MVT::i32); + + return DAG.getMemcpy(Chain, To, From, SizeNode, AlignNode, + AlwaysInline); +} + SDOperand X86TargetLowering::LowerMemArgument(SDOperand Op, SelectionDAG &DAG, const CCValAssign &VA, MachineFrameInfo *MFI, @@ -1221,18 +1260,7 @@ SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo()); unsigned Flags = cast<ConstantSDNode>(FlagsOp)->getValue(); if (Flags & ISD::ParamFlags::ByVal) { - unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >> - ISD::ParamFlags::ByValAlignOffs); - - unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; - - SDOperand AlignNode = DAG.getConstant(Align, MVT::i32); - SDOperand SizeNode = DAG.getConstant(Size, MVT::i32); - SDOperand AlwaysInline = DAG.getConstant(1, MVT::i32); - - return DAG.getMemcpy(Chain, PtrOff, Arg, SizeNode, AlignNode, - AlwaysInline); + return GetMemCpyWithFlags(DAG, Flags, Arg, PtrOff, Chain); } else { return DAG.getStore(Chain, Arg, PtrOff, NULL, 0); } @@ -1306,9 +1334,9 @@ SDOperand StackPtr; - // Walk the register/memloc assignments, inserting copies/loads. - // For tail calls, lower arguments first to the stack slot where they would - // normally - in case of a normal function call - be. + // Walk the register/memloc assignments, inserting copies/loads. For tail + // calls, lower arguments which could otherwise be possibly overwritten to the + // stack slot where they would go on normal function calls. for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; SDOperand Arg = Op.getOperand(5+2*VA.getValNo()); @@ -1331,12 +1359,14 @@ if (VA.isRegLoc()) { RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); } else { - assert(VA.isMemLoc()); - if (StackPtr.Val == 0) - StackPtr = DAG.getCopyFromReg(Chain, X86StackPtr, getPointerTy()); - - MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr, VA, Chain, - Arg)); + if (!IsTailCall || IsPossiblyOverriddenArgumentOfTailCall(Arg)) { + assert(VA.isMemLoc()); + if (StackPtr.Val == 0) + StackPtr = DAG.getCopyFromReg(Chain, X86StackPtr, getPointerTy()); + + MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr, VA, Chain, + Arg)); + } } } @@ -1390,52 +1420,45 @@ InFlag = Chain.getValue(1); } - // Copy from stack slots to stack slot of a tail called function. This needs - // to be done because if we would lower the arguments directly to their real - // stack slot we might end up overwriting each other. - // TODO: To make this more efficient (sometimes saving a store/load) we could - // analyse the arguments and emit this store/load/store sequence only for - // arguments which would be overwritten otherwise. + // For tail calls lower the arguments to the 'real' stack slot. if (IsTailCall) { SmallVector<SDOperand, 8> MemOpChains2; - SDOperand PtrOff; SDOperand FIN; int FI = 0; for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { CCValAssign &VA = ArgLocs[i]; if (!VA.isRegLoc()) { + assert(VA.isMemLoc()); + SDOperand Arg = Op.getOperand(5+2*VA.getValNo()); SDOperand FlagsOp = Op.getOperand(6+2*VA.getValNo()); unsigned Flags = cast<ConstantSDNode>(FlagsOp)->getValue(); - - // Get source stack slot. - SDOperand PtrOff = DAG.getConstant(VA.getLocMemOffset(), - getPointerTy()); - PtrOff = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, PtrOff); // Create frame index. int32_t Offset = VA.getLocMemOffset()+FPDiff; uint32_t OpSize = (MVT::getSizeInBits(VA.getLocVT())+7)/8; FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset); FIN = DAG.getFrameIndex(FI, MVT::i32); - if (Flags & ISD::ParamFlags::ByVal) { - // Copy relative to framepointer. - unsigned Align = 1 << ((Flags & ISD::ParamFlags::ByValAlign) >> - ISD::ParamFlags::ByValAlignOffs); - - unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >> - ISD::ParamFlags::ByValSizeOffs; - - SDOperand AlignNode = DAG.getConstant(Align, MVT::i32); - SDOperand SizeNode = DAG.getConstant(Size, MVT::i32); - SDOperand AlwaysInline = DAG.getConstant(1, MVT::i1); + SDOperand Source = Arg; + if (IsPossiblyOverriddenArgumentOfTailCall(Arg)){ + // Copy from stack slots to stack slot of a tail called function. This + // needs to be done because if we would lower the arguments directly + // to their real stack slot we might end up overwriting each other. + // Get source stack slot. + Source = DAG.getConstant(VA.getLocMemOffset(), getPointerTy()); + if (StackPtr.Val == 0) + StackPtr = DAG.getCopyFromReg(Chain, X86StackPtr, getPointerTy()); + Source = DAG.getNode(ISD::ADD, getPointerTy(), StackPtr, Source); + if ((Flags & ISD::ParamFlags::ByVal)==0) + Source = DAG.getLoad(VA.getValVT(), Chain, Source,NULL, 0); + } - MemOpChains2.push_back(DAG.getMemcpy(Chain, FIN, PtrOff, SizeNode, - AlignNode,AlwaysInline)); + if (Flags & ISD::ParamFlags::ByVal) { + // Copy relative to framepointer. + MemOpChains2. + push_back(GetMemCpyWithFlags(DAG, Flags, Source, FIN, Chain)); } else { - SDOperand LoadedArg = DAG.getLoad(VA.getValVT(), Chain, PtrOff, - NULL, 0); - // Store relative to framepointer. - MemOpChains2.push_back(DAG.getStore(Chain, LoadedArg, FIN, NULL, 0)); - } + // Store relative to framepointer. + MemOpChains2.push_back(DAG.getStore(Chain, Source, FIN, NULL, 0)); + } } } _______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits