Skip to content

Commit 9a9b649

Browse files
phoebewangrnk
authored andcommitted
[WinEH] Allocate space in funclets stack to save XMM CSRs
Summary: This is an alternate approach to D63396 Currently funclets reuse the same stack slots that are used in the parent function for saving callee-saved xmm registers. If the parent function modifies a callee-saved xmm register before an excpetion is thrown, the catch handler will overwrite the original saved value. This patch allocates space in funclets stack for saving callee-saved xmm registers and uses RSP instead RBP to access memory. Signed-off-by: Pengfei Wang <pengfei.wang@intel.com> Reviewers: rnk, RKSimon, craig.topper, annita.zhang, LuoYuanke, andrew.w.kaylor Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66596 Signed-off-by: Pengfei Wang <pengfei.wang@intel.com> llvm-svn: 370005 (cherry picked from commit 564fb58)
1 parent 2d75b24 commit 9a9b649

File tree

8 files changed

+366
-177
lines changed

8 files changed

+366
-177
lines changed

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,9 +1396,13 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
13961396
int FI;
13971397
if (unsigned Reg = TII.isStoreToStackSlot(FrameInstr, FI)) {
13981398
if (X86::FR64RegClass.contains(Reg)) {
1399+
int Offset;
13991400
unsigned IgnoredFrameReg;
1400-
int Offset = getFrameIndexReference(MF, FI, IgnoredFrameReg);
1401-
Offset += SEHFrameOffset;
1401+
if (IsWin64Prologue && IsFunclet)
1402+
Offset = getWin64EHFrameIndexRef(MF, FI, IgnoredFrameReg);
1403+
else
1404+
Offset = getFrameIndexReference(MF, FI, IgnoredFrameReg) +
1405+
SEHFrameOffset;
14021406

14031407
HasWinCFI = true;
14041408
assert(!NeedsWinFPO && "SEH_SaveXMM incompatible with FPO data");
@@ -1554,9 +1558,13 @@ X86FrameLowering::getPSPSlotOffsetFromSP(const MachineFunction &MF) const {
15541558

15551559
unsigned
15561560
X86FrameLowering::getWinEHFuncletFrameSize(const MachineFunction &MF) const {
1561+
const X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
15571562
// This is the size of the pushed CSRs.
1558-
unsigned CSSize =
1559-
MF.getInfo<X86MachineFunctionInfo>()->getCalleeSavedFrameSize();
1563+
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
1564+
// This is the size of callee saved XMMs.
1565+
const auto& WinEHXMMSlotInfo = X86FI->getWinEHXMMSlotInfo();
1566+
unsigned XMMSize = WinEHXMMSlotInfo.size() *
1567+
TRI->getSpillSize(X86::VR128RegClass);
15601568
// This is the amount of stack a funclet needs to allocate.
15611569
unsigned UsedSize;
15621570
EHPersonality Personality =
@@ -1576,7 +1584,7 @@ X86FrameLowering::getWinEHFuncletFrameSize(const MachineFunction &MF) const {
15761584
unsigned FrameSizeMinusRBP = alignTo(CSSize + UsedSize, getStackAlignment());
15771585
// Subtract out the size of the callee saved registers. This is how much stack
15781586
// each funclet will allocate.
1579-
return FrameSizeMinusRBP - CSSize;
1587+
return FrameSizeMinusRBP + XMMSize - CSSize;
15801588
}
15811589

15821590
static bool isTailCallOpcode(unsigned Opc) {
@@ -1850,6 +1858,20 @@ int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
18501858
return Offset + FPDelta;
18511859
}
18521860

1861+
int X86FrameLowering::getWin64EHFrameIndexRef(const MachineFunction &MF,
1862+
int FI, unsigned &FrameReg) const {
1863+
const MachineFrameInfo &MFI = MF.getFrameInfo();
1864+
const X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
1865+
const auto& WinEHXMMSlotInfo = X86FI->getWinEHXMMSlotInfo();
1866+
const auto it = WinEHXMMSlotInfo.find(FI);
1867+
1868+
if (it == WinEHXMMSlotInfo.end())
1869+
return getFrameIndexReference(MF, FI, FrameReg);
1870+
1871+
FrameReg = TRI->getStackRegister();
1872+
return alignTo(MFI.getMaxCallFrameSize(), getStackAlignment()) + it->second;
1873+
}
1874+
18531875
int X86FrameLowering::getFrameIndexReferenceSP(const MachineFunction &MF,
18541876
int FI, unsigned &FrameReg,
18551877
int Adjustment) const {
@@ -1948,6 +1970,8 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots(
19481970
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
19491971

19501972
unsigned CalleeSavedFrameSize = 0;
1973+
unsigned XMMCalleeSavedFrameSize = 0;
1974+
auto &WinEHXMMSlotInfo = X86FI->getWinEHXMMSlotInfo();
19511975
int SpillSlotOffset = getOffsetOfLocalArea() + X86FI->getTCReturnAddrDelta();
19521976

19531977
int64_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta();
@@ -2025,12 +2049,20 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots(
20252049
unsigned Size = TRI->getSpillSize(*RC);
20262050
unsigned Align = TRI->getSpillAlignment(*RC);
20272051
// ensure alignment
2028-
SpillSlotOffset -= std::abs(SpillSlotOffset) % Align;
2052+
assert(SpillSlotOffset < 0 && "SpillSlotOffset should always < 0 on X86");
2053+
SpillSlotOffset = -alignTo(-SpillSlotOffset, Align);
2054+
20292055
// spill into slot
20302056
SpillSlotOffset -= Size;
20312057
int SlotIndex = MFI.CreateFixedSpillStackObject(Size, SpillSlotOffset);
20322058
CSI[i - 1].setFrameIdx(SlotIndex);
20332059
MFI.ensureMaxAlignment(Align);
2060+
2061+
// Save the start offset and size of XMM in stack frame for funclets.
2062+
if (X86::VR128RegClass.contains(Reg)) {
2063+
WinEHXMMSlotInfo[SlotIndex] = XMMCalleeSavedFrameSize;
2064+
XMMCalleeSavedFrameSize += Size;
2065+
}
20342066
}
20352067

20362068
return true;

llvm/lib/Target/X86/X86FrameLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class X86FrameLowering : public TargetFrameLowering {
9999
int getFrameIndexReference(const MachineFunction &MF, int FI,
100100
unsigned &FrameReg) const override;
101101

102+
int getWin64EHFrameIndexRef(const MachineFunction &MF,
103+
int FI, unsigned &SPReg) const;
102104
int getFrameIndexReferenceSP(const MachineFunction &MF,
103105
int FI, unsigned &SPReg, int Adjustment) const;
104106
int getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI,

llvm/lib/Target/X86/X86MachineFunctionInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
3636
/// is stashed.
3737
signed char RestoreBasePointerOffset = 0;
3838

39+
/// WinEHXMMSlotInfo - Slot information of XMM registers in the stack frame
40+
/// in bytes.
41+
DenseMap<int, unsigned> WinEHXMMSlotInfo;
42+
3943
/// CalleeSavedFrameSize - Size of the callee-saved register portion of the
4044
/// stack frame in bytes.
4145
unsigned CalleeSavedFrameSize = 0;
@@ -120,6 +124,10 @@ class X86MachineFunctionInfo : public MachineFunctionInfo {
120124
void setRestoreBasePointer(const MachineFunction *MF);
121125
int getRestoreBasePointerOffset() const {return RestoreBasePointerOffset; }
122126

127+
DenseMap<int, unsigned>& getWinEHXMMSlotInfo() { return WinEHXMMSlotInfo; }
128+
const DenseMap<int, unsigned>& getWinEHXMMSlotInfo() const {
129+
return WinEHXMMSlotInfo; }
130+
123131
unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
124132
void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; }
125133

llvm/lib/Target/X86/X86RegisterInfo.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -692,12 +692,27 @@ static bool tryOptimizeLEAtoMOV(MachineBasicBlock::iterator II) {
692692
return true;
693693
}
694694

695+
static bool isFuncletReturnInstr(MachineInstr &MI) {
696+
switch (MI.getOpcode()) {
697+
case X86::CATCHRET:
698+
case X86::CLEANUPRET:
699+
return true;
700+
default:
701+
return false;
702+
}
703+
llvm_unreachable("impossible");
704+
}
705+
695706
void
696707
X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
697708
int SPAdj, unsigned FIOperandNum,
698709
RegScavenger *RS) const {
699710
MachineInstr &MI = *II;
700-
MachineFunction &MF = *MI.getParent()->getParent();
711+
MachineBasicBlock &MBB = *MI.getParent();
712+
MachineFunction &MF = *MBB.getParent();
713+
MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator();
714+
bool IsEHFuncletEpilogue = MBBI == MBB.end() ? false
715+
: isFuncletReturnInstr(*MBBI);
701716
const X86FrameLowering *TFI = getFrameLowering(MF);
702717
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
703718

@@ -709,6 +724,8 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
709724
MF.getFrameInfo().isFixedObjectIndex(FrameIndex)) &&
710725
"Return instruction can only reference SP relative frame objects");
711726
FIOffset = TFI->getFrameIndexReferenceSP(MF, FrameIndex, BasePtr, 0);
727+
} else if (TFI->Is64Bit && (MBB.isEHFuncletEntry() || IsEHFuncletEpilogue)) {
728+
FIOffset = TFI->getWin64EHFrameIndexRef(MF, FrameIndex, BasePtr);
712729
} else {
713730
FIOffset = TFI->getFrameIndexReference(MF, FrameIndex, BasePtr);
714731
}

0 commit comments

Comments
 (0)