aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
diff options
context:
space:
mode:
authorNemanja Ivanovic <nemanja.i.ibm@gmail.com>2022-10-13 09:06:26 -0500
committerNemanja Ivanovic <nemanja.i.ibm@gmail.com>2022-10-13 09:06:37 -0500
commita77a70fa3c80518e58c68aaaf3c7159a9738f058 (patch)
treeba160da192e336965f6e0e671d7505334fb6d9aa /llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
parent4431e705ccbf25b43afd369665eb127e7f8d3ade (diff)
downloadllvm-a77a70fa3c80518e58c68aaaf3c7159a9738f058.zip
llvm-a77a70fa3c80518e58c68aaaf3c7159a9738f058.tar.gz
llvm-a77a70fa3c80518e58c68aaaf3c7159a9738f058.tar.bz2
[PowerPC] Stash GPR to VSR if emergency spill slot is not reachable
When removing frame indices on PowerPC, we need to scavenge a GPR to materialize a large constant if the stack offset for the spill/reload cannot be reached by a D-Form instruction. However, in a perfect storm of conditions, we may not have GPR's available to scavenge, thereby requiring an emergency spill. If such an emergency spill also needs to be spilled to a location with a large offset, it would itself require register scavenging thereby creating an infinite loop. This patch detects when the scavenger cannot scavenge a register and the spill/reload is to a location with a large offset. It then stashes a GPR into a VSR so that it can use the GPR to materialize the constant (rather than scavenging a GPR). Fixes: https://github.com/llvm/llvm-project/issues/52894 Differential revision: https://reviews.llvm.org/D124841
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp27
1 files changed, 25 insertions, 2 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
index d39934b..ec13079 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp
@@ -1631,9 +1631,26 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
const TargetRegisterClass *G8RC = &PPC::G8RCRegClass;
const TargetRegisterClass *GPRC = &PPC::GPRCRegClass;
const TargetRegisterClass *RC = is64Bit ? G8RC : GPRC;
- Register SRegHi = MF.getRegInfo().createVirtualRegister(RC),
- SReg = MF.getRegInfo().createVirtualRegister(RC);
unsigned NewOpcode = 0u;
+ bool ScavengingFailed = RS && RS->getRegsAvailable(RC).none() &&
+ RS->getRegsAvailable(&PPC::VSFRCRegClass).any();
+ Register SRegHi, SReg, VSReg;
+
+ // The register scavenger is unable to get a GPR but can get a VSR. We
+ // need to stash a GPR into a VSR so that we can free one up.
+ if (ScavengingFailed && Subtarget.hasDirectMove()) {
+ // Pick a volatile register and if we are spilling/restoring that
+ // particular one, pick the next one.
+ SRegHi = SReg = is64Bit ? PPC::X4 : PPC::R4;
+ if (MI.getOperand(0).getReg() == SReg)
+ SRegHi = SReg = SReg + 1;
+ VSReg = MF.getRegInfo().createVirtualRegister(&PPC::VSFRCRegClass);
+ BuildMI(MBB, II, dl, TII.get(is64Bit ? PPC::MTVSRD : PPC::MTVSRWZ), VSReg)
+ .addReg(SReg);
+ } else {
+ SRegHi = MF.getRegInfo().createVirtualRegister(RC);
+ SReg = MF.getRegInfo().createVirtualRegister(RC);
+ }
// Insert a set of rA with the full offset value before the ld, st, or add
if (isInt<16>(Offset))
@@ -1673,6 +1690,12 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
MI.getOperand(OperandBase).ChangeToRegister(StackReg, false);
MI.getOperand(OperandBase + 1).ChangeToRegister(SReg, false, false, true);
+ // If we stashed a value from a GPR into a VSR, we need to get it back after
+ // spilling the register.
+ if (ScavengingFailed && Subtarget.hasDirectMove())
+ BuildMI(MBB, ++II, dl, TII.get(is64Bit ? PPC::MFVSRD : PPC::MFVSRWZ), SReg)
+ .addReg(VSReg);
+
// Since these are not real X-Form instructions, we must
// add the registers and access 0(NewReg) rather than
// emitting the X-Form pseudo.