summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
diff options
context:
space:
mode:
authorShiva Chen <shiva0217@gmail.com>2019-10-04 02:00:57 +0000
committerShiva Chen <shiva0217@gmail.com>2019-10-04 02:00:57 +0000
commitff55e2e0476b72f456dbb37c247ae9ffef7a4f8d (patch)
tree9b3d2d8ccbefe6c9e35c18bb8d9a84dff1b4656b /llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
parentae08e479aad9dd186065160983efe7ae42e4e15c (diff)
downloadbcm5719-llvm-ff55e2e0476b72f456dbb37c247ae9ffef7a4f8d.tar.gz
bcm5719-llvm-ff55e2e0476b72f456dbb37c247ae9ffef7a4f8d.zip
[RISCV] Split SP adjustment to reduce the offset of callee saved register spill and restore
We would like to split the SP adjustment to reduce the instructions in prologue and epilogue as the following case. In this way, the offset of the callee saved register could fit in a single store. add sp,sp,-2032 sw ra,2028(sp) sw s0,2024(sp) sw s1,2020(sp) sw s3,2012(sp) sw s4,2008(sp) add sp,sp,-64 Differential Revision: https://reviews.llvm.org/D68011 llvm-svn: 373688
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVFrameLowering.cpp')
-rw-r--r--llvm/lib/Target/RISCV/RISCVFrameLowering.cpp86
1 files changed, 85 insertions, 1 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 7d48634f206..6b6f62e18ce 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -131,6 +131,11 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
if (StackSize == 0 && !MFI.adjustsStack())
return;
+ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
+ // Split the SP adjustment to reduce the offsets of callee saved spill.
+ if (FirstSPAdjustAmount)
+ StackSize = FirstSPAdjustAmount;
+
// Allocate space on the stack if necessary.
adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup);
@@ -170,7 +175,23 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
nullptr, RI->getDwarfRegNum(FPReg, true), 0));
BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
.addCFIIndex(CFIIndex);
+ }
+ // Emit the second SP adjustment after saving callee saved registers.
+ if (FirstSPAdjustAmount) {
+ uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount;
+ assert(SecondSPAdjustAmount > 0 &&
+ "SecondSPAdjustAmount should be greater than zero");
+ adjustReg(MBB, MBBI, DL, SPReg, SPReg, -SecondSPAdjustAmount,
+ MachineInstr::FrameSetup);
+ // Emit ".cfi_def_cfa_offset StackSize"
+ unsigned CFIIndex = MF.addFrameInst(
+ MCCFIInstruction::createDefCfaOffset(nullptr, -MFI.getStackSize()));
+ BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(CFIIndex);
+ }
+
+ if (hasFP(MF)) {
// Realign Stack
const RISCVRegisterInfo *RI = STI.getRegisterInfo();
if (RI->needsStackRealignment(MF)) {
@@ -224,6 +245,24 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
MachineInstr::FrameDestroy);
}
+ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
+ if (FirstSPAdjustAmount) {
+ uint64_t SecondSPAdjustAmount = MFI.getStackSize() - FirstSPAdjustAmount;
+ assert(SecondSPAdjustAmount > 0 &&
+ "SecondSPAdjustAmount should be greater than zero");
+
+ adjustReg(MBB, LastFrameDestroy, DL, SPReg, SPReg, SecondSPAdjustAmount,
+ MachineInstr::FrameDestroy);
+
+ // Emit ".cfi_def_cfa_offset FirstSPAdjustAmount"
+ unsigned CFIIndex =
+ MF.addFrameInst(
+ MCCFIInstruction::createDefCfaOffset(nullptr,
+ -FirstSPAdjustAmount));
+ BuildMI(MBB, LastFrameDestroy, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
+ .addCFIIndex(CFIIndex);
+ }
+
if (hasFP(MF)) {
// To find the instruction restoring FP from stack.
for (auto &I = LastFrameDestroy; I != MBBI; ++I) {
@@ -256,6 +295,9 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
.addCFIIndex(CFIIndex);
}
+ if (FirstSPAdjustAmount)
+ StackSize = FirstSPAdjustAmount;
+
// Deallocate stack
adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy);
@@ -284,6 +326,8 @@ int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() +
MFI.getOffsetAdjustment();
+ uint64_t FirstSPAdjustAmount = getFirstSPAdjustAmount(MF);
+
if (CSI.size()) {
MinCSFI = CSI[0].getFrameIdx();
MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
@@ -291,7 +335,11 @@ int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
if (FI >= MinCSFI && FI <= MaxCSFI) {
FrameReg = RISCV::X2;
- Offset += MF.getFrameInfo().getStackSize();
+
+ if (FirstSPAdjustAmount)
+ Offset += FirstSPAdjustAmount;
+ else
+ Offset += MF.getFrameInfo().getStackSize();
} else if (RI->needsStackRealignment(MF)) {
assert(!MFI.hasVarSizedObjects() &&
"Unexpected combination of stack realignment and varsized objects");
@@ -404,3 +452,39 @@ MachineBasicBlock::iterator RISCVFrameLowering::eliminateCallFramePseudoInstr(
return MBB.erase(MI);
}
+
+// We would like to split the SP adjustment to reduce prologue/epilogue
+// as following instructions. In this way, the offset of the callee saved
+// register could fit in a single store.
+// add sp,sp,-2032
+// sw ra,2028(sp)
+// sw s0,2024(sp)
+// sw s1,2020(sp)
+// sw s3,2012(sp)
+// sw s4,2008(sp)
+// add sp,sp,-64
+uint64_t
+RISCVFrameLowering::getFirstSPAdjustAmount(const MachineFunction &MF) const {
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+ uint64_t StackSize = MFI.getStackSize();
+ uint64_t StackAlign = getStackAlignment();
+
+ // FIXME: Disable SplitSPAdjust if save-restore libcall enabled when the patch
+ // landing. The callee saved registers will be pushed by the
+ // save-restore libcalls, so we don't have to split the SP adjustment
+ // in this case.
+ //
+ // Return the FirstSPAdjustAmount if the StackSize can not fit in signed
+ // 12-bit and there exists a callee saved register need to be pushed.
+ if (!isInt<12>(StackSize) && (CSI.size() > 0)) {
+ // FirstSPAdjustAmount is choosed as (2048 - StackAlign)
+ // because 2048 will cause sp = sp + 2048 in epilogue split into
+ // multi-instructions. The offset smaller than 2048 can fit in signle
+ // load/store instruction and we have to stick with the stack alignment.
+ // 2048 is 16-byte alignment. The stack alignment for RV32 and RV64 is 16,
+ // for RV32E is 4. So (2048 - StackAlign) will satisfy the stack alignment.
+ return 2048 - StackAlign;
+ }
+ return 0;
+}
OpenPOWER on IntegriCloud