Skip to content

Commit b5351c4

Browse files
committed
prevent copy an argument has a matching stack offset
this covers non-byval arguments that are passed via the stack because registers are full
1 parent dc1c03f commit b5351c4

File tree

1 file changed

+110
-103
lines changed

1 file changed

+110
-103
lines changed

llvm/lib/Target/X86/X86ISelLoweringCall.cpp

Lines changed: 110 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,6 +2018,103 @@ SDValue X86TargetLowering::getMOVL(SelectionDAG &DAG, const SDLoc &dl, MVT VT,
20182018
return DAG.getVectorShuffle(VT, dl, V1, V2, Mask);
20192019
}
20202020

2021+
/// Return true if the given stack call argument is already available in the
2022+
/// same position (relatively) of the caller's incoming argument stack.
2023+
static bool MatchingStackOffset(SDValue Arg, unsigned Offset,
2024+
ISD::ArgFlagsTy Flags, MachineFrameInfo &MFI,
2025+
const MachineRegisterInfo *MRI,
2026+
const X86InstrInfo *TII,
2027+
const CCValAssign &VA) {
2028+
unsigned Bytes = Arg.getValueSizeInBits() / 8;
2029+
2030+
for (;;) {
2031+
// Look through nodes that don't alter the bits of the incoming value.
2032+
unsigned Op = Arg.getOpcode();
2033+
if (Op == ISD::ZERO_EXTEND || Op == ISD::ANY_EXTEND || Op == ISD::BITCAST ||
2034+
Op == ISD::AssertZext) {
2035+
Arg = Arg.getOperand(0);
2036+
continue;
2037+
}
2038+
if (Op == ISD::TRUNCATE) {
2039+
const SDValue &TruncInput = Arg.getOperand(0);
2040+
if (TruncInput.getOpcode() == ISD::AssertZext &&
2041+
cast<VTSDNode>(TruncInput.getOperand(1))->getVT() ==
2042+
Arg.getValueType()) {
2043+
Arg = TruncInput.getOperand(0);
2044+
continue;
2045+
}
2046+
}
2047+
break;
2048+
}
2049+
2050+
int FI = INT_MAX;
2051+
if (Arg.getOpcode() == ISD::CopyFromReg) {
2052+
Register VR = cast<RegisterSDNode>(Arg.getOperand(1))->getReg();
2053+
if (!VR.isVirtual())
2054+
return false;
2055+
MachineInstr *Def = MRI->getVRegDef(VR);
2056+
if (!Def)
2057+
return false;
2058+
if (!Flags.isByVal()) {
2059+
if (!TII->isLoadFromStackSlot(*Def, FI))
2060+
return false;
2061+
} else {
2062+
unsigned Opcode = Def->getOpcode();
2063+
if ((Opcode == X86::LEA32r || Opcode == X86::LEA64r ||
2064+
Opcode == X86::LEA64_32r) &&
2065+
Def->getOperand(1).isFI()) {
2066+
FI = Def->getOperand(1).getIndex();
2067+
Bytes = Flags.getByValSize();
2068+
} else
2069+
return false;
2070+
}
2071+
} else if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Arg)) {
2072+
if (Flags.isByVal())
2073+
// ByVal argument is passed in as a pointer but it's now being
2074+
// dereferenced. e.g.
2075+
// define @foo(%struct.X* %A) {
2076+
// tail call @bar(%struct.X* byval %A)
2077+
// }
2078+
return false;
2079+
SDValue Ptr = Ld->getBasePtr();
2080+
FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(Ptr);
2081+
if (!FINode)
2082+
return false;
2083+
FI = FINode->getIndex();
2084+
} else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) {
2085+
FrameIndexSDNode *FINode = cast<FrameIndexSDNode>(Arg);
2086+
FI = FINode->getIndex();
2087+
Bytes = Flags.getByValSize();
2088+
} else
2089+
return false;
2090+
2091+
assert(FI != INT_MAX);
2092+
if (!MFI.isFixedObjectIndex(FI))
2093+
return false;
2094+
2095+
if (Offset != MFI.getObjectOffset(FI))
2096+
return false;
2097+
2098+
// If this is not byval, check that the argument stack object is immutable.
2099+
// inalloca and argument copy elision can create mutable argument stack
2100+
// objects. Byval objects can be mutated, but a byval call intends to pass the
2101+
// mutated memory.
2102+
if (!Flags.isByVal() && !MFI.isImmutableObjectIndex(FI))
2103+
return false;
2104+
2105+
if (VA.getLocVT().getFixedSizeInBits() >
2106+
Arg.getValueSizeInBits().getFixedValue()) {
2107+
// If the argument location is wider than the argument type, check that any
2108+
// extension flags match.
2109+
if (Flags.isZExt() != MFI.isObjectZExt(FI) ||
2110+
Flags.isSExt() != MFI.isObjectSExt(FI)) {
2111+
return false;
2112+
}
2113+
}
2114+
2115+
return Bytes == MFI.getObjectSize(FI);
2116+
}
2117+
20212118
// Returns the type of copying which is required to set up a byval argument to
20222119
// a tail-called function. This isn't needed for non-tail calls, because they
20232120
// always need the equivalent of CopyOnce, but tail-calls sometimes need two to
@@ -2191,7 +2288,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
21912288

