summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2010-12-15 23:32:27 +0000
committerBill Wendling <isanbard@gmail.com>2010-12-15 23:32:27 +0000
commit7a905a82f7425d1a10b828c8bb3365b2ebc15833 (patch)
tree226bb45e75cf74fa6915d624624d526fa730ae89 /lib
parentdc3813750e4400a02099b047c3ebe5a182585ac3 (diff)
downloadllvm-7a905a82f7425d1a10b828c8bb3365b2ebc15833.tar.gz
llvm-7a905a82f7425d1a10b828c8bb3365b2ebc15833.tar.bz2
llvm-7a905a82f7425d1a10b828c8bb3365b2ebc15833.tar.xz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp3
-rw-r--r--lib/Target/ARM/Thumb1RegisterInfo.cpp64
2 files changed, 38 insertions, 29 deletions
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index 1efcae03a4..8a779cebb9 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 5b086d1a78..41a9cf3bf1 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;
}