[llvm-commits] [llvm] r47593 - in /llvm/trunk/lib/Target/X86: X86ISelLowering.cpp X86ISelLowering.h
Tanya Lattner
lattner at apple.com
Tue Feb 26 09:24:16 PST 2008
Please use doxygen style comments for functions (///)
-Tanya
On Feb 26, 2008, at 1:20 AM, Arnold Schwaighofer wrote:
> Author: arnolds
> Date: Tue Feb 26 03:19:59 2008
> New Revision: 47593
>
> URL: http://llvm.org/viewvc/llvm-project?rev=47593&view=rev
> Log:
> Change the lowering of arguments for tail call optimized
> calls. Before arguments that could overwrite each other were
> explicitly lowered to a stack slot, not giving the register allocator
> a chance to optimize. Now a sequence of copyto/copyfrom virtual
> registers ensures that arguments are loaded in (virtual) registers
> before they are lowered to the stack slot (and might overwrite each
> other). Also parameter stack slots are marked mutable for
> (potentially) tail calling functions.
>
> Modified:
> llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> llvm/trunk/lib/Target/X86/X86ISelLowering.h
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/
> X86ISelLowering.cpp?rev=47593&r1=47592&r2=47593&view=diff
>
> ======================================================================
> ========
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Tue Feb 26
> 03:19:59 2008
> @@ -1057,26 +1057,55 @@
> return None;
> }
>
> -
> // IsPossiblyOverwrittenArgumentOfTailCall - Check if the operand
> could possibly
> // be overwritten 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 overwritten 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 IsPossiblyOverwrittenArgumentOfTailCall(SDOperand Op) {
> +static bool IsPossiblyOverwrittenArgumentOfTailCall(SDOperand Op,
> +
> MachineFrameInfo * MFI) {
> RegisterSDNode * OpReg = NULL;
> + FrameIndexSDNode * FrameIdxNode = NULL;
> + int FrameIdx = 0;
> if (Op.getOpcode() == ISD::FORMAL_ARGUMENTS ||
> (Op.getOpcode()== ISD::CopyFromReg &&
> - (OpReg = cast<RegisterSDNode>(Op.getOperand(1))) &&
> - OpReg->getReg() >= TargetRegisterInfo::FirstVirtualRegister))
> + (OpReg = dyn_cast<RegisterSDNode>(Op.getOperand(1))) &&
> + (OpReg->getReg() >=
> TargetRegisterInfo::FirstVirtualRegister)) ||
> + (Op.getOpcode() == ISD::LOAD &&
> + (FrameIdxNode = dyn_cast<FrameIndexSDNode>(Op.getOperand
> (1))) &&
> + (MFI->isFixedObjectIndex((FrameIdx = FrameIdxNode->getIndex
> ()))) &&
> + (MFI->getObjectOffset(FrameIdx) >= 0)))
> return true;
> return false;
> }
>
> +// CopyTailCallClobberedArgumentsToVRegs - Create virtual
> registers for all
> +// arguments to force loading and guarantee that arguments
> sourcing from
> +// incomming parameters are not overwriting each other.
> +static SDOperand
> +CopyTailCallClobberedArgumentsToVRegs(SDOperand Chain,
> + SmallVector<std::pair<unsigned, SDOperand>, 8>
> &TailCallClobberedVRegs,
> + SelectionDAG &DAG,
> + MachineFunction &MF,
> + const TargetLowering * TL) {
> +
> + SDOperand InFlag;
> + for (unsigned i = 0, e = TailCallClobberedVRegs.size(); i != e; i
> ++) {
> + SDOperand Arg = TailCallClobberedVRegs[i].second;
> + unsigned Idx = TailCallClobberedVRegs[i].first;
> + unsigned VReg =
> + MF.getRegInfo().
> + createVirtualRegister(TL->getRegClassFor(Arg.getValueType()));
> + Chain = DAG.getCopyToReg(Chain, VReg, Arg, InFlag);
> + InFlag = Chain.getValue(1);
> + Arg = DAG.getCopyFromReg(Chain, VReg, Arg.getValueType(),
> InFlag);
> + TailCallClobberedVRegs[i] = std::make_pair(Idx, Arg);
> + Chain = Arg.getValue(1);
> + InFlag = Arg.getValue(2);
> + }
> + return Chain;
> +}
> +
> // CreateCopyOfByValArgument - Make a copy of an aggregate at
> address specified
> // by "Src" to address "Dst" with size and alignment information
> specified by
> // the specific parameter attribute. The copy will be passed as a
> byval function
> @@ -1097,15 +1126,20 @@
> SDOperand X86TargetLowering::LowerMemArgument(SDOperand Op,
> SelectionDAG &DAG,
> const CCValAssign &VA,
> MachineFrameInfo *MFI,
> + unsigned CC,
> SDOperand Root,
> unsigned i) {
> // Create the nodes corresponding to a load from this parameter
> slot.
> unsigned Flags = cast<ConstantSDNode>(Op.getOperand(3 + i))-
> >getValue();
> + bool AlwaysUseMutable = (CC==CallingConv::Fast) &&
> PerformTailCallOpt;
> bool isByVal = Flags & ISD::ParamFlags::ByVal;
> + bool isImmutable = !AlwaysUseMutable && !isByVal;
>
> - // FIXME: For now, all byval parameter objects are marked
> mutable. This
> - // can be changed with more analysis.
> + // FIXME: For now, all byval parameter objects are marked
> mutable. This can be
> + // changed with more analysis.
> + // In case of tail call optimization mark all arguments mutable.
> Since they
> + // could be overwritten by lowering of arguments in case of a
> tail call.
> int FI = MFI->CreateFixedObject(MVT::getSizeInBits(VA.getValVT
> ())/8,
> - VA.getLocMemOffset(), !isByVal);
> + VA.getLocMemOffset(), isImmutable);
> SDOperand FIN = DAG.getFrameIndex(FI, getPointerTy());
> if (isByVal)
> return FIN;
> @@ -1195,7 +1229,7 @@
> ArgValues.push_back(ArgValue);
> } else {
> assert(VA.isMemLoc());
> - ArgValues.push_back(LowerMemArgument(Op, DAG, VA, MFI, Root,
> i));
> + ArgValues.push_back(LowerMemArgument(Op, DAG, VA, MFI, CC,
> Root, i));
> }
> }
>
> @@ -1381,6 +1415,7 @@
>
> SDOperand X86TargetLowering::LowerCALL(SDOperand Op, SelectionDAG
> &DAG) {
> MachineFunction &MF = DAG.getMachineFunction();
> + MachineFrameInfo * MFI = MF.getFrameInfo();
> SDOperand Chain = Op.getOperand(0);
> unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))-
> >getValue();
> bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))-
> >getValue() != 0;
> @@ -1442,7 +1477,7 @@
>
> Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant
> (NumBytes));
>
> - SDOperand RetAddrFrIdx, NewRetAddrFrIdx;
> + SDOperand RetAddrFrIdx;
> if (IsTailCall) {
> // Adjust the Return address stack slot.
> if (FPDiff) {
> @@ -1451,23 +1486,18 @@
> // Load the "old" Return address.
> RetAddrFrIdx =
> DAG.getLoad(VT, Chain,RetAddrFrIdx, NULL, 0);
> - // Calculate the new stack slot for the return address.
> - int SlotSize = Is64Bit ? 8 : 4;
> - int NewReturnAddrFI =
> - MF.getFrameInfo()->CreateFixedObject(SlotSize, FPDiff-
> SlotSize);
> - NewRetAddrFrIdx = DAG.getFrameIndex(NewReturnAddrFI, VT);
> Chain = SDOperand(RetAddrFrIdx.Val, 1);
> }
> }
>
> SmallVector<std::pair<unsigned, SDOperand>, 8> RegsToPass;
> + SmallVector<std::pair<unsigned, SDOperand>, 8>
> TailCallClobberedVRegs;
> SmallVector<SDOperand, 8> MemOpChains;
>
> SDOperand StackPtr;
>
> // 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.
> + // calls, remember all arguments for later special lowering.
> for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
> CCValAssign &VA = ArgLocs[i];
> SDOperand Arg = Op.getOperand(5+2*VA.getValNo());
> @@ -1490,13 +1520,15 @@
> if (VA.isRegLoc()) {
> RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
> } else {
> - if (!IsTailCall || IsPossiblyOverwrittenArgumentOfTailCall
> (Arg)) {
> + if (!IsTailCall) {
> assert(VA.isMemLoc());
> if (StackPtr.Val == 0)
> StackPtr = DAG.getCopyFromReg(Chain, X86StackPtr,
> getPointerTy());
>
> MemOpChains.push_back(LowerMemOpCallTo(Op, DAG, StackPtr,
> VA, Chain,
> Arg));
> + } else if (IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) {
> + TailCallClobberedVRegs.push_back(std::make_pair(i,Arg));
> }
> }
> }
> @@ -1514,9 +1546,6 @@
> InFlag = Chain.getValue(1);
> }
>
> - if (IsTailCall)
> - InFlag = SDOperand(); // ??? Isn't this nuking the preceding
> loop's output?
> -
> // ELF / PIC requires GOT in the EBX register before function
> calls via PLT
> // GOT pointer.
> // Does not work with tail call since ebx is not restored
> correctly by
> @@ -1551,11 +1580,18 @@
> InFlag = Chain.getValue(1);
> }
>
> +
> // For tail calls lower the arguments to the 'real' stack slot.
> if (IsTailCall) {
> SmallVector<SDOperand, 8> MemOpChains2;
> SDOperand FIN;
> int FI = 0;
> + // Do not flag preceeding copytoreg stuff together with the
> following stuff.
> + InFlag = SDOperand();
> +
> + Chain = CopyTailCallClobberedArgumentsToVRegs(Chain,
> TailCallClobberedVRegs,
> + DAG, MF, this);
> +
> for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
> CCValAssign &VA = ArgLocs[i];
> if (!VA.isRegLoc()) {
> @@ -1568,28 +1604,26 @@
> uint32_t OpSize = (MVT::getSizeInBits(VA.getLocVT())+7)/8;
> FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset);
> FIN = DAG.getFrameIndex(FI, MVT::i32);
> - SDOperand Source = Arg;
> - if (IsPossiblyOverwrittenArgumentOfTailCall(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.getIntPtrConstant(VA.getLocMemOffset());
> - 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);
> - }
>
> + // Find virtual register for this argument.
> + bool Found=false;
> + for (unsigned idx=0, e= TailCallClobberedVRegs.size(); idx
> < e; idx++)
> + if (TailCallClobberedVRegs[idx].first==i) {
> + Arg = TailCallClobberedVRegs[idx].second;
> + Found=true;
> + break;
> + }
> + assert(IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)
> ==false ||
> + (Found==true && "No corresponding Argument was found"));
> +
> if (Flags & ISD::ParamFlags::ByVal) {
> // Copy relative to framepointer.
> - MemOpChains2.push_back(CreateCopyOfByValArgument(Source,
> FIN, Chain,
> + MemOpChains2.push_back(CreateCopyOfByValArgument(Arg,
> FIN, Chain,
> Flags,
> DAG));
> } else {
> // Store relative to framepointer.
> MemOpChains2.push_back(
> - DAG.getStore(Chain, Source, FIN,
> + DAG.getStore(Chain, Arg, FIN,
> PseudoSourceValue::getFixedStack(), FI));
> }
> }
> @@ -1600,8 +1634,16 @@
> &MemOpChains2[0], MemOpChains2.size());
>
> // Store the return address to the appropriate stack slot.
> - if (FPDiff)
> - Chain = DAG.getStore(Chain,RetAddrFrIdx, NewRetAddrFrIdx,
> NULL, 0);
> + if (FPDiff) {
> + // Calculate the new stack slot for the return address.
> + int SlotSize = Is64Bit ? 8 : 4;
> + int NewReturnAddrFI =
> + MF.getFrameInfo()->CreateFixedObject(SlotSize, FPDiff-
> SlotSize);
> + MVT::ValueType VT = Is64Bit ? MVT::i64 : MVT::i32;
> + SDOperand NewRetAddrFrIdx = DAG.getFrameIndex
> (NewReturnAddrFI, VT);
> + Chain = DAG.getStore(Chain, RetAddrFrIdx, NewRetAddrFrIdx,
> + PseudoSourceValue::getFixedStack(),
> NewReturnAddrFI);
> + }
> }
>
> // If the callee is a GlobalAddress node (quite common, every
> direct call is)
>
> Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/
> X86ISelLowering.h?rev=47593&r1=47592&r2=47593&view=diff
>
> ======================================================================
> ========
> --- llvm/trunk/lib/Target/X86/X86ISelLowering.h (original)
> +++ llvm/trunk/lib/Target/X86/X86ISelLowering.h Tue Feb 26 03:19:59
> 2008
> @@ -482,7 +482,7 @@
>
> SDOperand LowerMemArgument(SDOperand Op, SelectionDAG &DAG,
> const CCValAssign &VA,
> MachineFrameInfo *MFI,
> - SDOperand Root, unsigned i);
> + unsigned CC, SDOperand Root,
> unsigned i);
>
> SDOperand LowerMemOpCallTo(SDOperand Op, SelectionDAG &DAG,
> const SDOperand &StackPtr,
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list