mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-14 11:32:34 +00:00
[Sparc] Implement spill and load for long double(f128) registers.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@189768 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
195dd8a1ce
commit
6ee0857bd7
@ -44,7 +44,8 @@ unsigned SparcInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
|
||||
if (MI->getOpcode() == SP::LDri ||
|
||||
MI->getOpcode() == SP::LDXri ||
|
||||
MI->getOpcode() == SP::LDFri ||
|
||||
MI->getOpcode() == SP::LDDFri) {
|
||||
MI->getOpcode() == SP::LDDFri ||
|
||||
MI->getOpcode() == SP::LDQFri) {
|
||||
if (MI->getOperand(1).isFI() && MI->getOperand(2).isImm() &&
|
||||
MI->getOperand(2).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(1).getIndex();
|
||||
@ -64,7 +65,8 @@ unsigned SparcInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
||||
if (MI->getOpcode() == SP::STri ||
|
||||
MI->getOpcode() == SP::STXri ||
|
||||
MI->getOpcode() == SP::STFri ||
|
||||
MI->getOpcode() == SP::STDFri) {
|
||||
MI->getOpcode() == SP::STDFri ||
|
||||
MI->getOpcode() == SP::STQFri) {
|
||||
if (MI->getOperand(0).isFI() && MI->getOperand(1).isImm() &&
|
||||
MI->getOperand(1).getImm() == 0) {
|
||||
FrameIndex = MI->getOperand(0).getIndex();
|
||||
@ -273,6 +275,16 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
bool KillSrc) const {
|
||||
unsigned numSubRegs = 0;
|
||||
unsigned movOpc = 0;
|
||||
const unsigned *subRegIdx = 0;
|
||||
|
||||
const unsigned DFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };
|
||||
const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };
|
||||
const unsigned QFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd,
|
||||
SP::sub_odd64_then_sub_even,
|
||||
SP::sub_odd64_then_sub_odd };
|
||||
|
||||
if (SP::IntRegsRegClass.contains(DestReg, SrcReg))
|
||||
BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0)
|
||||
.addReg(SrcReg, getKillRegState(KillSrc));
|
||||
@ -285,23 +297,47 @@ void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
||||
.addReg(SrcReg, getKillRegState(KillSrc));
|
||||
} else {
|
||||
// Use two FMOVS instructions.
|
||||
const TargetRegisterInfo *TRI = &getRegisterInfo();
|
||||
MachineInstr *MovMI = 0;
|
||||
unsigned subRegIdx[] = {SP::sub_even, SP::sub_odd};
|
||||
for (unsigned i = 0; i != 2; ++i) {
|
||||
unsigned Dst = TRI->getSubReg(DestReg, subRegIdx[i]);
|
||||
unsigned Src = TRI->getSubReg(SrcReg, subRegIdx[i]);
|
||||
assert(Dst && Src && "Bad sub-register");
|
||||
|
||||
MovMI = BuildMI(MBB, I, DL, get(SP::FMOVS), Dst).addReg(Src);
|
||||
subRegIdx = DFP_FP_SubRegsIdx;
|
||||
numSubRegs = 2;
|
||||
movOpc = SP::FMOVS;
|
||||
}
|
||||
} else if (SP::QFPRegsRegClass.contains(DestReg, SrcReg)) {
|
||||
if (Subtarget.isV9()) {
|
||||
if (Subtarget.hasHardQuad()) {
|
||||
BuildMI(MBB, I, DL, get(SP::FMOVQ), DestReg)
|
||||
.addReg(SrcReg, getKillRegState(KillSrc));
|
||||
} else {
|
||||
// Use two FMOVD instructions.
|
||||
subRegIdx = QFP_DFP_SubRegsIdx;
|
||||
numSubRegs = 2;
|
||||
movOpc = SP::FMOVD;
|
||||
}
|
||||
// Add implicit super-register defs and kills to the last MovMI.
|
||||
MovMI->addRegisterDefined(DestReg, TRI);
|
||||
if (KillSrc)
|
||||
MovMI->addRegisterKilled(SrcReg, TRI);
|
||||
} else {
|
||||
// Use four FMOVS instructions.
|
||||
subRegIdx = QFP_FP_SubRegsIdx;
|
||||
numSubRegs = 4;
|
||||
movOpc = SP::FMOVS;
|
||||
}
|
||||
} else
|
||||
llvm_unreachable("Impossible reg-to-reg copy");
|
||||
|
||||
if (numSubRegs == 0 || subRegIdx == 0 || movOpc == 0)
|
||||
return;
|
||||
|
||||
const TargetRegisterInfo *TRI = &getRegisterInfo();
|
||||
MachineInstr *MovMI = 0;
|
||||
|
||||
for (unsigned i = 0; i != numSubRegs; ++i) {
|
||||
unsigned Dst = TRI->getSubReg(DestReg, subRegIdx[i]);
|
||||
unsigned Src = TRI->getSubReg(SrcReg, subRegIdx[i]);
|
||||
assert(Dst && Src && "Bad sub-register");
|
||||
|
||||
MovMI = BuildMI(MBB, I, DL, get(movOpc), Dst).addReg(Src);
|
||||
}
|
||||
// Add implicit super-register defs and kills to the last MovMI.
|
||||
MovMI->addRegisterDefined(DestReg, TRI);
|
||||
if (KillSrc)
|
||||
MovMI->addRegisterKilled(SrcReg, TRI);
|
||||
}
|
||||
|
||||
void SparcInstrInfo::
|
||||
@ -321,7 +357,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
MFI.getObjectAlignment(FI));
|
||||
|
||||
// On the order of operands here: think "[FrameIdx + 0] = SrcReg".
|
||||
if (RC == &SP::I64RegsRegClass)
|
||||
if (RC == &SP::I64RegsRegClass)
|
||||
BuildMI(MBB, I, DL, get(SP::STXri)).addFrameIndex(FI).addImm(0)
|
||||
.addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
|
||||
else if (RC == &SP::IntRegsRegClass)
|
||||
@ -330,9 +366,14 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
else if (RC == &SP::FPRegsRegClass)
|
||||
BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0)
|
||||
.addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
|
||||
else if (RC == &SP::DFPRegsRegClass)
|
||||
else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
|
||||
BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0)
|
||||
.addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
|
||||
else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
|
||||
// Use STQFri irrespective of its legality. If STQ is not legal, it will be
|
||||
// lowered into two STDs in eliminateFrameIndex.
|
||||
BuildMI(MBB, I, DL, get(SP::STQFri)).addFrameIndex(FI).addImm(0)
|
||||
.addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
|
||||
else
|
||||
llvm_unreachable("Can't store this register to stack slot");
|
||||
}
|
||||
@ -362,9 +403,14 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
else if (RC == &SP::FPRegsRegClass)
|
||||
BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0)
|
||||
.addMemOperand(MMO);
|
||||
else if (RC == &SP::DFPRegsRegClass)
|
||||
else if (SP::DFPRegsRegClass.hasSubClassEq(RC))
|
||||
BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0)
|
||||
.addMemOperand(MMO);
|
||||
else if (SP::QFPRegsRegClass.hasSubClassEq(RC))
|
||||
// Use LDQFri irrespective of its legality. If LDQ is not legal, it will be
|
||||
// lowered into two LDDs in eliminateFrameIndex.
|
||||
BuildMI(MBB, I, DL, get(SP::LDQFri), DestReg).addFrameIndex(FI).addImm(0)
|
||||
.addMemOperand(MMO);
|
||||
else
|
||||
llvm_unreachable("Can't load this register from stack slot");
|
||||
}
|
||||
|
@ -87,6 +87,35 @@ SparcRegisterInfo::getPointerRegClass(const MachineFunction &MF,
|
||||
return Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;
|
||||
}
|
||||
|
||||
static void replaceFI(MachineFunction &MF,
|
||||
MachineBasicBlock::iterator II,
|
||||
MachineInstr &MI,
|
||||
DebugLoc dl,
|
||||
unsigned FIOperandNum, int Offset,
|
||||
unsigned FramePtr)
|
||||
{
|
||||
// Replace frame index with a frame pointer reference.
|
||||
if (Offset >= -4096 && Offset <= 4095) {
|
||||
// If the offset is small enough to fit in the immediate field, directly
|
||||
// encode it.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
|
||||
} else {
|
||||
// Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to
|
||||
// scavenge a register here instead of reserving G1 all of the time.
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
unsigned OffHi = (unsigned)Offset >> 10U;
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
|
||||
// Emit G1 = G1 + I6
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
|
||||
.addReg(FramePtr);
|
||||
// Insert: G1+%lo(offset) into the user.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
int SPAdj, unsigned FIOperandNum,
|
||||
@ -111,25 +140,37 @@ SparcRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
||||
Offset += (stackSize) ? Subtarget.getAdjustedFrameSize(stackSize) : 0 ;
|
||||
}
|
||||
|
||||
// Replace frame index with a frame pointer reference.
|
||||
if (Offset >= -4096 && Offset <= 4095) {
|
||||
// If the offset is small enough to fit in the immediate field, directly
|
||||
// encode it.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(FramePtr, false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset);
|
||||
} else {
|
||||
// Otherwise, emit a G1 = SETHI %hi(offset). FIXME: it would be better to
|
||||
// scavenge a register here instead of reserving G1 all of the time.
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
unsigned OffHi = (unsigned)Offset >> 10U;
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(SP::SETHIi), SP::G1).addImm(OffHi);
|
||||
// Emit G1 = G1 + I6
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(SP::ADDrr), SP::G1).addReg(SP::G1)
|
||||
.addReg(FramePtr);
|
||||
// Insert: G1+%lo(offset) into the user.
|
||||
MI.getOperand(FIOperandNum).ChangeToRegister(SP::G1, false);
|
||||
MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset & ((1 << 10)-1));
|
||||
if (!Subtarget.isV9() || !Subtarget.hasHardQuad()) {
|
||||
if (MI.getOpcode() == SP::STQFri) {
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
unsigned SrcReg = MI.getOperand(2).getReg();
|
||||
unsigned SrcEvenReg = getSubReg(SrcReg, SP::sub_even64);
|
||||
unsigned SrcOddReg = getSubReg(SrcReg, SP::sub_odd64);
|
||||
MachineInstr *StMI =
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(SP::STDFri))
|
||||
.addReg(FramePtr).addImm(0).addReg(SrcEvenReg);
|
||||
replaceFI(MF, II, *StMI, dl, 0, Offset, FramePtr);
|
||||
MI.setDesc(TII.get(SP::STDFri));
|
||||
MI.getOperand(2).setReg(SrcOddReg);
|
||||
Offset += 8;
|
||||
} else if (MI.getOpcode() == SP::LDQFri) {
|
||||
const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo();
|
||||
unsigned DestReg = MI.getOperand(0).getReg();
|
||||
unsigned DestEvenReg = getSubReg(DestReg, SP::sub_even64);
|
||||
unsigned DestOddReg = getSubReg(DestReg, SP::sub_odd64);
|
||||
MachineInstr *StMI =
|
||||
BuildMI(*MI.getParent(), II, dl, TII.get(SP::LDDFri), DestEvenReg)
|
||||
.addReg(FramePtr).addImm(0);
|
||||
replaceFI(MF, II, *StMI, dl, 1, Offset, FramePtr);
|
||||
|
||||
MI.setDesc(TII.get(SP::LDDFri));
|
||||
MI.getOperand(0).setReg(DestOddReg);
|
||||
Offset += 8;
|
||||
}
|
||||
}
|
||||
|
||||
replaceFI(MF, II, MI, dl, FIOperandNum, Offset, FramePtr);
|
||||
|
||||
}
|
||||
|
||||
unsigned SparcRegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
||||
|
@ -25,3 +25,18 @@ entry:
|
||||
store fp128 %7, fp128* %scalar.result, align 8
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: f128_spill
|
||||
; CHECK: std %f{{.+}}, [%[[S0:.+]]]
|
||||
; CHECK: std %f{{.+}}, [%[[S1:.+]]]
|
||||
; CHECK-DAG: ldd [%[[S0]]], %f{{.+}}
|
||||
; CHECK-DAG: ldd [%[[S1]]], %f{{.+}}
|
||||
; CHECK: jmp
|
||||
|
||||
define void @f128_spill(fp128* noalias sret %scalar.result, fp128* byval %a) {
|
||||
entry:
|
||||
%0 = load fp128* %a, align 8
|
||||
call void asm sideeffect "", "~{f0},~{f1},~{f2},~{f3},~{f4},~{f5},~{f6},~{f7},~{f8},~{f9},~{f10},~{f11},~{f12},~{f13},~{f14},~{f15},~{f16},~{f17},~{f18},~{f19},~{f20},~{f21},~{f22},~{f23},~{f24},~{f25},~{f26},~{f27},~{f28},~{f29},~{f30},~{f31}"()
|
||||
store fp128 %0, fp128* %scalar.result, align 8
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user