Skip to content

Commit 47396a1

Browse files
committed
start using ByValCopyKind
1 parent 9827d27 commit 47396a1

File tree

1 file changed

+80
-7
lines changed

1 file changed

+80
-7
lines changed

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,6 +2201,74 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
22012201
unsigned NumBytesToPush = NumBytes;
22022202
unsigned NumBytesToPop = NumBytes;
22032203

2204+
SDValue StackPtr;
2205+
const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
2206+
int RetAddrSize = 8;
2207+
2208+
// If we are doing a tail-call, any byval arguments will be written to stack
2209+
// space which was used for incoming arguments. If any the values being used
2210+
// are incoming byval arguments to this function, then they might be
2211+
// overwritten by the stores of the outgoing arguments. To avoid this, we
2212+
// need to make a temporary copy of them in local stack space, then copy back
2213+
// to the argument area.
2214+
DenseMap<unsigned, SDValue> ByValTemporaries;
2215+
SDValue ByValTempChain;
2216+
if (isTailCall) {
2217+
SmallVector<SDValue, 8> ByValCopyChains;
2218+
for (const CCValAssign &VA : ArgLocs) {
2219+
unsigned ArgIdx = VA.getValNo();
2220+
SDValue Src = OutVals[ArgIdx];
2221+
ISD::ArgFlagsTy Flags = Outs[ArgIdx].Flags;
2222+
2223+
if (!Flags.isByVal())
2224+
continue;
2225+
2226+
auto PtrVT = getPointerTy(DAG.getDataLayout());
2227+
2228+
if (!StackPtr.getNode())
2229+
StackPtr =
2230+
DAG.getCopyFromReg(Chain, dl, RegInfo->getStackRegister(), PtrVT);
2231+
2232+
// Destination: where this byval should live in the callee’s frame
2233+
// after the tail call.
2234+
int32_t Offset = VA.getLocMemOffset() + FPDiff + RetAddrSize;
2235+
SDValue Dst = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr,
2236+
DAG.getIntPtrConstant(Offset, dl));
2237+
2238+
ByValCopyKind Copy = ByValNeedsCopyForTailCall(DAG, Src, Dst, Flags);
2239+
2240+
if (Copy == NoCopy) {
2241+
// If the argument is already at the correct offset on the stack
2242+
// (because we are forwarding a byval argument from our caller), we
2243+
// don't need any copying.
2244+
continue;
2245+
} else if (Copy == CopyOnce) {
2246+
// If the argument is in our local stack frame, no other argument
2247+
// preparation can clobber it, so we can copy it to the final location
2248+
// later.
2249+
ByValTemporaries[ArgIdx] = Src;
2250+
} else {
2251+
assert(Copy == CopyViaTemp && "unexpected enum value");
2252+
// If we might be copying this argument from the outgoing argument
2253+
// stack area, we need to copy via a temporary in the local stack
2254+
// frame.
2255+
MachineFrameInfo &MFI = MF.getFrameInfo();
2256+
int TempFrameIdx = MFI.CreateStackObject(Flags.getByValSize(),
2257+
Flags.getNonZeroByValAlign(),
2258+
/*isSS=*/false);
2259+
SDValue Temp =
2260+
DAG.getFrameIndex(TempFrameIdx, getPointerTy(DAG.getDataLayout()));
2261+
2262+
SDValue CopyChain =
2263+
CreateCopyOfByValArgument(Src, Temp, Chain, Flags, DAG, dl);
2264+
ByValCopyChains.push_back(CopyChain);
2265+
}
2266+
}
2267+
if (!ByValCopyChains.empty())
2268+
ByValTempChain =
2269+
DAG.getNode(ISD::TokenFactor, dl, MVT::Other, ByValCopyChains);
2270+
}
2271+
22042272
// If we have an inalloca argument, all stack space has already been allocated
22052273
// for us and be right at the top of the stack. We don't support multiple
22062274
// arguments passed in memory when using inalloca.
@@ -2241,7 +2309,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
22412309

22422310
SmallVector<std::pair<Register, SDValue>, 8> RegsToPass;
22432311
SmallVector<SDValue, 8> MemOpChains;
2244-
SDValue StackPtr;
22452312

22462313
// The next loop assumes that the locations are in the same order of the
22472314
// input arguments.
@@ -2250,7 +2317,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
22502317

22512318
// Walk the register/memloc assignments, inserting copies/loads. In the case
22522319
// of tail call optimization arguments are handle later.
2253-
const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
22542320
for (unsigned I = 0, OutIndex = 0, E = ArgLocs.size(); I != E;
22552321
++I, ++OutIndex) {
22562322
assert(OutIndex < Outs.size() && "Invalid Out index");
@@ -2459,13 +2525,20 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
24592525
FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
24602526

24612527
if (Flags.isByVal()) {
2462-
// Copy relative to framepointer.
2528+
SDValue ByValSrc;
2529+
bool NeedsStackCopy;
2530+
if (auto It = ByValTemporaries.find(OutsIndex);
2531+
It != ByValTemporaries.end()) {
2532+
ByValSrc = It->second;
2533+
NeedsStackCopy = true;
2534+
} else {
2535+
ByValSrc = Arg;
2536+
NeedsStackCopy = !isTailCall;
2537+
}
2538+
24632539
SDValue Source = DAG.getIntPtrConstant(VA.getLocMemOffset(), dl);
2464-
if (!StackPtr.getNode())
2465-
StackPtr = DAG.getCopyFromReg(Chain, dl, RegInfo->getStackRegister(),
2466-
getPointerTy(DAG.getDataLayout()));
24672540
Source = DAG.getNode(ISD::ADD, dl, getPointerTy(DAG.getDataLayout()),
2468-
StackPtr, Source);
2541+
ByValSrc, Source);
24692542

24702543
MemOpChains2.push_back(
24712544
CreateCopyOfByValArgument(Source, FIN, Chain, Flags, DAG, dl));

0 commit comments

Comments
 (0)