diff options
| author | Renato Golin <renato.golin@linaro.org> | 2014-06-10 16:39:21 +0000 |
|---|---|---|
| committer | Renato Golin <renato.golin@linaro.org> | 2014-06-10 16:39:21 +0000 |
| commit | 65eea557aee10ddf0dc35be069597f34554de308 (patch) | |
| tree | 2f3ff5a82eb50b2ed5ea4ddf89246de197781235 | |
| parent | 3787b122552d8dfc1cb965494bf4f1803c6acbc5 (diff) | |
| download | bcm5719-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.cpp | 14 | ||||
| -rw-r--r-- | llvm/test/CodeGen/Thumb/2014-06-10-thumb1-ldst-opt-bug.ll | 17 |
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 |

