summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Golin <renato.golin@linaro.org>2014-06-10 16:39:21 +0000
committerRenato Golin <renato.golin@linaro.org>2014-06-10 16:39:21 +0000
commit65eea557aee10ddf0dc35be069597f34554de308 (patch)
tree2f3ff5a82eb50b2ed5ea4ddf89246de197781235
parent3787b122552d8dfc1cb965494bf4f1803c6acbc5 (diff)
downloadbcm5719-llvm-65eea557aee10ddf0dc35be069597f34554de308.tar.gz
bcm5719-llvm-65eea557aee10ddf0dc35be069597f34554de308.zip
Fix a bug in the Thumb1 ARM Load/Store optimizer
Previously, the basic block was searched for future uses of the base register, and if necessary any writeback to the base register was reset using a SUB instruction (e.g. before calling a function) just before such a use. However, this step happened *before* the merged LDM/STM instruction was built. So if there was (e.g.) a function call directly after the not-yet-formed LDM/STM, the pass would first insert a SUB instruction to reset the base register, and then (at the same location, incorrectly) insert the LDM/STM itself. This patch fixes PR19972. Patch by Moritz Roth. llvm-svn: 210542
-rw-r--r--llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp14
-rw-r--r--llvm/test/CodeGen/Thumb/2014-06-10-thumb1-ldst-opt-bug.ll17
2 files changed, 24 insertions, 7 deletions
diff --git a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
index ee7df5476c7..62fd0596569 100644
--- a/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/ARM/ARMLoadStoreOptimizer.cpp
@@ -505,7 +505,7 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
// Exception: If the base register is in the input reglist, Thumb1 LDM is
// non-writeback. Check for this.
- if (Opcode == ARM::tLDRi && isThumb1)
+ if (Opcode == ARM::tLDMIA && isThumb1)
for (unsigned I = 0; I < NumRegs; ++I)
if (Base == Regs[I].first) {
Writeback = false;
@@ -519,17 +519,17 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
// Update tLDMIA with writeback if necessary.
Opcode = ARM::tLDMIA_UPD;
- // The base isn't dead after a merged instruction with writeback. Update
- // future uses of the base with the added offset (if possible), or reset
- // the base register as necessary.
- if (!BaseKill)
- UpdateBaseRegUses(MBB, MBBI, dl, Base, NumRegs, Pred, PredReg);
-
MIB = BuildMI(MBB, MBBI, dl, TII->get(Opcode));
// Thumb1: we might need to set base writeback when building the MI.
MIB.addReg(Base, getDefRegState(true))
.addReg(Base, getKillRegState(BaseKill));
+
+ // The base isn't dead after a merged instruction with writeback. Update
+ // future uses of the base with the added offset (if possible), or reset
+ // the base register as necessary.
+ if (!BaseKill)
+ UpdateBaseRegUses(MBB, MBBI, dl, Base, NumRegs, Pred, PredReg);
} else {
// No writeback, simply build the MachineInstr.
MIB = BuildMI(MBB, MBBI, dl, TII->get(Opcode));
diff --git a/llvm/test/CodeGen/Thumb/2014-06-10-thumb1-ldst-opt-bug.ll b/llvm/test/CodeGen/Thumb/2014-06-10-thumb1-ldst-opt-bug.ll
new file mode 100644
index 00000000000..3c43383d7a2
--- /dev/null
+++ b/llvm/test/CodeGen/Thumb/2014-06-10-thumb1-ldst-opt-bug.ll
@@ -0,0 +1,17 @@
+; RUN: llc < %s -mtriple=thumbv6m-eabi -o - | FileCheck %s
+
+define void @foo(i32* %A) #0 {
+entry:
+; CHECK-LABEL: foo:
+; CHECK: push {r7, lr}
+; CHECK: ldm [[REG0:r[0-9]]]!,
+; CHECK-NEXT: subs [[REG0]]
+; CHECK-NEXT: bl
+ %0 = load i32* %A, align 4
+ %arrayidx1 = getelementptr inbounds i32* %A, i32 1
+ %1 = load i32* %arrayidx1, align 4
+ tail call void @bar(i32* %A, i32 %0, i32 %1) #2
+ ret void
+}
+
+declare void @bar(i32*, i32, i32) #1
OpenPOWER on IntegriCloud