-
Notifications
You must be signed in to change notification settings - Fork 14.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 1 commit
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 | ||
---|---|---|---|---|
|
@@ -33,10 +33,158 @@ 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(); | ||||
const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>( | ||||
MF.getSubtarget().getRegisterInfo()); | ||||
const XtensaInstrInfo &TII = | ||||
arsenm marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
*static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo()); | ||||
MachineBasicBlock::iterator MBBI = MBB.begin(); | ||||
DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); | ||||
unsigned SP = Xtensa::SP; | ||||
arsenm marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
unsigned FP = RegInfo->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()) { | ||||
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. !CSI.empty() 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. fixed |
||||
// 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(); | ||||
const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>( | ||||
arsenm marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
MF.getSubtarget().getRegisterInfo()); | ||||
const XtensaInstrInfo &TII = | ||||
*static_cast<const XtensaInstrInfo *>(MF.getSubtarget().getInstrInfo()); | ||||
DebugLoc DL = MBBI->getDebugLoc(); | ||||
unsigned SP = Xtensa::SP; | ||||
unsigned FP = RegInfo->getFrameRegister(MF); | ||||
|
||||
// if framepointer enabled, restore the stack pointer. | ||||
if (hasFP(MF)) { | ||||
// Find the first instruction that restores a callee-saved register. | ||||
MachineBasicBlock::iterator I = MBBI; | ||||
|
||||
for (unsigned i = 0; i < MFI.getCalleeSavedInfo().size(); ++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. I don't see how incrementing the instruction iteration based on this makes sense 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. Thank you very much for review. I've made some code improvements (added more comments and loop is changed), I hope that I understand correctly your comment. Actually I used the same approach as in Mips architecture
|
||||
--I; | ||||
|
||||
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()); | ||||
const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); | ||||
|
||||
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( | ||||
|
@@ -57,3 +205,31 @@ MachineBasicBlock::iterator XtensaFrameLowering::eliminateCallFramePseudoInstr( | |||
|
||||
return MBB.erase(I); | ||||
} | ||||
|
||||
void XtensaFrameLowering::determineCalleeSaves(MachineFunction &MF, | ||||
BitVector &SavedRegs, | ||||
RegScavenger *RS) const { | ||||
MachineFrameInfo &MFI = MF.getFrameInfo(); | ||||
const XtensaRegisterInfo *RegInfo = static_cast<const XtensaRegisterInfo *>( | ||||
arsenm marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
MF.getSubtarget().getRegisterInfo()); | ||||
unsigned FP = RegInfo->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; | ||||
const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); | ||||
arsenm marked this conversation as resolved.
Show resolved
Hide resolved
|
||||
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 |
||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
; RUN: llc -mtriple=xtensa -disable-block-placement -verify-machineinstrs < %s \ | ||
; RUN: | FileCheck %s | ||
|
||
define ptr @test_simple_alloca(i32 %numelts) { | ||
; CHECK-LABEL: test_simple_alloca | ||
; CHECK: addi a8, a1, -16 | ||
; CHECK: or a1, a8, a8 | ||
; CHECK: s32i a15, a1, 0 | ||
; CHECK: or a15, a1, a1 | ||
; CHECK: addi a8, a2, 3 | ||
; CHECK-NEXT: movi a9, -4 | ||
; CHECK-NEXT: and a8, a8, a9 | ||
; CHECK-NEXT: addi a8, a8, 31 | ||
; CHECK-NEXT: movi a9, -32 | ||
; CHECK-NEXT: and a8, a8, a9 | ||
; CHECK-NEXT: sub a1, a1, a8 | ||
; CHECK-NEXT: or a2, a1, a1 | ||
; CHECK-NEXT: or a1, a15, a15 | ||
; CHECK-NEXT: l32i a15, a1, 0 | ||
; CHECK-NEXT: addi a8, a1, 16 | ||
; CHECK-NEXT: or a1, a8, a8 | ||
; CHECK-NEXT: ret | ||
|
||
%addr = alloca i8, i32 %numelts | ||
ret ptr %addr | ||
} |
Uh oh!
There was an error while loading. Please reload this page.