Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp
Show First 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | void LoongArchFrameLowering::determineFrameLayout(MachineFunction &MF) const { | ||||
// Update frame info. | // Update frame info. | ||||
MFI.setStackSize(FrameSize); | MFI.setStackSize(FrameSize); | ||||
} | } | ||||
void LoongArchFrameLowering::emitPrologue(MachineFunction &MF, | void LoongArchFrameLowering::emitPrologue(MachineFunction &MF, | ||||
MachineBasicBlock &MBB) const { | MachineBasicBlock &MBB) const { | ||||
MachineFrameInfo &MFI = MF.getFrameInfo(); | MachineFrameInfo &MFI = MF.getFrameInfo(); | ||||
auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>(); | |||||
const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); | const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); | ||||
const LoongArchInstrInfo *TII = STI.getInstrInfo(); | const LoongArchInstrInfo *TII = STI.getInstrInfo(); | ||||
MachineBasicBlock::iterator MBBI = MBB.begin(); | MachineBasicBlock::iterator MBBI = MBB.begin(); | ||||
Register SPReg = LoongArch::R3; | Register SPReg = LoongArch::R3; | ||||
Register FPReg = LoongArch::R22; | Register FPReg = LoongArch::R22; | ||||
// Debug location must be unknown since the first debug location is used | // Debug location must be unknown since the first debug location is used | ||||
Show All 35 Lines | unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::createOffset( | ||||
nullptr, RI->getDwarfRegNum(Entry.getReg(), true), Offset)); | nullptr, RI->getDwarfRegNum(Entry.getReg(), true), Offset)); | ||||
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) | ||||
.addCFIIndex(CFIIndex) | .addCFIIndex(CFIIndex) | ||||
.setMIFlag(MachineInstr::FrameSetup); | .setMIFlag(MachineInstr::FrameSetup); | ||||
} | } | ||||
// Generate new FP. | // Generate new FP. | ||||
if (hasFP(MF)) { | if (hasFP(MF)) { | ||||
adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); | adjustReg(MBB, MBBI, DL, FPReg, SPReg, | ||||
StackSize - LoongArchFI->getVarArgsSaveSize(), | |||||
// Emit ".cfi_def_cfa $fp, 0" | MachineInstr::FrameSetup); | ||||
unsigned CFIIndex = MF.addFrameInst(MCCFIInstruction::cfiDefCfa( | |||||
nullptr, RI->getDwarfRegNum(FPReg, true), 0)); | // Emit ".cfi_def_cfa $fp, LoongArchFI->getVarArgsSaveSize()" | ||||
unsigned CFIIndex = MF.addFrameInst( | |||||
MCCFIInstruction::cfiDefCfa(nullptr, RI->getDwarfRegNum(FPReg, true), | |||||
LoongArchFI->getVarArgsSaveSize())); | |||||
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) | BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) | ||||
.addCFIIndex(CFIIndex) | .addCFIIndex(CFIIndex) | ||||
.setMIFlag(MachineInstr::FrameSetup); | .setMIFlag(MachineInstr::FrameSetup); | ||||
} | } | ||||
} | } | ||||
void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF, | void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF, | ||||
MachineBasicBlock &MBB) const { | MachineBasicBlock &MBB) const { | ||||
const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); | const LoongArchRegisterInfo *RI = STI.getRegisterInfo(); | ||||
MachineFrameInfo &MFI = MF.getFrameInfo(); | MachineFrameInfo &MFI = MF.getFrameInfo(); | ||||
auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>(); | |||||
Register SPReg = LoongArch::R3; | Register SPReg = LoongArch::R3; | ||||
MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); | MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); | ||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); | DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); | ||||
const auto &CSI = MFI.getCalleeSavedInfo(); | const auto &CSI = MFI.getCalleeSavedInfo(); | ||||
// Skip to before the restores of callee-saved registers. | // Skip to before the restores of callee-saved registers. | ||||
auto LastFrameDestroy = MBBI; | auto LastFrameDestroy = MBBI; | ||||
if (!CSI.empty()) | if (!CSI.empty()) | ||||
LastFrameDestroy = std::prev(MBBI, CSI.size()); | LastFrameDestroy = std::prev(MBBI, CSI.size()); | ||||
// Get the number of bytes from FrameInfo. | // Get the number of bytes from FrameInfo. | ||||
uint64_t StackSize = MFI.getStackSize(); | uint64_t StackSize = MFI.getStackSize(); | ||||
// Restore the stack pointer. | // Restore the stack pointer. | ||||
if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects()) { | if (RI->hasStackRealignment(MF) || MFI.hasVarSizedObjects()) { | ||||
assert(hasFP(MF) && "frame pointer should not have been eliminated"); | assert(hasFP(MF) && "frame pointer should not have been eliminated"); | ||||
adjustReg(MBB, LastFrameDestroy, DL, SPReg, LoongArch::R22, -StackSize, | adjustReg(MBB, LastFrameDestroy, DL, SPReg, LoongArch::R22, | ||||
-StackSize + LoongArchFI->getVarArgsSaveSize(), | |||||
MachineInstr::FrameDestroy); | MachineInstr::FrameDestroy); | ||||
} | } | ||||
// Deallocate stack | // Deallocate stack | ||||
adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); | adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); | ||||
} | } | ||||
void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF, | void LoongArchFrameLowering::determineCalleeSaves(MachineFunction &MF, | ||||
BitVector &SavedRegs, | BitVector &SavedRegs, | ||||
RegScavenger *RS) const { | RegScavenger *RS) const { | ||||
TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); | TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); | ||||
// Unconditionally spill RA and FP only if the function uses a frame | // Unconditionally spill RA and FP only if the function uses a frame | ||||
// pointer. | // pointer. | ||||
if (hasFP(MF)) { | if (hasFP(MF)) { | ||||
SavedRegs.set(LoongArch::R1); | SavedRegs.set(LoongArch::R1); | ||||
SavedRegs.set(LoongArch::R22); | SavedRegs.set(LoongArch::R22); | ||||
} | } | ||||
// Mark BP as used if function has dedicated base pointer. | // Mark BP as used if function has dedicated base pointer. | ||||
if (hasBP(MF)) | if (hasBP(MF)) | ||||
SavedRegs.set(LoongArchABI::getBPReg()); | SavedRegs.set(LoongArchABI::getBPReg()); | ||||
} | } | ||||
// Do not preserve stack space within prologue for outgoing variables if the | |||||
xen0n: nit: "Do not ... if ..." | |||||
Not Done ReplyInline Actions"Do not" ;-) xen0n: "Do not" ;-) | |||||
Forgive me for my carelessness. Thanks. wangleiat: Forgive me for my carelessness. Thanks. | |||||
// function contains variable size objects. | |||||
// Let eliminateCallFramePseudoInstr preserve stack space for it. | |||||
bool LoongArchFrameLowering::hasReservedCallFrame( | |||||
const MachineFunction &MF) const { | |||||
return !MF.getFrameInfo().hasVarSizedObjects(); | |||||
} | |||||
// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions. | |||||
MachineBasicBlock::iterator | |||||
LoongArchFrameLowering::eliminateCallFramePseudoInstr( | |||||
MachineFunction &MF, MachineBasicBlock &MBB, | |||||
MachineBasicBlock::iterator MI) const { | |||||
Register SPReg = LoongArch::R3; | |||||
DebugLoc DL = MI->getDebugLoc(); | |||||
if (!hasReservedCallFrame(MF)) { | |||||
// If space has not been reserved for a call frame, ADJCALLSTACKDOWN and | |||||
// ADJCALLSTACKUP must be converted to instructions manipulating the stack | |||||
// pointer. This is necessary when there is a variable length stack | |||||
// allocation (e.g. alloca), which means it's not possible to allocate | |||||
// space for outgoing arguments from within the function prologue. | |||||
int64_t Amount = MI->getOperand(0).getImm(); | |||||
if (Amount != 0) { | |||||
// Ensure the stack remains aligned after adjustment. | |||||
Amount = alignSPAdjust(Amount); | |||||
if (MI->getOpcode() == LoongArch::ADJCALLSTACKDOWN) | |||||
Amount = -Amount; | |||||
adjustReg(MBB, MI, DL, SPReg, SPReg, Amount, MachineInstr::NoFlags); | |||||
} | |||||
} | |||||
return MBB.erase(MI); | |||||
} | |||||
StackOffset LoongArchFrameLowering::getFrameIndexReference( | StackOffset LoongArchFrameLowering::getFrameIndexReference( | ||||
const MachineFunction &MF, int FI, Register &FrameReg) const { | const MachineFunction &MF, int FI, Register &FrameReg) const { | ||||
const MachineFrameInfo &MFI = MF.getFrameInfo(); | const MachineFrameInfo &MFI = MF.getFrameInfo(); | ||||
const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); | const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); | ||||
auto *LoongArchFI = MF.getInfo<LoongArchMachineFunctionInfo>(); | |||||
// Callee-saved registers should be referenced relative to the stack | // Callee-saved registers should be referenced relative to the stack | ||||
// pointer (positive offset), otherwise use the frame pointer (negative | // pointer (positive offset), otherwise use the frame pointer (negative | ||||
// offset). | // offset). | ||||
const auto &CSI = MFI.getCalleeSavedInfo(); | const auto &CSI = MFI.getCalleeSavedInfo(); | ||||
int MinCSFI = 0; | int MinCSFI = 0; | ||||
int MaxCSFI = -1; | int MaxCSFI = -1; | ||||
StackOffset Offset = | StackOffset Offset = | ||||
StackOffset::getFixed(MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + | StackOffset::getFixed(MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + | ||||
MFI.getOffsetAdjustment()); | MFI.getOffsetAdjustment()); | ||||
if (CSI.size()) { | if (CSI.size()) { | ||||
MinCSFI = CSI[0].getFrameIdx(); | MinCSFI = CSI[0].getFrameIdx(); | ||||
MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); | MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); | ||||
} | } | ||||
FrameReg = RI->getFrameRegister(MF); | |||||
if ((FI >= MinCSFI && FI <= MaxCSFI) || !hasFP(MF)) { | if ((FI >= MinCSFI && FI <= MaxCSFI) || !hasFP(MF)) { | ||||
FrameReg = LoongArch::R3; | FrameReg = LoongArch::R3; | ||||
Offset += StackOffset::getFixed(MFI.getStackSize()); | Offset += StackOffset::getFixed(MFI.getStackSize()); | ||||
} else { | |||||
FrameReg = RI->getFrameRegister(MF); | |||||
Offset += StackOffset::getFixed(LoongArchFI->getVarArgsSaveSize()); | |||||
} | } | ||||
return Offset; | return Offset; | ||||
} | } |
nit: "Do not ... if ..."