mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-18 14:31:27 +00:00
Add support for spilling VRSAVE on PPC
Although there is only one Altivec VRSAVE register, it is a member of a register class, and we need the ability to spill it. Because this register is normally callee-preserved and handled by special code this has never before been necessary. However, this capability will be required by a forthcoming commit adding SjLj support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177654 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e9cc0a09ae
commit
10f7f2a222
@ -539,6 +539,12 @@ PPCInstrInfo::StoreRegToStackSlot(MachineFunction &MF,
|
||||
getKillRegState(isKill)),
|
||||
FrameIdx));
|
||||
NonRI = true;
|
||||
} else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) {
|
||||
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::SPILL_VRSAVE))
|
||||
.addReg(SrcReg,
|
||||
getKillRegState(isKill)),
|
||||
FrameIdx));
|
||||
NonRI = true;
|
||||
} else {
|
||||
llvm_unreachable("Unknown regclass!");
|
||||
}
|
||||
@ -647,6 +653,12 @@ PPCInstrInfo::LoadRegFromStackSlot(MachineFunction &MF, DebugLoc DL,
|
||||
NewMIs.push_back(addFrameReference(BuildMI(MF, DL, get(PPC::LVX), DestReg),
|
||||
FrameIdx));
|
||||
NonRI = true;
|
||||
} else if (PPC::VRSAVERCRegClass.hasSubClassEq(RC)) {
|
||||
NewMIs.push_back(addFrameReference(BuildMI(MF, DL,
|
||||
get(PPC::RESTORE_VRSAVE),
|
||||
DestReg),
|
||||
FrameIdx));
|
||||
NonRI = true;
|
||||
} else {
|
||||
llvm_unreachable("Unknown regclass!");
|
||||
}
|
||||
|
@ -1237,6 +1237,29 @@ def MFVRSAVE : XFXForm_1_ext<31, 339, 256, (outs GPRC:$rT), (ins),
|
||||
"mfspr $rT, 256", IntGeneral>,
|
||||
PPC970_DGroup_First, PPC970_Unit_FXU;
|
||||
|
||||
let isCodeGenOnly = 1 in {
|
||||
def MTVRSAVEv : XFXForm_7_ext<31, 467, 256,
|
||||
(outs VRSAVERC:$reg), (ins GPRC:$rS),
|
||||
"mtspr 256, $rS", IntGeneral>,
|
||||
PPC970_DGroup_Single, PPC970_Unit_FXU;
|
||||
def MFVRSAVEv : XFXForm_1_ext<31, 339, 256, (outs GPRC:$rT),
|
||||
(ins VRSAVERC:$reg),
|
||||
"mfspr $rT, 256", IntGeneral>,
|
||||
PPC970_DGroup_First, PPC970_Unit_FXU;
|
||||
}
|
||||
|
||||
// SPILL_VRSAVE - Indicate that we're dumping the VRSAVE register,
|
||||
// so we'll need to scavenge a register for it.
|
||||
let mayStore = 1 in
|
||||
def SPILL_VRSAVE : Pseudo<(outs), (ins VRSAVERC:$vrsave, memri:$F),
|
||||
"#SPILL_VRSAVE", []>;
|
||||
|
||||
// RESTORE_VRSAVE - Indicate that we're restoring the VRSAVE register (previously
|
||||
// spilled), so we'll need to scavenge a register for it.
|
||||
let mayLoad = 1 in
|
||||
def RESTORE_VRSAVE : Pseudo<(outs VRSAVERC:$vrsave), (ins memri:$F),
|
||||
"#RESTORE_VRSAVE", []>;
|
||||
|
||||
def MTCRF : XFXForm_5<31, 144, (outs crbitm:$FXM), (ins GPRC:$rS),
|
||||
"mtcrf $FXM, $rS", BrMCRX>,
|
||||
PPC970_MicroCode, PPC970_Unit_CRU;
|
||||
|
@ -369,6 +369,65 @@ void PPCRegisterInfo::lowerCRRestore(MachineBasicBlock::iterator II,
|
||||
MBB.erase(II);
|
||||
}
|
||||
|
||||
void PPCRegisterInfo::lowerVRSAVESpilling(MachineBasicBlock::iterator II,
|
||||
unsigned FrameIndex, int SPAdj,
|
||||
RegScavenger *RS) const {
|
||||
// Get the instruction.
|
||||
MachineInstr &MI = *II; // ; SPILL_VRSAVE <SrcReg>, <offset>
|
||||
// Get the instruction's basic block.
|
||||
MachineBasicBlock &MBB = *MI.getParent();
|
||||
DebugLoc dl = MI.getDebugLoc();
|
||||
|
||||
// FIXME: Once LLVM supports creating virtual registers here, or the register
|
||||
// scavenger can return multiple registers, stop using reserved registers
|
||||
// here.
|
||||
(void) SPAdj;
|
||||
(void) RS;
|
||||
|
||||
unsigned Reg = PPC::R0;
|
||||
unsigned SrcReg = MI.getOperand(0).getReg();
|
||||
|
||||
BuildMI(MBB, II, dl, TII.get(PPC::MFVRSAVEv), Reg)
|
||||
.addReg(SrcReg, getKillRegState(MI.getOperand(0).isKill()));
|
||||
|
||||
addFrameReference(BuildMI(MBB, II, dl, TII.get(PPC::STW))
|
||||
.addReg(Reg, getKillRegState(MI.getOperand(1).getImm())),
|
||||
FrameIndex);
|
||||
|
||||
// Discard the pseudo instruction.
|
||||
MBB.erase(II);
|
||||
}
|
||||
|
||||
void PPCRegisterInfo::lowerVRSAVERestore(MachineBasicBlock::iterator II,
|
||||
unsigned FrameIndex, int SPAdj,
|
||||
RegScavenger *RS) const {
|
||||
// Get the instruction.
|
||||
MachineInstr &MI = *II; // ; <DestReg> = RESTORE_VRSAVE <offset>
|
||||
// Get the instruction's basic block.
|
||||
MachineBasicBlock &MBB = *MI.getParent();
|
||||
DebugLoc dl = MI.getDebugLoc();
|
||||
|
||||
// FIXME: Once LLVM supports creating virtual registers here, or the register
|
||||
// scavenger can return multiple registers, stop using reserved registers
|
||||
// here.
|
||||
(void) SPAdj;
|
||||
(void) RS;
|
||||
|
||||
unsigned Reg = PPC::R0;
|
||||
unsigned DestReg = MI.getOperand(0).getReg();
|
||||
assert(MI.definesRegister(DestReg) &&
|
||||
"RESTORE_VRSAVE does not define its destination");
|
||||
|
||||
addFrameReference(BuildMI(MBB, II, dl, TII.get(PPC::LWZ),
|
||||
Reg), FrameIndex);
|
||||
|
||||
BuildMI(MBB, II, dl, TII.get(PPC::MTVRSAVEv), DestReg)
|
||||
.addReg(Reg);
|
||||
|
||||
// Discard the pseudo instruction.
|
||||
MBB.erase(II);
|
||||
}
|
||||
|
||||
bool
|
||||
PPCRegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
|
||||
unsigned Reg, int &FrameIdx) const {
|
||||
@ -429,13 +488,19 @@ PPCRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
return;
|
||||
}
|
||||
|
||||
// Special case for pseudo-ops SPILL_CR and RESTORE_CR.
|
||||
// Special case for pseudo-ops SPILL_CR and RESTORE_CR, etc.
|
||||
if (OpC == PPC::SPILL_CR) {
|
||||
lowerCRSpilling(II, FrameIndex, SPAdj, RS);
|
||||
return;
|
||||
} else if (OpC == PPC::RESTORE_CR) {
|
||||
lowerCRRestore(II, FrameIndex, SPAdj, RS);
|
||||
return;
|
||||
} else if (OpC == PPC::SPILL_VRSAVE) {
|
||||
lowerVRSAVESpilling(II, FrameIndex, SPAdj, RS);
|
||||
return;
|
||||
} else if (OpC == PPC::RESTORE_VRSAVE) {
|
||||
lowerVRSAVERestore(II, FrameIndex, SPAdj, RS);
|
||||
return;
|
||||
}
|
||||
|
||||
// Replace the FrameIndex with base register with GPR1 (SP) or GPR31 (FP).
|
||||
|
@ -66,6 +66,11 @@ public:
|
||||
int SPAdj, RegScavenger *RS) const;
|
||||
void lowerCRRestore(MachineBasicBlock::iterator II, unsigned FrameIndex,
|
||||
int SPAdj, RegScavenger *RS) const;
|
||||
void lowerVRSAVESpilling(MachineBasicBlock::iterator II, unsigned FrameIndex,
|
||||
int SPAdj, RegScavenger *RS) const;
|
||||
void lowerVRSAVERestore(MachineBasicBlock::iterator II, unsigned FrameIndex,
|
||||
int SPAdj, RegScavenger *RS) const;
|
||||
|
||||
bool hasReservedSpillSlot(const MachineFunction &MF, unsigned Reg,
|
||||
int &FrameIdx) const;
|
||||
void eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
|
18
test/CodeGen/PowerPC/vrsave-spill.ll
Normal file
18
test/CodeGen/PowerPC/vrsave-spill.ll
Normal file
@ -0,0 +1,18 @@
|
||||
; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=g5 | FileCheck %s
|
||||
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
|
||||
target triple = "powerpc64-unknown-linux-gnu"
|
||||
|
||||
define <4 x float> @foo(<4 x float> %a, <4 x float> %b) nounwind {
|
||||
entry:
|
||||
%c = fadd <4 x float> %a, %b
|
||||
call void asm sideeffect "", "~{VRsave}"() nounwind
|
||||
br label %return
|
||||
|
||||
; CHECK: @foo
|
||||
; CHECK: mfspr {{[0-9]+}}, 256
|
||||
; CHECK: mtspr 256, {{[0-9]+}}
|
||||
|
||||
return: ; preds = %entry
|
||||
ret <4 x float> %c
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user