diff --git a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp index ecac67a2f313..a790ab0f8523 100644 --- a/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp +++ b/llvm/lib/Target/ARM/ARMLowOverheadLoops.cpp @@ -54,6 +54,12 @@ namespace { bool ProcessLoop(MachineLoop *ML); + void RevertWhile(MachineInstr *MI) const; + + void RevertLoopDec(MachineInstr *MI) const; + + void RevertLoopEnd(MachineInstr *MI) const; + void Expand(MachineLoop *ML, MachineInstr *Start, MachineInstr *Dec, MachineInstr *End, bool Revert); @@ -208,6 +214,68 @@ bool ARMLowOverheadLoops::ProcessLoop(MachineLoop *ML) { return true; } +// WhileLoopStart holds the exit block, so produce a cmp lr, 0 and then a +// beq that branches to the exit branch. +// FIXME: Need to check that we're not trashing the CPSR when generating the +// cmp. We could also try to generate a cbz if the value in LR is also in +// another low register. +void ARMLowOverheadLoops::RevertWhile(MachineInstr *MI) const { + LLVM_DEBUG(dbgs() << "ARM Loops: Reverting to cmp: " << *MI); + 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::CPSR); + + // TODO: Try to use tBcc instead + MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2Bcc)); + MIB.add(MI->getOperand(1)); // branch target + MIB.addImm(ARMCC::EQ); // condition code + MIB.addReg(ARM::CPSR); + MI->eraseFromParent(); +} + +// TODO: Check flags so that we can possibly generate a tSubs or tSub. +void ARMLowOverheadLoops::RevertLoopDec(MachineInstr *MI) const { + LLVM_DEBUG(dbgs() << "ARM Loops: Reverting to sub: " << *MI); + MachineBasicBlock *MBB = MI->getParent(); + MachineInstrBuilder MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), + TII->get(ARM::t2SUBri)); + MIB.addDef(ARM::LR); + MIB.add(MI->getOperand(1)); + MIB.add(MI->getOperand(2)); + MIB.addImm(ARMCC::AL); + MIB.addReg(0); + MIB.addReg(0); + MI->eraseFromParent(); +} + +// Generate a subs, or sub and cmp, and a branch instead of an LE. +// FIXME: Need to check that we're not trashing the CPSR when generating +// the cmp. +void ARMLowOverheadLoops::RevertLoopEnd(MachineInstr *MI) 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::CPSR); + + // TODO Try to use tBcc instead. + // Create bne + MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2Bcc)); + MIB.add(MI->getOperand(1)); // branch target + MIB.addImm(ARMCC::NE); // condition code + MIB.addReg(ARM::CPSR); + MI->eraseFromParent(); +} + void ARMLowOverheadLoops::Expand(MachineLoop *ML, MachineInstr *Start, MachineInstr *Dec, MachineInstr *End, bool Revert) { @@ -269,60 +337,6 @@ void ARMLowOverheadLoops::Expand(MachineLoop *ML, MachineInstr *Start, return &*MIB; }; - // Generate a subs, or sub and cmp, and a branch instead of an LE. - // TODO: Check flags so that we can possibly generate a subs. - // FIXME: Need to check that we're not trashing the CPSR when generating - // the cmp. - auto ExpandBranch = [this](MachineInstr *Dec, MachineInstr *End) { - LLVM_DEBUG(dbgs() << "ARM Loops: Reverting to sub, cmp, br.\n"); - // Create sub - MachineBasicBlock *MBB = Dec->getParent(); - MachineInstrBuilder MIB = BuildMI(*MBB, Dec, Dec->getDebugLoc(), - TII->get(ARM::t2SUBri)); - MIB.addDef(ARM::LR); - MIB.add(Dec->getOperand(1)); - MIB.add(Dec->getOperand(2)); - MIB.addImm(ARMCC::AL); - MIB.addReg(0); - MIB.addReg(0); - - // Create cmp - MBB = End->getParent(); - MIB = BuildMI(*MBB, End, End->getDebugLoc(), TII->get(ARM::t2CMPri)); - MIB.addReg(ARM::LR); - MIB.addImm(0); - MIB.addImm(ARMCC::AL); - MIB.addReg(ARM::CPSR); - - // Create bne - MIB = BuildMI(*MBB, End, End->getDebugLoc(), TII->get(ARM::t2Bcc)); - MIB.add(End->getOperand(1)); // branch target - MIB.addImm(ARMCC::NE); // condition code - MIB.addReg(ARM::CPSR); - End->eraseFromParent(); - Dec->eraseFromParent(); - }; - - // WhileLoopStart holds the exit block, so produce a cmp lr, 0 and then a - // beq that branches to the exit branch. - // FIXME: Need to check that we're not trashing the CPSR when generating the - // cmp. We could also try to generate a cbz if the value in LR is also in - // another low register. - auto ExpandStart = [this](MachineInstr *MI) { - 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::CPSR); - - MIB = BuildMI(*MBB, MI, MI->getDebugLoc(), TII->get(ARM::t2Bcc)); - MIB.add(MI->getOperand(1)); // branch target - MIB.addImm(ARMCC::EQ); // condition code - MIB.addReg(ARM::CPSR); - }; - // TODO: We should be able to automatically remove these branches before we // get here - probably by teaching analyzeBranch about the pseudo // instructions. @@ -342,9 +356,11 @@ void ARMLowOverheadLoops::Expand(MachineLoop *ML, MachineInstr *Start, if (Revert) { if (Start->getOpcode() == ARM::t2WhileLoopStart) - ExpandStart(Start); - ExpandBranch(Dec, End); - Start->eraseFromParent(); + RevertWhile(Start); + else + Start->eraseFromParent(); + RevertLoopDec(Dec); + RevertLoopEnd(End); } else { Start = ExpandLoopStart(ML, Start); RemoveDeadBranch(Start);