From 8e59ea998f1357768aa43cb00187e6c1c1a1cc7e Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 7 Feb 2007 00:06:56 +0000 Subject: [PATCH] Spill / restore should avoid modifying the condition register. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33971 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrInfo.cpp | 4 +- lib/Target/ARM/ARMInstrThumb.td | 10 +++++ lib/Target/ARM/ARMRegisterInfo.cpp | 69 +++++++++++++++--------------- lib/Target/ARM/README-Thumb.txt | 17 ++++++++ 4 files changed, 64 insertions(+), 36 deletions(-) diff --git a/lib/Target/ARM/ARMInstrInfo.cpp b/lib/Target/ARM/ARMInstrInfo.cpp index 6adf645e493..36ed76d9616 100644 --- a/lib/Target/ARM/ARMInstrInfo.cpp +++ b/lib/Target/ARM/ARMInstrInfo.cpp @@ -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) { diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index b0e531cdc84..59a0098f44d 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -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", []>; } //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index 90fc84ffe5b..2eb9eeac2bf 100644 --- a/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -130,7 +130,7 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, MachineFunction &MF = *MBB.getParent(); ARMFunctionInfo *AFI = MF.getInfo(); 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(); 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)); } diff --git a/lib/Target/ARM/README-Thumb.txt b/lib/Target/ARM/README-Thumb.txt index 3bb8695b3a3..6c2cb710ab3 100644 --- a/lib/Target/ARM/README-Thumb.txt +++ b/lib/Target/ARM/README-Thumb.txt @@ -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]