diff options
author | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2022-10-13 09:06:26 -0500 |
---|---|---|
committer | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2022-10-13 09:06:37 -0500 |
commit | a77a70fa3c80518e58c68aaaf3c7159a9738f058 (patch) | |
tree | ba160da192e336965f6e0e671d7505334fb6d9aa /llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp | |
parent | 4431e705ccbf25b43afd369665eb127e7f8d3ade (diff) | |
download | llvm-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.cpp | 27 |
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. |