[llvm] r285232 - ARM: don't rely on push/pop reglists being in order when folding SP adjust.

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 26 13:01:00 PDT 2016


Author: tnorthover
Date: Wed Oct 26 15:01:00 2016
New Revision: 285232

URL: http://llvm.org/viewvc/llvm-project?rev=285232&view=rev
Log:
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}

Modified:
    llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
    llvm/trunk/test/CodeGen/ARM/fold-stack-adjust.ll

Modified: llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp?rev=285232&r1=285231&r2=285232&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMBaseInstrInfo.cpp Wed Oct 26 15:01:00 2016
@@ -2077,29 +2077,40 @@ bool llvm::tryFoldSPUpdateIntoPushPop(co
   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

Modified: llvm/trunk/test/CodeGen/ARM/fold-stack-adjust.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/fold-stack-adjust.ll?rev=285232&r1=285231&r2=285232&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/fold-stack-adjust.ll (original)
+++ llvm/trunk/test/CodeGen/ARM/fold-stack-adjust.ll Wed Oct 26 15:01:00 2016
@@ -218,4 +218,18 @@ exit:
   ret float %call1
 }
 
+declare void @use_arr(i32*)
+define void @test_fold_reuse() minsize {
+; CHECK-LABEL: test_fold_reuse:
+; CHECK: push.w {r4, r7, r8, lr}
+; CHECK: sub sp, #24
+; [...]
+; CHECK: add sp, #24
+; CHECK: pop.w {r4, r7, r8, pc}
+  %arr = alloca i8, i32 24
+  call void asm sideeffect "", "~{r8},~{r4}"()
+  call void @bar(i8* %arr)
+  ret void
+}
+
 declare void @llvm.va_start(i8*) nounwind




More information about the llvm-commits mailing list