diff --git a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp --- a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp +++ b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp @@ -70,9 +70,9 @@ void RevertWhile(MachineInstr *MI) const; - void RevertLoopDec(MachineInstr *MI) const; + bool RevertLoopDec(MachineInstr *MI, bool AllowFlags = false) const; - void RevertLoopEnd(MachineInstr *MI) const; + void RevertLoopEnd(MachineInstr *MI, bool SkipCmp = false) const; void Expand(MachineLoop *ML, MachineInstr *Start, MachineInstr *InsertPt, MachineInstr *Dec, @@ -377,10 +377,21 @@ MI->eraseFromParent(); } -// TODO: Check flags so that we can possibly generate a tSubs or tSub. -void ARMLowOverheadLoops::RevertLoopDec(MachineInstr *MI) const { +bool ARMLowOverheadLoops::RevertLoopDec(MachineInstr *MI, + bool AllowFlags) const { LLVM_DEBUG(dbgs() << "ARM Loops: Reverting to sub: " << *MI); MachineBasicBlock *MBB = MI->getParent(); + + // If nothing uses or defines CPSR between LoopDec and LoopEnd, use a t2SUBS. + bool SetFlags = false; + if (AllowFlags) { + if (auto *Def = SearchForDef(MI, MBB->end(), ARM::CPSR)) { + if (!SearchForUse(MI, MBB->end(), ARM::CPSR) && + Def->getOpcode() == ARM::t2LoopEnd) + SetFlags = true; + } + } + MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2SUBri)); MIB.addDef(ARM::LR); @@ -388,29 +399,39 @@ MIB.add(MI->getOperand(2)); MIB.addImm(ARMCC::AL); MIB.addReg(0); - MIB.addReg(0); + + if (SetFlags) { + MIB.addReg(ARM::CPSR); + MIB->getOperand(5).setIsDef(true); + } else + MIB.addReg(0); + MI->eraseFromParent(); + return SetFlags; } // Generate a subs, or sub and cmp, and a branch instead of an LE. -void ARMLowOverheadLoops::RevertLoopEnd(MachineInstr *MI) const { +void ARMLowOverheadLoops::RevertLoopEnd(MachineInstr *MI, bool SkipCmp) const { LLVM_DEBUG(dbgs() << "ARM Loops: Reverting to cmp, br: " << *MI); - // Create cmp MachineBasicBlock *MBB = MI->getParent(); - MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), - TII->get(ARM::t2CMPri)); - MIB.addReg(ARM::LR); - MIB.addImm(0); - MIB.addImm(ARMCC::AL); - MIB.addReg(ARM::NoRegister); + // Create cmp + if (!SkipCmp) { + MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), + TII->get(ARM::t2CMPri)); + MIB.addReg(ARM::LR); + MIB.addImm(0); + MIB.addImm(ARMCC::AL); + MIB.addReg(ARM::NoRegister); + } MachineBasicBlock *DestBB = MI->getOperand(1).getMBB(); unsigned BrOpc = BBUtils->isBBInRange(MI, DestBB, 254) ? ARM::tBcc : ARM::t2Bcc; // Create bne - MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc)); + MachineInstrBuilder MIB = + BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(BrOpc)); MIB.add(MI->getOperand(1)); // branch target MIB.addImm(ARMCC::NE); // condition code MIB.addReg(ARM::CPSR); @@ -480,8 +501,8 @@ RevertWhile(Start); else Start->eraseFromParent(); - RevertLoopDec(Dec); - RevertLoopEnd(End); + bool FlagsAlreadySet = RevertLoopDec(Dec, true); + RevertLoopEnd(End, FlagsAlreadySet); } else { Start = ExpandLoopStart(ML, Start, InsertPt); RemoveDeadBranch(Start); diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/branch-targets.ll b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/branch-targets.ll --- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/branch-targets.ll +++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/branch-targets.ll @@ -14,8 +14,7 @@ ; CHECK-END: .LBB0_1: ; CHECK-END: b .LBB0_3 ; CHECK-END: .LBB0_2: -; CHECK-END: sub.w lr, lr, #1 -; CHECK-END: cmp.w lr, #0 +; CHECK-END: subs.w lr, lr, #1 ; CHECK-END: bne .LBB0_3 ; CHECK-END: b .LBB0_4 ; CHECK-END: .LBB0_3: diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/end-positive-offset.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/end-positive-offset.mir --- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/end-positive-offset.mir +++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/end-positive-offset.mir @@ -3,9 +3,10 @@ # CHECK-NOT: DoLoopStart # CHECK-NOT: DLS # CHECK: bb.1.for.body: -# CHECK: t2CMPri $lr, 0, 14, $noreg, implicit-def $cpsr -# CHECK: tBcc %bb.3, 1, $cpsr -# CHECK: tB %bb.2, 14, $noreg +# CHECK: $lr = t2SUBri killed renamable $lr, 1, 14, $noreg, def $cpsr +# CHECK-NOT: t2CMPri $lr +# CHECK: tBcc %bb.3, 1, $cpsr +# CHECK: tB %bb.2, 14, $noreg # CHECK: bb.2.for.cond.cleanup: # CHECK: bb.3.for.header: diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-non-header.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-non-header.mir --- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-non-header.mir +++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-non-header.mir @@ -1,10 +1,10 @@ # RUN: llc -mtriple=thumbv8.1m.main -run-pass=arm-low-overhead-loops --verify-machineinstrs %s -o - | FileCheck %s # CHECK-NOT: t2DLS # CHECK: bb.5.for.inc16: -# CHECK: $lr = t2SUBri killed renamable $lr, 1, 14 -# CHECK: t2CMPri $lr, 0, 14 -# CHECK: tBcc %bb.6, 1 -# CHECK: tB %bb.2 +# CHECK: $lr = t2SUBri killed renamable $lr, 1, 14, $noreg, def $cpsr +# CHECK-NOT: t2CMPri $lr +# CHECK: tBcc %bb.6, 1 +# CHECK: tB %bb.2 # CHECK: bb.6.for.cond4.preheader: --- | diff --git a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-while.mir b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-while.mir --- a/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-while.mir +++ b/llvm/test/CodeGen/Thumb2/LowOverheadLoops/revert-while.mir @@ -7,8 +7,7 @@ # CHECK: bb.1.do.body.preheader: # CHECK: $lr = tMOVr killed $r3 # CHECK: bb.2.do.body: -# CHECK: $lr = t2SUBri killed renamable $lr, 1, 14 -# CHECK-NEXT: t2CMPri $lr, 0, 14, $noreg, implicit-def $cpsr +# CHECK: $lr = t2SUBri killed renamable $lr, 1, 14, $noreg, def $cpsr # CHECK-NEXT: t2Bcc %bb.2, 1, $cpsr # CHECK-NEXT: tB %bb.3, 14