21922289
SDValue StackPtr;
21932290
const X86RegisterInfo *RegInfo = Subtarget.getRegisterInfo();
2194-
int RetAddrSize = 8;
21952291

21962292
// If we are doing a tail-call, any byval arguments will be written to stack
21972293
// space which was used for incoming arguments. If any the values being used
@@ -2530,8 +2626,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
25302626
NeedsStackCopy = !isTailCall;
25312627
}
25322628

2533-
// FIXME: contrary to the arm backend, with the current logic we always
2534-
// seem to need a stack copy.
25352629
if (NeedsStackCopy) {
25362630

25372631
auto PtrVT = getPointerTy(DAG.getDataLayout());
@@ -2542,10 +2636,19 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
25422636
ByValSrc, DstAddr, Chain, Flags, DAG, dl));
25432637
}
25442638
} else {
2545-
// Store relative to framepointer.
2546-
MemOpChains2.push_back(DAG.getStore(
2547-
Chain, dl, Arg, FIN,
2548-
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));
2639+
// Check if the arguments are already laid out in the right way as
2640+
// the caller's fixed stack objects.
2641+
MachineFrameInfo &MFI = MF.getFrameInfo();
2642+
const MachineRegisterInfo *MRI = &MF.getRegInfo();
2643+
const X86InstrInfo *TII = Subtarget.getInstrInfo();
2644+
2645+
if (!MatchingStackOffset(Arg, VA.getLocMemOffset(), Flags, MFI, MRI,
2646+
TII, VA)) {
2647+
// Store relative to framepointer.
2648+
MemOpChains2.push_back(DAG.getStore(
2649+
Chain, dl, Arg, FIN,
2650+
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)));
2651+
}
25492652
}
25502653
}
25512654

@@ -2811,102 +2914,6 @@ X86TargetLowering::GetAlignedArgumentStackSize(const unsigned StackSize,
28112914
return alignTo(StackSize + SlotSize, StackAlignment) - SlotSize;
28122915
}
28132916

