summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Rosier <mcrosier@apple.com>2011-10-18 05:28:00 +0000
committerChad Rosier <mcrosier@apple.com>2011-10-18 05:28:00 +0000
commitfe04757f5e06ab15208ac0a2ab8d7e83c62b9f0d (patch)
tree679d85c4d3576a429a1419196494da9ecb339d96
parent895ede819f0558574fce66cc1eca80eee2deaa4e (diff)
downloadllvm-fe04757f5e06ab15208ac0a2ab8d7e83c62b9f0d.tar.gz
llvm-fe04757f5e06ab15208ac0a2ab8d7e83c62b9f0d.tar.bz2
llvm-fe04757f5e06ab15208ac0a2ab8d7e83c62b9f0d.tar.xz
Add support for dynamic stack realignment when in thumb1 mode.
rdar://10288916 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142337 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMBaseRegisterInfo.cpp7
-rw-r--r--lib/Target/ARM/ARMFrameLowering.cpp6
-rw-r--r--lib/Target/ARM/Thumb1FrameLowering.cpp30
-rw-r--r--test/CodeGen/ARM/thumb1-dynrealign.ll40
4 files changed, 72 insertions, 11 deletions
diff --git a/lib/Target/ARM/ARMBaseRegisterInfo.cpp b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
index 7c42342229..48e3c52460 100644
--- a/lib/Target/ARM/ARMBaseRegisterInfo.cpp
+++ b/lib/Target/ARM/ARMBaseRegisterInfo.cpp
@@ -626,13 +626,10 @@ bool ARMBaseRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
bool ARMBaseRegisterInfo::canRealignStack(const MachineFunction &MF) const {
const MachineFrameInfo *MFI = MF.getFrameInfo();
- const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
// We can't realign the stack if:
// 1. Dynamic stack realignment is explicitly disabled,
- // 2. This is a Thumb1 function (it's not useful, so we don't bother), or
- // 3. There are VLAs in the function and the base pointer is disabled.
- return (RealignStack && !AFI->isThumb1OnlyFunction() &&
- (!MFI->hasVarSizedObjects() || EnableBasePointer));
+ // 2. There are VLAs in the function and the base pointer is disabled.
+ return (RealignStack && (!MFI->hasVarSizedObjects() || EnableBasePointer));
}
bool ARMBaseRegisterInfo::
diff --git a/lib/Target/ARM/ARMFrameLowering.cpp b/lib/Target/ARM/ARMFrameLowering.cpp
index 2d1de6fe8e..4bac6c5fa9 100644
--- a/lib/Target/ARM/ARMFrameLowering.cpp
+++ b/lib/Target/ARM/ARMFrameLowering.cpp
@@ -881,10 +881,12 @@ ARMFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
// for sure what the stack size will be, but for this, an estimate is good
// enough. If there anything changes it, it'll be a spill, which implies
// we've used all the registers and so R4 is already used, so not marking
- // it here will be OK.
+ // it here will be OK. Also spill R4 if Thumb1 function requires stack
+ // realignment.
// FIXME: It will be better just to find spare register here.
unsigned StackSize = estimateStackSize(MF);
- if (MFI->hasVarSizedObjects() || StackSize > 508)
+ if (MFI->hasVarSizedObjects() || RegInfo->needsStackRealignment(MF) ||
+ StackSize > 508)
MF.getRegInfo().setPhysRegUsed(ARM::R4);
}
diff --git a/lib/Target/ARM/Thumb1FrameLowering.cpp b/lib/Target/ARM/Thumb1FrameLowering.cpp
index d8481778c0..ad1edc8dd8 100644
--- a/lib/Target/ARM/Thumb1FrameLowering.cpp
+++ b/lib/Target/ARM/Thumb1FrameLowering.cpp
@@ -155,10 +155,32 @@ void Thumb1FrameLowering::emitPrologue(MachineFunction &MF) const {
AFI->setGPRCalleeSavedArea2Size(GPRCS2Size);
AFI->setDPRCalleeSavedAreaSize(DPRCSSize);
- // Thumb1 does not currently support dynamic stack realignment. Report a
- // fatal error rather then silently generate bad code.
- if (RegInfo->needsStackRealignment(MF))
- report_fatal_error("Dynamic stack realignment not supported for thumb1.");
+ // If we need dynamic stack realignment, do it here. Be paranoid and make
+ // sure if we also have VLAs, we have a base pointer for frame access.
+ if (RegInfo->needsStackRealignment(MF)) {
+ // We cannot use sp as source/dest register here, thus we're emitting the
+ // following sequence:
+ // mov r4, sp
+ // lsrs r4, r4, Log2MaxAlign
+ // lsls r4, r4, Log2MaxAlign
+ // mov sp, r4
+ unsigned MaxAlign = MFI->getMaxAlignment();
+ unsigned Log2MaxAlign = Log2_32(MaxAlign);
+ AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::R4)
+ .addReg(ARM::SP, RegState::Kill));
+ AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSRri),
+ ARM::R4))
+ .addReg(ARM::R4, RegState::Kill)
+ .addImm(Log2MaxAlign));
+ AddDefaultPred(AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tLSLri),
+ ARM::R4))
+ .addReg(ARM::R4, RegState::Kill)
+ .addImm(Log2MaxAlign));
+ AddDefaultPred(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVr), ARM::SP)
+ .addReg(ARM::R4, RegState::Kill));
+
+ AFI->setShouldRestoreSPFromFP(true);
+ }
// If we need a base pointer, set it up here. It's whatever the value
// of the stack pointer is at this point. Any variable size objects
diff --git a/test/CodeGen/ARM/thumb1-dynrealign.ll b/test/CodeGen/ARM/thumb1-dynrealign.ll
new file mode 100644
index 0000000000..fa14fb42a3
--- /dev/null
+++ b/test/CodeGen/ARM/thumb1-dynrealign.ll
@@ -0,0 +1,40 @@
+; RUN: llc < %s -mtriple=thumbv6-apple-darwin | FileCheck %s
+
+; Normal load from SP
+define void @SP(i32 %i) nounwind uwtable ssp {
+entry:
+; CHECK: @SP
+; CHECK: push {r7, lr}
+; CHECK-NEXT: mov r7, sp
+; CHECK-NEXT: sub sp, #4
+; CHECK-NEXT: mov r1, sp
+; CHECK-NEXT: str r0, [r1]
+; CHECK-NEXT: mov r0, sp
+; CHECK-NEXT: blx _SP_
+; CHECK-NEXT: add sp, #4
+; CHECK-NEXT: pop {r7, pc}
+ %i.addr = alloca i32, align 4
+ store i32 %i, i32* %i.addr, align 4
+ call void @SP_(i32* %i.addr)
+ ret void
+}
+
+declare void @SP_(i32*)
+
+; Dynamic stack realignment
+define void @FP(double %a) nounwind uwtable ssp {
+entry:
+; CHECK: mov r4, sp
+; CHECK-NEXT: lsrs r4, r4, #3
+; CHECK-NEXT: lsls r4, r4, #3
+; CHECK-NEXT: mov sp, r4
+; Restore from FP
+; CHECK: subs r4, r7, #4
+; CHECK: mov sp, r4
+ %a.addr = alloca double, align 8
+ store double %a, double* %a.addr, align 8
+ call void @FP_(double* %a.addr)
+ ret void
+}
+
+declare void @FP_(double*)