-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[PATCH] [Xtensa] Implement FrameLowering methods and stack operation lowering. #92960
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
78c9f32
c84f7f1
cfe1305
7df895e
039f075
7a15a99
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,9 +22,10 @@ | |
|
||
using namespace llvm; | ||
|
||
XtensaFrameLowering::XtensaFrameLowering() | ||
XtensaFrameLowering::XtensaFrameLowering(const XtensaSubtarget &STI) | ||
: TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(4), 0, | ||
Align(4)) {} | ||
Align(4)), | ||
STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {} | ||
|
||
bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const { | ||
const MachineFrameInfo &MFI = MF.getFrameInfo(); | ||
|
@@ -33,10 +34,153 @@ bool XtensaFrameLowering::hasFP(const MachineFunction &MF) const { | |
} | ||
|
||
void XtensaFrameLowering::emitPrologue(MachineFunction &MF, | ||
MachineBasicBlock &MBB) const {} | ||
MachineBasicBlock &MBB) const { | ||
assert(&MBB == &MF.front() && "Shrink-wrapping not yet implemented"); | ||
MachineFrameInfo &MFI = MF.getFrameInfo(); | ||
MachineBasicBlock::iterator MBBI = MBB.begin(); | ||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); | ||
MCRegister SP = Xtensa::SP; | ||
MCRegister FP = TRI->getFrameRegister(MF); | ||
MachineModuleInfo &MMI = MF.getMMI(); | ||
const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); | ||
|
||
// First, compute final stack size. | ||
uint64_t StackSize = MFI.getStackSize(); | ||
uint64_t PrevStackSize = StackSize; | ||
|
||
// Round up StackSize to 16*N | ||
StackSize += (16 - StackSize) & 0xf; | ||
|
||
// No need to allocate space on the stack. | ||
if (StackSize == 0 && !MFI.adjustsStack()) | ||
return; | ||
|
||
// Adjust stack. | ||
TII.adjustStackPtr(SP, -StackSize, MBB, MBBI); | ||
|
||
// emit ".cfi_def_cfa_offset StackSize" | ||
unsigned CFIIndex = | ||
MF.addFrameInst(MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize)); | ||
BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
.addCFIIndex(CFIIndex); | ||
|
||
const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); | ||
|
||
if (CSI.size()) { | ||
// Find the instruction past the last instruction that saves a | ||
// callee-saved register to the stack. | ||
for (unsigned i = 0; i < CSI.size(); ++i) | ||
++MBBI; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a dubious way to guarantee this. Can you at least assert each instruction is a spill of the appropriate register? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added check functions for store/restore instructions, PTAL. |
||
|
||
// Iterate over list of callee-saved registers and emit .cfi_offset | ||
// directives. | ||
for (const auto &I : CSI) { | ||
int64_t Offset = MFI.getObjectOffset(I.getFrameIdx()); | ||
Register Reg = I.getReg(); | ||
|
||
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( | ||
nullptr, MRI->getDwarfRegNum(Reg, 1), Offset)); | ||
BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
.addCFIIndex(CFIIndex); | ||
} | ||
} | ||
|
||
// if framepointer enabled, set it to point to the stack pointer. | ||
if (hasFP(MF)) { | ||
// Insert instruction "move $fp, $sp" at this location. | ||
BuildMI(MBB, MBBI, DL, TII.get(Xtensa::OR), FP) | ||
.addReg(SP) | ||
.addReg(SP) | ||
.setMIFlag(MachineInstr::FrameSetup); | ||
|
||
// emit ".cfi_def_cfa_register $fp" | ||
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createDefCfaRegister( | ||
nullptr, MRI->getDwarfRegNum(FP, true))); | ||
BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) | ||
.addCFIIndex(CFIIndex); | ||
} | ||
|
||
if (StackSize != PrevStackSize) { | ||
MFI.setStackSize(StackSize); | ||
|
||
for (int i = MFI.getObjectIndexBegin(); i < MFI.getObjectIndexEnd(); i++) { | ||
if (!MFI.isDeadObjectIndex(i)) { | ||
int64_t SPOffset = MFI.getObjectOffset(i); | ||
|
||
if (SPOffset < 0) | ||
MFI.setObjectOffset(i, SPOffset - StackSize + PrevStackSize); | ||
} | ||
} | ||
} | ||
} | ||
|
||
void XtensaFrameLowering::emitEpilogue(MachineFunction &MF, | ||
MachineBasicBlock &MBB) const {} | ||
MachineBasicBlock &MBB) const { | ||
MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); | ||
MachineFrameInfo &MFI = MF.getFrameInfo(); | ||
DebugLoc DL = MBBI->getDebugLoc(); | ||
MCRegister SP = Xtensa::SP; | ||
MCRegister FP = TRI->getFrameRegister(MF); | ||
|
||
// if framepointer enabled, restore the stack pointer. | ||
if (hasFP(MF)) { | ||
// We should place restore stack pointer instruction just before | ||
// sequence of instructions which restores callee-saved registers. | ||
// This sequence is placed at the end of the basic block, | ||
// so we should find first instruction of the sequence. | ||
MachineBasicBlock::iterator I = MBBI; | ||
|
||
// Find the first instruction at the end that restores a callee-saved | ||
// register. | ||
for (auto &Info : MFI.getCalleeSavedInfo()) | ||
--I; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, can this at least assert the instructions are the expected ones? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added check functions |
||
|
||
BuildMI(MBB, I, DL, TII.get(Xtensa::OR), SP).addReg(FP).addReg(FP); | ||
} | ||
|
||
// Get the number of bytes from FrameInfo | ||
uint64_t StackSize = MFI.getStackSize(); | ||
|
||
if (!StackSize) | ||
return; | ||
|
||
// Adjust stack. | ||
TII.adjustStackPtr(SP, StackSize, MBB, MBBI); | ||
} | ||
|
||
bool XtensaFrameLowering::spillCalleeSavedRegisters( | ||
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, | ||
ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { | ||
MachineFunction *MF = MBB.getParent(); | ||
MachineBasicBlock &EntryBlock = *(MF->begin()); | ||
|
||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) { | ||
// Add the callee-saved register as live-in. Do not add if the register is | ||
// A0 and return address is taken, because it will be implemented in | ||
// method XtensaTargetLowering::LowerRETURNADDR. | ||
// It's killed at the spill, unless the register is RA and return address | ||
// is taken. | ||
Register Reg = CSI[i].getReg(); | ||
bool IsA0AndRetAddrIsTaken = | ||
(Reg == Xtensa::A0) && MF->getFrameInfo().isReturnAddressTaken(); | ||
if (!IsA0AndRetAddrIsTaken) | ||
EntryBlock.addLiveIn(Reg); | ||
|
||
// Insert the spill to the stack frame. | ||
bool IsKill = !IsA0AndRetAddrIsTaken; | ||
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); | ||
TII.storeRegToStackSlot(EntryBlock, MI, Reg, IsKill, CSI[i].getFrameIdx(), | ||
RC, TRI, Register()); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool XtensaFrameLowering::restoreCalleeSavedRegisters( | ||
MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, | ||
MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { | ||
return TargetFrameLowering::restoreCalleeSavedRegisters(MBB, MI, CSI, TRI); | ||
} | ||
|
||
// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions | ||
MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr( | ||
|
@@ -51,9 +195,34 @@ MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr( | |
if (I->getOpcode() == Xtensa::ADJCALLSTACKDOWN) | ||
Amount = -Amount; | ||
|
||
unsigned SP = Xtensa::SP; | ||
TII.adjustStackPtr(SP, Amount, MBB, I); | ||
TII.adjustStackPtr(Xtensa::SP, Amount, MBB, I); | ||
} | ||
|
||
return MBB.erase(I); | ||
} | ||
|
||
void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF, | ||
BitVector &SavedRegs, | ||
RegScavenger *RS) const { | ||
MachineFrameInfo &MFI = MF.getFrameInfo(); | ||
unsigned FP = TRI->getFrameRegister(MF); | ||
|
||
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); | ||
|
||
// Mark $fp as used if function has dedicated frame pointer. | ||
if (hasFP(MF)) | ||
SavedRegs.set(FP); | ||
|
||
// Set scavenging frame index if necessary. | ||
uint64_t MaxSPOffset = MFI.estimateStackSize(MF); | ||
|
||
if (isInt<12>(MaxSPOffset)) | ||
return; | ||
|
||
const TargetRegisterClass &RC = Xtensa::ARRegClass; | ||
unsigned Size = TRI->getSpillSize(RC); | ||
Align Alignment = TRI->getSpillAlign(RC); | ||
int FI = MF.getFrameInfo().CreateStackObject(Size, Alignment, false); | ||
|
||
RS->addScavengingFrameIndex(FI); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure it's safe to do this in determineCalleeSaves. Can you create the emergency scavenging index in processFunctionBeforeFrameFinalized instead? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved frame index scavenging to processFunctionBeforeFrameFinalized |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!CSI.empty()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed