From: Bill Wendling Date: Wed, 15 Dec 2010 23:32:27 +0000 (+0000) Subject: If we're changing the frame register to a physical register other than SP, we X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=7a905a82f7425d1a10b828c8bb3365b2ebc15833;p=oota-llvm.git If we're changing the frame register to a physical register other than SP, we need to use tLDRi and tSTRi instead of tLDRspi and tSTRspi respectively. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121915 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp index 1efcae03a4f..8a779cebb95 100644 --- a/lib/Target/ARM/ARMMCCodeEmitter.cpp +++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp @@ -806,10 +806,9 @@ getAddrModeThumbSPOpValue(const MCInst &MI, unsigned OpIdx, // [SP, #imm] // {7-0} = imm8 const MCOperand &MO1 = MI.getOperand(OpIdx + 1); -#if 0 // FIXME: This crashes2003-05-14-initialize-string.c assert(MI.getOperand(OpIdx).getReg() == ARM::SP && "Unexpected base register!"); -#endif + // The immediate is already shifted for the implicit zeroes, so no change // here. return MO1.getImm() & 0xff; diff --git a/lib/Target/ARM/Thumb1RegisterInfo.cpp b/lib/Target/ARM/Thumb1RegisterInfo.cpp index 5b086d1a783..41a9cf3bf17 100644 --- a/lib/Target/ARM/Thumb1RegisterInfo.cpp +++ b/lib/Target/ARM/Thumb1RegisterInfo.cpp @@ -351,6 +351,20 @@ static void removeOperands(MachineInstr &MI, unsigned i) { MI.RemoveOperand(Op); } +/// convertToNonSPOpcode - Change the opcode to the non-SP version, because +/// we're replacing the frame index with a non-SP register. +static unsigned convertToNonSPOpcode(unsigned Opcode) { + switch (Opcode) { + case ARM::tLDRspi: + return ARM::tLDRi; + + case ARM::tSTRspi: + return ARM::tSTRi; + } + + return Opcode; +} + bool Thumb1RegisterInfo:: rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, unsigned FrameReg, int &Offset, @@ -452,55 +466,51 @@ rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx, } return true; } else { - unsigned ImmIdx = 0; - int InstrOffs = 0; - unsigned NumBits = 0; - unsigned Scale = 1; - switch (AddrMode) { - case ARMII::AddrModeT1_s: { - ImmIdx = FrameRegIdx+1; - InstrOffs = MI.getOperand(ImmIdx).getImm(); - NumBits = (FrameReg == ARM::SP) ? 8 : 5; - Scale = 4; - break; - } - default: + if (AddrMode != ARMII::AddrModeT1_s) llvm_unreachable("Unsupported addressing mode!"); - break; - } + + unsigned ImmIdx = FrameRegIdx + 1; + int InstrOffs = MI.getOperand(ImmIdx).getImm(); + unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5; + unsigned Scale = 4; Offset += InstrOffs * Scale; - assert((Offset & (Scale-1)) == 0 && "Can't encode this offset!"); + assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!"); // Common case: small offset, fits into instruction. MachineOperand &ImmOp = MI.getOperand(ImmIdx); int ImmedOffset = Offset / Scale; unsigned Mask = (1 << NumBits) - 1; + if ((unsigned)Offset <= Mask * Scale) { - // Replace the FrameIndex with sp + // Replace the FrameIndex with the frame register (e.g., sp). MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false); ImmOp.ChangeToImmediate(ImmedOffset); + + // If we're using a register where sp was stored, convert the instruction + // to the non-SP version. + unsigned NewOpc = convertToNonSPOpcode(Opcode); + if (NewOpc != Opcode && FrameReg != ARM::SP) + MI.setDesc(TII.get(NewOpc)); + return true; } - bool isThumSpillRestore = Opcode == ARM::tRestore || Opcode == ARM::tSpill; - if (AddrMode == ARMII::AddrModeT1_s) { - // Thumb tLDRspi, tSTRspi. These will change to instructions that use - // a different base register. - NumBits = 5; - Mask = (1 << NumBits) - 1; - } + NumBits = 5; + Mask = (1 << NumBits) - 1; + // If this is a thumb spill / restore, we will be using a constpool load to // materialize the offset. - if (AddrMode == ARMII::AddrModeT1_s && isThumSpillRestore) + if (Opcode == ARM::tRestore || Opcode == ARM::tSpill) { ImmOp.ChangeToImmediate(0); - else { + } else { // Otherwise, it didn't fit. Pull in what we can to simplify the immed. ImmedOffset = ImmedOffset & Mask; ImmOp.ChangeToImmediate(ImmedOffset); - Offset &= ~(Mask*Scale); + Offset &= ~(Mask * Scale); } } + return Offset == 0; }