diff options
Diffstat (limited to 'llvm/lib/Target/ARM/ARMBlockPlacement.cpp')
| -rw-r--r-- | llvm/lib/Target/ARM/ARMBlockPlacement.cpp | 108 |
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); } |
