mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-28 14:36:34 +00:00
Spill / restore should avoid modifying the condition register.
llvm-svn: 33971
This commit is contained in:
parent
c0fcd78ca0
commit
60bde0ebb1
@ -83,7 +83,7 @@ unsigned ARMInstrInfo::isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) co
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
case ARM::tLDRspi:
|
||||
case ARM::tRestore:
|
||||
if (MI->getOperand(1).isFrameIndex() &&
|
||||
MI->getOperand(2).isImmediate() &&
|
||||
MI->getOperand(2).getImmedValue() == 0) {
|
||||
@ -117,7 +117,7 @@ unsigned ARMInstrInfo::isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) con
|
||||
return MI->getOperand(0).getReg();
|
||||
}
|
||||
break;
|
||||
case ARM::tSTRspi:
|
||||
case ARM::tSpill:
|
||||
if (MI->getOperand(1).isFrameIndex() &&
|
||||
MI->getOperand(2).isImmediate() &&
|
||||
MI->getOperand(2).getImmedValue() == 0) {
|
||||
|
@ -239,6 +239,11 @@ def tLDRspi : TIs<(ops GPR:$dst, t_addrmode_sp:$addr),
|
||||
"ldr $dst, $addr",
|
||||
[(set GPR:$dst, (load t_addrmode_sp:$addr))]>;
|
||||
|
||||
// Special instruction for restore. It cannot clobber condition register
|
||||
// when it's expanded by eliminateCallFramePseudoInstr().
|
||||
def tRestore : TIs<(ops GPR:$dst, t_addrmode_sp:$addr),
|
||||
"ldr $dst, $addr", []>;
|
||||
|
||||
// Load tconstpool
|
||||
def tLDRpci : TIs<(ops GPR:$dst, i32imm:$addr),
|
||||
"ldr $dst, $addr",
|
||||
@ -261,6 +266,11 @@ def tSTRH : TI2<(ops GPR:$src, t_addrmode_s2:$addr),
|
||||
def tSTRspi : TIs<(ops GPR:$src, t_addrmode_sp:$addr),
|
||||
"str $src, $addr",
|
||||
[(store GPR:$src, t_addrmode_sp:$addr)]>;
|
||||
|
||||
// Special instruction for spill. It cannot clobber condition register
|
||||
// when it's expanded by eliminateCallFramePseudoInstr().
|
||||
def tSpill : TIs<(ops GPR:$src, t_addrmode_sp:$addr),
|
||||
"str $src, $addr", []>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -130,7 +130,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (AFI->isThumbFunction())
|
||||
BuildMI(MBB, I, TII.get(ARM::tSTRspi)).addReg(SrcReg)
|
||||
BuildMI(MBB, I, TII.get(ARM::tSpill)).addReg(SrcReg)
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
else
|
||||
BuildMI(MBB, I, TII.get(ARM::STR)).addReg(SrcReg)
|
||||
@ -153,7 +153,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (AFI->isThumbFunction())
|
||||
BuildMI(MBB, I, TII.get(ARM::tLDRspi), DestReg)
|
||||
BuildMI(MBB, I, TII.get(ARM::tRestore), DestReg)
|
||||
.addFrameIndex(FI).addImm(0);
|
||||
else
|
||||
BuildMI(MBB, I, TII.get(ARM::LDR), DestReg)
|
||||
@ -220,16 +220,16 @@ MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr *MI,
|
||||
if (OpNum == 0) { // move -> store
|
||||
unsigned SrcReg = MI->getOperand(1).getReg();
|
||||
if (!isLowRegister(SrcReg))
|
||||
// tSTRspi cannot take a high register operand.
|
||||
// tSpill cannot take a high register operand.
|
||||
break;
|
||||
NewMI = BuildMI(TII.get(ARM::tSTRspi)).addReg(SrcReg).addFrameIndex(FI)
|
||||
NewMI = BuildMI(TII.get(ARM::tSpill)).addReg(SrcReg).addFrameIndex(FI)
|
||||
.addImm(0);
|
||||
} else { // move -> load
|
||||
unsigned DstReg = MI->getOperand(0).getReg();
|
||||
if (!isLowRegister(DstReg))
|
||||
// tLDRspi cannot target a high register operand.
|
||||
// tRestore cannot target a high register operand.
|
||||
break;
|
||||
NewMI = BuildMI(TII.get(ARM::tLDRspi), DstReg).addFrameIndex(FI)
|
||||
NewMI = BuildMI(TII.get(ARM::tRestore), DstReg).addFrameIndex(FI)
|
||||
.addImm(0);
|
||||
}
|
||||
break;
|
||||
@ -412,7 +412,7 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
if (isSub) Bytes = -NumBytes;
|
||||
bool isMul4 = (Bytes & 3) == 0;
|
||||
bool isTwoAddr = false;
|
||||
bool DstNeBase = false;
|
||||
bool DstNotEqBase = false;
|
||||
unsigned NumBits = 1;
|
||||
unsigned Scale = 1;
|
||||
int Opc = 0;
|
||||
@ -441,14 +441,14 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
// r1 = sub sp, c
|
||||
// r8 = sub sp, c
|
||||
if (DestReg != BaseReg)
|
||||
DstNeBase = true;
|
||||
DstNotEqBase = true;
|
||||
NumBits = 8;
|
||||
Opc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
||||
isTwoAddr = true;
|
||||
}
|
||||
|
||||
unsigned NumMIs = calcNumMI(Opc, ExtraOpc, Bytes, NumBits, Scale);
|
||||
unsigned Threshold = (DestReg == ARM::SP) ? 4 : 3;
|
||||
unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
|
||||
if (NumMIs > Threshold) {
|
||||
// This will expand into too many instructions. Load the immediate from a
|
||||
// constpool entry.
|
||||
@ -456,7 +456,7 @@ void emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
||||
return;
|
||||
}
|
||||
|
||||
if (DstNeBase) {
|
||||
if (DstNotEqBase) {
|
||||
if (isLowRegister(DestReg) && isLowRegister(BaseReg)) {
|
||||
// If both are low registers, emit DestReg = add BaseReg, max(Imm, 7)
|
||||
unsigned Chunk = (1 << 3) - 1;
|
||||
@ -730,27 +730,20 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
|
||||
isSub = true;
|
||||
}
|
||||
|
||||
if (!isSub || !isThumb) {
|
||||
MachineOperand &ImmOp = MI.getOperand(ImmIdx);
|
||||
int ImmedOffset = Offset / Scale;
|
||||
unsigned Mask = (1 << NumBits) - 1;
|
||||
if ((unsigned)Offset <= Mask * Scale) {
|
||||
// Replace the FrameIndex with sp
|
||||
MI.getOperand(i).ChangeToRegister(FrameReg, false);
|
||||
if (isSub)
|
||||
ImmedOffset |= 1 << NumBits;
|
||||
ImmOp.ChangeToImmediate(ImmedOffset);
|
||||
return;
|
||||
}
|
||||
MachineOperand &ImmOp = MI.getOperand(ImmIdx);
|
||||
int ImmedOffset = Offset / Scale;
|
||||
unsigned Mask = (1 << NumBits) - 1;
|
||||
if ((unsigned)Offset <= Mask * Scale) {
|
||||
// Replace the FrameIndex with sp
|
||||
MI.getOperand(i).ChangeToRegister(FrameReg, false);
|
||||
if (isSub)
|
||||
ImmedOffset |= 1 << NumBits;
|
||||
ImmOp.ChangeToImmediate(ImmedOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isThumb) {
|
||||
// Otherwise, it didn't fit. Pull in what we can to simplify the immed.
|
||||
if (AddrMode == ARMII::AddrModeTs) {
|
||||
// Thumb tLDRspi, tSTRspi. These will change to instructions that use
|
||||
// a different base register.
|
||||
NumBits = 5;
|
||||
Mask = (1 << NumBits) - 1;
|
||||
}
|
||||
|
||||
ImmedOffset = ImmedOffset & Mask;
|
||||
if (isSub)
|
||||
ImmedOffset |= 1 << NumBits;
|
||||
@ -768,8 +761,12 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
|
||||
if (TII.isLoad(Opcode)) {
|
||||
// Use the destination register to materialize sp + offset.
|
||||
unsigned TmpReg = MI.getOperand(0).getReg();
|
||||
emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
|
||||
isSub ? -Offset : Offset, TII);
|
||||
if (Opcode == ARM::tRestore)
|
||||
emitThumbRegPlusConstPool(MBB, II, TmpReg, FrameReg,
|
||||
isSub ? -Offset : Offset, TII);
|
||||
else
|
||||
emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
|
||||
isSub ? -Offset : Offset, TII);
|
||||
MI.setInstrDescriptor(TII.get(ARM::tLDR));
|
||||
MI.getOperand(i).ChangeToRegister(TmpReg, false);
|
||||
MI.addRegOperand(0, false); // tLDR has an extra register operand.
|
||||
@ -788,8 +785,12 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
|
||||
BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R2);
|
||||
TmpReg = ARM::R2;
|
||||
}
|
||||
emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
|
||||
isSub ? -Offset : Offset, TII);
|
||||
if (Opcode == ARM::tSpill)
|
||||
emitThumbRegPlusConstPool(MBB, II, TmpReg, FrameReg,
|
||||
isSub ? -Offset : Offset, TII);
|
||||
else
|
||||
emitThumbRegPlusImmediate(MBB, II, TmpReg, FrameReg,
|
||||
isSub ? -Offset : Offset, TII);
|
||||
MI.setInstrDescriptor(TII.get(ARM::tSTR));
|
||||
MI.getOperand(i).ChangeToRegister(TmpReg, false);
|
||||
MI.addRegOperand(0, false); // tSTR has an extra register operand.
|
||||
@ -1098,7 +1099,7 @@ static bool isCalleeSavedRegister(unsigned Reg, const unsigned *CSRegs) {
|
||||
static bool isCSRestore(MachineInstr *MI, const unsigned *CSRegs) {
|
||||
return ((MI->getOpcode() == ARM::FLDD ||
|
||||
MI->getOpcode() == ARM::LDR ||
|
||||
MI->getOpcode() == ARM::tLDRspi) &&
|
||||
MI->getOpcode() == ARM::tRestore) &&
|
||||
MI->getOperand(1).isFrameIndex() &&
|
||||
isCalleeSavedRegister(MI->getOperand(0).getReg(), CSRegs));
|
||||
}
|
||||
|
@ -124,3 +124,20 @@ L12:
|
||||
.align 2
|
||||
L11:
|
||||
.long 642
|
||||
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
When spilling in thumb mode and the sp offset is too large to fit in the ldr /
|
||||
str offset field, we load the offset from a constpool entry and add it to sp:
|
||||
|
||||
ldr r2, LCPI
|
||||
add r2, sp
|
||||
ldr r2, [r2]
|
||||
|
||||
These instructions preserve the condition code which is important if the spill
|
||||
is between a cmp and a bcc instruction. However, we can use the (potentially)
|
||||
cheaper sequnce if we know it's ok to clobber the condition register.
|
||||
|
||||
add r2, sp, #255 * 4
|
||||
add r2, #132
|
||||
ldr r2, [r2, #7 * 4]
|
||||
|
Loading…
Reference in New Issue
Block a user