2814-
/// Return true if the given stack call argument is already available in the
2815-
/// same position (relatively) of the caller's incoming argument stack.
2816-
static
2817-
bool MatchingStackOffset(SDValue Arg, unsigned Offset, ISD::ArgFlagsTy Flags,
2818-
MachineFrameInfo &MFI, const MachineRegisterInfo *MRI,
2819-
const X86InstrInfo *TII, const CCValAssign &VA) {
2820-
unsigned Bytes = Arg.getValueSizeInBits() / 8;
2821-
2822-
for (;;) {
2823-
// Look through nodes that don't alter the bits of the incoming value.
2824-
unsigned Op = Arg.getOpcode();
2825-
if (Op == ISD::ZERO_EXTEND || Op == ISD::ANY_EXTEND || Op == ISD::BITCAST ||
2826-
Op == ISD::AssertZext) {
2827-
Arg = Arg.getOperand(0);
2828-
continue;
2829-
}
2830-
if (Op == ISD::TRUNCATE) {
2831-
const SDValue &TruncInput = Arg.getOperand(0);
2832-
if (TruncInput.getOpcode() == ISD::AssertZext &&
2833-
cast<VTSDNode>(TruncInput.getOperand(1))->getVT() ==
2834-
Arg.getValueType()) {
2835-
Arg = TruncInput.getOperand(0);
2836-
continue;
2837-
}
2838-
}
2839-
break;
2840-
}
2841-
2842-
int FI = INT_MAX;
2843-
if (Arg.getOpcode() == ISD::CopyFromReg) {
2844-
Register VR = cast<RegisterSDNode>(Arg.getOperand(1))->getReg();
2845-
if (!VR.isVirtual())
2846-
return false;
2847-
MachineInstr *Def = MRI->getVRegDef(VR);
2848-
if (!Def)
2849-
return false;
2850-
if (!Flags.isByVal()) {
2851-
if (!TII->isLoadFromStackSlot(*Def, FI))
2852-
return false;
2853-
} else {
2854-
unsigned Opcode = Def->getOpcode();
2855-
if ((Opcode == X86::LEA32r || Opcode == X86::LEA64r ||
2856-
Opcode == X86::LEA64_32r) &&
2857-
Def->getOperand(1).isFI()) {
2858-
FI = Def->getOperand(1).getIndex();
2859-
Bytes = Flags.getByValSize();
2860-
} else
2861-
return false;
2862-
}
2863-
} else if (LoadSDNode *Ld = dyn_cast<LoadSDNode>(Arg)) {
2864-
if (Flags.isByVal())
2865-
// ByVal argument is passed in as a pointer but it's now being
2866-
// dereferenced. e.g.
2867-
// define @foo(%struct.X* %A) {
2868-
// tail call @bar(%struct.X* byval %A)
2869-
// }
2870-
return false;
2871-
SDValue Ptr = Ld->getBasePtr();
2872-
FrameIndexSDNode *FINode = dyn_cast<FrameIndexSDNode>(Ptr);
2873-
if (!FINode)
2874-
return false;
2875-
FI = FINode->getIndex();
2876-
} else if (Arg.getOpcode() == ISD::FrameIndex && Flags.isByVal()) {
2877-
FrameIndexSDNode *FINode = cast<FrameIndexSDNode>(Arg);
2878-
FI = FINode->getIndex();
2879-
Bytes = Flags.getByValSize();
2880-
} else
2881-
return false;
2882-
2883-
assert(FI != INT_MAX);
2884-
if (!MFI.isFixedObjectIndex(FI))
2885-
return false;
2886-
2887-
if (Offset != MFI.getObjectOffset(FI))
2888-
return false;
2889-
2890-
// If this is not byval, check that the argument stack object is immutable.
2891-
// inalloca and argument copy elision can create mutable argument stack
2892-
// objects. Byval objects can be mutated, but a byval call intends to pass the
2893-
// mutated memory.
2894-
if (!Flags.isByVal() && !MFI.isImmutableObjectIndex(FI))
2895-
return false;
2896-
2897-
if (VA.getLocVT().getFixedSizeInBits() >
2898-
Arg.getValueSizeInBits().getFixedValue()) {
2899-
// If the argument location is wider than the argument type, check that any
2900-
// extension flags match.
2901-
if (Flags.isZExt() != MFI.isObjectZExt(FI) ||
2902-
Flags.isSExt() != MFI.isObjectSExt(FI)) {
2903-
return false;
2904-
}
2905-
}
2906-
2907-
return Bytes == MFI.getObjectSize(FI);
2908-
}
2909-
29102917
static bool
29112918
mayBeSRetTailCallCompatible(const TargetLowering::CallLoweringInfo &CLI,
29122919
Register CallerSRetReg) {

0 commit comments

Comments
 (0)