Skip to content

Commit 0d471b3

Browse files
authored
Spill/restore FP/BP around instructions in which they are clobbered (#81048)
This patch fixes #17204. If a base pointer is used in a function, and it is clobbered by an instruction (typically an inline asm), current register allocator can't handle this situation, so BP becomes garbage after those instructions. It can also occur to FP in theory. We can spill and reload FP/BP registers around those instructions. But normal spill/reload instructions also use FP/BP, so we can't spill them into normal spill slots, instead we spill them into the top of stack by using SP register.
1 parent ce2a3d9 commit 0d471b3

17 files changed

+783
-6
lines changed

llvm/include/llvm/CodeGen/TargetFrameLowering.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,10 @@ class TargetFrameLowering {
475475
/// debug info.
476476
virtual DwarfFrameBase getDwarfFrameBase(const MachineFunction &MF) const;
477477

478+
/// If frame pointer or base pointer is clobbered by an instruction, we should
479+
/// spill/restore it around that instruction.
480+
virtual void spillFPBP(MachineFunction &MF) const {}
481+
478482
/// This method is called at the end of prolog/epilog code insertion, so
479483
/// targets can emit remarks based on the final frame layout.
480484
virtual void emitRemarks(const MachineFunction &MF,

llvm/lib/CodeGen/CFIInstrInserter.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "llvm/CodeGen/TargetInstrInfo.h"
2626
#include "llvm/CodeGen/TargetSubtargetInfo.h"
2727
#include "llvm/InitializePasses.h"
28+
#include "llvm/MC/MCContext.h"
2829
#include "llvm/MC/MCDwarf.h"
2930
using namespace llvm;
3031

@@ -184,6 +185,10 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
184185
unsigned NumRegs = TRI.getNumSupportedRegs(*MF);
185186
BitVector CSRSaved(NumRegs), CSRRestored(NumRegs);
186187

188+
#ifndef NDEBUG
189+
int RememberState = 0;
190+
#endif
191+
187192
// Determine cfa offset and register set by the block.
188193
for (MachineInstr &MI : *MBBInfo.MBB) {
189194
if (MI.isCFIInstruction()) {
@@ -228,17 +233,25 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
228233
case MCCFIInstruction::OpRememberState:
229234
// TODO: Add support for handling cfi_remember_state.
230235
#ifndef NDEBUG
231-
report_fatal_error(
232-
"Support for cfi_remember_state not implemented! Value of CFA "
233-
"may be incorrect!\n");
236+
// Currently we need cfi_remember_state and cfi_restore_state to be in
237+
// the same BB, so it will not impact outgoing CFA.
238+
++RememberState;
239+
if (RememberState != 1)
240+
MF->getContext().reportError(
241+
SMLoc(),
242+
"Support for cfi_remember_state not implemented! Value of CFA "
243+
"may be incorrect!\n");
234244
#endif
235245
break;
236246
case MCCFIInstruction::OpRestoreState:
237247
// TODO: Add support for handling cfi_restore_state.
238248
#ifndef NDEBUG
239-
report_fatal_error(
240-
"Support for cfi_restore_state not implemented! Value of CFA may "
241-
"be incorrect!\n");
249+
--RememberState;
250+
if (RememberState != 0)
251+
MF->getContext().reportError(
252+
SMLoc(),
253+
"Support for cfi_restore_state not implemented! Value of CFA may "
254+
"be incorrect!\n");
242255
#endif
243256
break;
244257
// Other CFI directives do not affect CFA value.
@@ -264,6 +277,14 @@ void CFIInstrInserter::calculateOutgoingCFAInfo(MBBCFAInfo &MBBInfo) {
264277
}
265278
}
266279

280+
#ifndef NDEBUG
281+
if (RememberState != 0)
282+
MF->getContext().reportError(
283+
SMLoc(),
284+
"Support for cfi_remember_state not implemented! Value of CFA may be "
285+
"incorrect!\n");
286+
#endif
287+
267288
MBBInfo.Processed = true;
268289

269290
// Update outgoing CFA info.

llvm/lib/CodeGen/PrologEpilogInserter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,11 @@ bool PEI::runOnMachineFunction(MachineFunction &MF) {
228228
FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(MF);
229229
ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
230230

231+
// Spill frame pointer and/or base pointer registers if they are clobbered.
232+
// It is placed before call frame instruction elimination so it will not mess
233+
// with stack arguments.
234+
TFI->spillFPBP(MF);
235+
231236
// Calculate the MaxCallFrameSize value for the function's frame
232237
// information. Also eliminates call frame pseudo instructions.
233238
calculateCallFrameInfo(MF);

0 commit comments

Comments
 (0)