aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2007-02-07 09:17:36 +0000
committerEvan Cheng <evan.cheng@apple.com>2007-02-07 09:17:36 +0000
commit8bed6c968fd7164222bc0cf4b86686c88381c3b8 (patch)
treec967ead91f7545288d52af859502893637d9a7e4
parent1f253d6e97f6be21210d03b748c07954313605e3 (diff)
In thumb mode, R3 is reserved, but it can be live in to the function. If
that is the case, whenever we use it as a scratch register, save it to R12 first and then restore it after the use. This is a temporary and truly horrible workaround! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@33999 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMMachineFunctionInfo.h13
-rw-r--r--lib/Target/ARM/ARMRegisterInfo.cpp26
2 files changed, 32 insertions, 7 deletions
diff --git a/lib/Target/ARM/ARMMachineFunctionInfo.h b/lib/Target/ARM/ARMMachineFunctionInfo.h
index 6b3ac21d52..cf4c105fe1 100644
--- a/lib/Target/ARM/ARMMachineFunctionInfo.h
+++ b/lib/Target/ARM/ARMMachineFunctionInfo.h
@@ -40,6 +40,10 @@ class ARMFunctionInfo : public MachineFunctionInfo {
/// far jump.
bool LRForceSpilled;
+ /// R3IsLiveIn - True if R3 is live in to this function.
+ ///
+ bool R3IsLiveIn;
+
/// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer
/// spill stack offset.
unsigned FramePtrSpillOffset;
@@ -75,13 +79,15 @@ class ARMFunctionInfo : public MachineFunctionInfo {
public:
ARMFunctionInfo() :
isThumb(false),
- VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false),
+ VarArgsRegSaveSize(0), HasStackFrame(false),
+ LRForceSpilled(false), R3IsLiveIn(false),
FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {}
ARMFunctionInfo(MachineFunction &MF) :
isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()),
- VarArgsRegSaveSize(0), HasStackFrame(false), LRForceSpilled(false),
+ VarArgsRegSaveSize(0), HasStackFrame(false),
+ LRForceSpilled(false), R3IsLiveIn(false),
FramePtrSpillOffset(0), GPRCS1Offset(0), GPRCS2Offset(0), DPRCSOffset(0),
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0), JumpTableUId(0) {}
@@ -96,6 +102,9 @@ public:
bool isLRForceSpilled() const { return LRForceSpilled; }
void setLRIsForceSpilled(bool s) { LRForceSpilled = s; }
+ bool isR3IsLiveIn() const { return R3IsLiveIn; }
+ void setR3IsLiveIn(bool l) { R3IsLiveIn = l; }
+
unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; }
void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; }
diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp
index 644fcec63c..ac2ed8ebab 100644
--- a/lib/Target/ARM/ARMRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMRegisterInfo.cpp
@@ -401,7 +401,10 @@ void emitThumbRegPlusConstPool(MachineBasicBlock &MBB,
if (NumBytes <= 255 && NumBytes >= 0)
BuildMI(MBB, MBBI, TII.get(ARM::tMOVri8), LdReg).addImm(NumBytes);
- else
+ else if (NumBytes < 0 && NumBytes >= -255) {
+ BuildMI(MBB, MBBI, TII.get(ARM::tMOVri8), LdReg).addImm(NumBytes);
+ BuildMI(MBB, MBBI, TII.get(ARM::tNEG), LdReg).addReg(LdReg);
+ } else
emitLoadConstPool(MBB, MBBI, LdReg, NumBytes, TII);
// Emit add / sub.
@@ -811,7 +814,7 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
// being storing here. If that's the case, we do the following:
// r12 = r2
// Use r2 to materialize sp + offset
- // str r12, r2
+ // str r3, r2
// r2 = r12
unsigned ValReg = MI.getOperand(0).getReg();
unsigned TmpReg = ARM::R3;
@@ -820,6 +823,8 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R2);
TmpReg = ARM::R2;
}
+ if (TmpReg == ARM::R3 && AFI->isR3IsLiveIn())
+ BuildMI(MBB, II, TII.get(ARM::tMOVrr), ARM::R12).addReg(ARM::R3);
if (Opcode == ARM::tSpill) {
if (FrameReg == ARM::SP)
emitThumbRegPlusConstPool(MBB, II, TmpReg, FrameReg,Offset,false,TII);
@@ -835,10 +840,12 @@ void ARMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II) const{
MI.addRegOperand(FrameReg, false); // Use [reg, reg] addrmode.
else
MI.addRegOperand(0, false); // tSTR has an extra register operand.
- if (ValReg == ARM::R3) {
- MachineBasicBlock::iterator NII = next(II);
+
+ MachineBasicBlock::iterator NII = next(II);
+ if (ValReg == ARM::R3)
BuildMI(MBB, NII, TII.get(ARM::tMOVrr), ARM::R2).addReg(ARM::R12);
- }
+ if (TmpReg == ARM::R3 && AFI->isR3IsLiveIn())
+ BuildMI(MBB, NII, TII.get(ARM::tMOVrr), ARM::R3).addReg(ARM::R12);
} else
assert(false && "Unexpected opcode!");
} else {
@@ -1032,6 +1039,15 @@ void ARMRegisterInfo::emitPrologue(MachineFunction &MF) const {
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
if (isThumb) {
+ // Check if R3 is live in. It might have to be used as a scratch register.
+ for (MachineFunction::livein_iterator I=MF.livein_begin(),E=MF.livein_end();
+ I != E; ++I) {
+ if ((*I).first == ARM::R3) {
+ AFI->setR3IsLiveIn(true);
+ break;
+ }
+ }
+
// Thumb add/sub sp, imm8 instructions implicitly multiply the offset by 4.
NumBytes = (NumBytes + 3) & ~3;
MFI->setStackSize(NumBytes);