summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2016-10-26 20:01:00 +0000
committerTim Northover <tnorthover@apple.com>2016-10-26 20:01:00 +0000
commita9cc3856647a26c742d06948320781f93c3e04e3 (patch)
treefc0d9f0b27e2791cf1706419caa9c363bece797c /llvm/lib
parent275853e777a2a2f7069d7b10b61ebc80bc699d5f (diff)
downloadbcm5719-llvm-a9cc3856647a26c742d06948320781f93c3e04e3.tar.gz
bcm5719-llvm-a9cc3856647a26c742d06948320781f93c3e04e3.zip
ARM: don't rely on push/pop reglists being in order when folding SP adjust.
It would be a very nice invariant to rely on, but unfortunately it doesn't necessarily hold (and the causes of mis-sorted reglists appear to be quite varied) so to be robust the frame lowering code can't assume that the first register in the list is also the first one that actually gets pushed. Should fix an issue where we were turning something like: push {r8, r4, r7, lr} sub sp, #24 into nonsense like: push {r2, r3, r4, r5, r6, r7, r8, r4, r7, lr} llvm-svn: 285232
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp27
1 files changed, 19 insertions, 8 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
index 6aa060ae0d9..9c8229c275d 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp
@@ -2077,29 +2077,40 @@ bool llvm::tryFoldSPUpdateIntoPushPop(const ARMSubtarget &Subtarget,
int RegListIdx = IsT1PushPop ? 2 : 4;
// Calculate the space we'll need in terms of registers.
- unsigned FirstReg = MI->getOperand(RegListIdx).getReg();
- unsigned RD0Reg, RegsNeeded;
+ unsigned RegsNeeded;
+ const TargetRegisterClass *RegClass;
if (IsVFPPushPop) {
- RD0Reg = ARM::D0;
RegsNeeded = NumBytes / 8;
+ RegClass = &ARM::DPRRegClass;
} else {
- RD0Reg = ARM::R0;
RegsNeeded = NumBytes / 4;
+ RegClass = &ARM::GPRRegClass;
}
// We're going to have to strip all list operands off before
// re-adding them since the order matters, so save the existing ones
// for later.
SmallVector<MachineOperand, 4> RegList;
- for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i)
- RegList.push_back(MI->getOperand(i));
+
+ // We're also going to need the first register transferred by this
+ // instruction, which won't necessarily be the first register in the list.
+ unsigned FirstRegEnc = -1;
const TargetRegisterInfo *TRI = MF.getRegInfo().getTargetRegisterInfo();
+ for (int i = MI->getNumOperands() - 1; i >= RegListIdx; --i) {
+ MachineOperand &MO = MI->getOperand(i);
+ RegList.push_back(MO);
+
+ if (MO.isReg() && TRI->getEncodingValue(MO.getReg()) < FirstRegEnc)
+ FirstRegEnc = TRI->getEncodingValue(MO.getReg());
+ }
+
const MCPhysReg *CSRegs = TRI->getCalleeSavedRegs(&MF);
// Now try to find enough space in the reglist to allocate NumBytes.
- for (unsigned CurReg = FirstReg - 1; CurReg >= RD0Reg && RegsNeeded;
- --CurReg) {
+ for (int CurRegEnc = FirstRegEnc - 1; CurRegEnc >= 0 && RegsNeeded;
+ --CurRegEnc) {
+ unsigned CurReg = RegClass->getRegister(CurRegEnc);
if (!IsPop) {
// Pushing any register is completely harmless, mark the
// register involved as undef since we don't care about it in
OpenPOWER on IntegriCloud