summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/ARM/ARMBlockPlacement.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/ARM/ARMBlockPlacement.cpp')
-rw-r--r--llvm/lib/Target/ARM/ARMBlockPlacement.cpp108
1 files changed, 89 insertions, 19 deletions
diff --git a/llvm/lib/Target/ARM/ARMBlockPlacement.cpp b/llvm/lib/Target/ARM/ARMBlockPlacement.cpp
index 5ea47f529b23..ddbd6702e528 100644
--- a/llvm/lib/Target/ARM/ARMBlockPlacement.cpp
+++ b/llvm/lib/Target/ARM/ARMBlockPlacement.cpp
@@ -31,6 +31,8 @@ private:
const ARMBaseInstrInfo *TII;
std::unique_ptr<ARMBasicBlockUtils> BBUtils = nullptr;
MachineLoopInfo *MLI = nullptr;
+ // A list of WLS instructions that need to be reverted to DLS.
+ SmallVector<MachineInstr *> RevertedWhileLoops;
public:
static char ID;
@@ -41,9 +43,9 @@ public:
bool blockIsBefore(MachineBasicBlock *BB, MachineBasicBlock *Other);
bool fixBackwardsWLS(MachineLoop *ML);
bool processPostOrderLoops(MachineLoop *ML);
+ bool revertWhileToDoLoop(MachineInstr *WLS);
void getAnalysisUsage(AnalysisUsage &AU) const override {
- AU.setPreservesCFG();
AU.addRequired<MachineLoopInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -82,6 +84,66 @@ static MachineInstr *findWLS(MachineLoop *ML) {
return nullptr;
}
+// Revert a WhileLoopStart to an equivalent DoLoopStart and branch. Note that
+// because of the branches this requires an extra block to be created.
+bool ARMBlockPlacement::revertWhileToDoLoop(MachineInstr *WLS) {
+ // lr = t2WhileLoopStartTP r0, r1, TgtBB
+ // t2Br Ph
+ // ->
+ // cmp r0, 0
+ // brcc TgtBB
+ // block2:
+ // LR = t2DoLoopStartTP r0, r1
+ // t2Br Ph
+ MachineBasicBlock *Preheader = WLS->getParent();
+ assert(WLS != &Preheader->back());
+ assert(WLS->getNextNode() == &Preheader->back());
+ MachineInstr *Br = &Preheader->back();
+ assert(Br->getOpcode() == ARM::t2B);
+ assert(Br->getOperand(1).getImm() == 14);
+
+ // Clear the kill flags, as the cmp/bcc will no longer kill any operands.
+ WLS->getOperand(1).setIsKill(false);
+ if (WLS->getOpcode() == ARM::t2WhileLoopStartTP)
+ WLS->getOperand(2).setIsKill(false);
+
+ // Create the new block
+ MachineBasicBlock *NewBlock = Preheader->getParent()->CreateMachineBasicBlock(
+ Preheader->getBasicBlock());
+ Preheader->getParent()->insert(++Preheader->getIterator(), NewBlock);
+ // Move the Br to it
+ Br->removeFromParent();
+ NewBlock->insert(NewBlock->end(), Br);
+ // And setup the successors correctly.
+ Preheader->replaceSuccessor(Br->getOperand(0).getMBB(), NewBlock);
+ NewBlock->addSuccessor(Br->getOperand(0).getMBB());
+
+ // Create a new DLS to replace the WLS
+ MachineInstrBuilder MIB =
+ BuildMI(*NewBlock, Br, WLS->getDebugLoc(),
+ TII->get(WLS->getOpcode() == ARM::t2WhileLoopStartTP
+ ? ARM::t2DoLoopStartTP
+ : ARM::t2DoLoopStart));
+ MIB.add(WLS->getOperand(0));
+ MIB.add(WLS->getOperand(1));
+ if (WLS->getOpcode() == ARM::t2WhileLoopStartTP)
+ MIB.add(WLS->getOperand(2));
+
+ LLVM_DEBUG(dbgs() << DEBUG_PREFIX
+ << "Reverting While Loop to Do Loop: " << *WLS << "\n");
+
+ RevertWhileLoopStartLR(WLS, TII, ARM::t2Bcc, true);
+
+ LivePhysRegs LiveRegs;
+ computeAndAddLiveIns(LiveRegs, *NewBlock);
+
+ Preheader->getParent()->RenumberBlocks();
+ BBUtils->computeAllBlockSizes();
+ BBUtils->adjustBBOffsetsAfter(Preheader);
+
+ return true;
+}
+
/// Checks if loop has a backwards branching WLS, and if possible, fixes it.
/// This requires checking the predecessor (ie. preheader or it's predecessor)
/// for a WLS and if its loopExit/target is before it.
@@ -125,11 +187,10 @@ bool ARMBlockPlacement::fixBackwardsWLS(MachineLoop *ML) {
// TODO: Analyse the blocks to make a decision if it would be worth
// moving Preheader even if we'd introduce a backwards WLS
if (WLSTarget == Predecessor) {
- LLVM_DEBUG(
- dbgs() << DEBUG_PREFIX
- << "Can't move Predecessor"
- "block as it would convert a WLS from forward to a "
- "backwards branching WLS\n");
+ LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Can't move Predecessor block as "
+ << "it would convert a WLS from forward to a "
+ << "backwards branching WLS\n");
+ RevertedWhileLoops.push_back(WlsInstr);
return false;
}
}
@@ -162,11 +223,16 @@ bool ARMBlockPlacement::runOnMachineFunction(MachineFunction &MF) {
BBUtils->computeAllBlockSizes();
BBUtils->adjustBBOffsetsAfter(&MF.front());
bool Changed = false;
+ RevertedWhileLoops.clear();
// Find loops with a backwards branching WLS and fix if possible.
for (auto *ML : *MLI)
Changed |= processPostOrderLoops(ML);
+ // Revert any While loops still out of range to DLS loops.
+ for (auto *WlsInstr : RevertedWhileLoops)
+ Changed |= revertWhileToDoLoop(WlsInstr);
+
return Changed;
}
@@ -199,18 +265,22 @@ void ARMBlockPlacement::moveBasicBlock(MachineBasicBlock *BB,
assert(From->isSuccessor(To) &&
"'To' is expected to be a successor of 'From'");
MachineInstr &Terminator = *(--From->terminators().end());
- if (!Terminator.isUnconditionalBranch()) {
- // The BB doesn't have an unconditional branch so it relied on
- // fall-through. Fix by adding an unconditional branch to the moved BB.
- MachineInstrBuilder MIB =
- BuildMI(From, Terminator.getDebugLoc(), TII->get(ARM::t2B));
- MIB.addMBB(To);
- MIB.addImm(ARMCC::CondCodes::AL);
- MIB.addReg(ARM::NoRegister);
- LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Adding unconditional branch from "
- << From->getName() << " to " << To->getName() << ": "
- << *MIB.getInstr());
- }
+ if (!TII->isPredicated(Terminator) &&
+ (isUncondBranchOpcode(Terminator.getOpcode()) ||
+ isIndirectBranchOpcode(Terminator.getOpcode()) ||
+ isJumpTableBranchOpcode(Terminator.getOpcode()) ||
+ Terminator.isReturn()))
+ return;
+ // The BB doesn't have an unconditional branch so it relied on
+ // fall-through. Fix by adding an unconditional branch to the moved BB.
+ MachineInstrBuilder MIB =
+ BuildMI(From, Terminator.getDebugLoc(), TII->get(ARM::t2B));
+ MIB.addMBB(To);
+ MIB.addImm(ARMCC::CondCodes::AL);
+ MIB.addReg(ARM::NoRegister);
+ LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Adding unconditional branch from "
+ << From->getName() << " to " << To->getName() << ": "
+ << *MIB.getInstr());
};
// Fix fall-through to the moved BB from the one that used to be before it.
@@ -225,5 +295,5 @@ void ARMBlockPlacement::moveBasicBlock(MachineBasicBlock *BB,
F->RenumberBlocks();
BBUtils->computeAllBlockSizes();
- BBUtils->adjustBBOffsetsAfter(&F->front());
+ BBUtils->adjustBBOffsetsAfter(BB);
}