ARMBlockPlacement.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. //===-- ARMBlockPlacement.cpp - ARM block placement pass ------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This pass re-arranges machine basic blocks to suit target requirements.
  10. // Currently it only moves blocks to fix backwards WLS branches.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "ARM.h"
  14. #include "ARMBaseInstrInfo.h"
  15. #include "ARMBasicBlockInfo.h"
  16. #include "ARMSubtarget.h"
  17. #include "llvm/CodeGen/MachineFunctionPass.h"
  18. #include "llvm/CodeGen/MachineInstrBuilder.h"
  19. #include "llvm/CodeGen/MachineLoopInfo.h"
  20. using namespace llvm;
  21. #define DEBUG_TYPE "arm-block-placement"
  22. #define DEBUG_PREFIX "ARM Block Placement: "
  23. namespace llvm {
  24. class ARMBlockPlacement : public MachineFunctionPass {
  25. private:
  26. const ARMBaseInstrInfo *TII;
  27. std::unique_ptr<ARMBasicBlockUtils> BBUtils = nullptr;
  28. MachineLoopInfo *MLI = nullptr;
  29. public:
  30. static char ID;
  31. ARMBlockPlacement() : MachineFunctionPass(ID) {}
  32. bool runOnMachineFunction(MachineFunction &MF) override;
  33. void moveBasicBlock(MachineBasicBlock *BB, MachineBasicBlock *After);
  34. bool blockIsBefore(MachineBasicBlock *BB, MachineBasicBlock *Other);
  35. void getAnalysisUsage(AnalysisUsage &AU) const override {
  36. AU.setPreservesCFG();
  37. AU.addRequired<MachineLoopInfo>();
  38. MachineFunctionPass::getAnalysisUsage(AU);
  39. }
  40. };
  41. } // namespace llvm
  42. FunctionPass *llvm::createARMBlockPlacementPass() {
  43. return new ARMBlockPlacement();
  44. }
  45. char ARMBlockPlacement::ID = 0;
  46. INITIALIZE_PASS(ARMBlockPlacement, DEBUG_TYPE, "ARM block placement", false,
  47. false)
  48. bool ARMBlockPlacement::runOnMachineFunction(MachineFunction &MF) {
  49. if (skipFunction(MF.getFunction()))
  50. return false;
  51. const ARMSubtarget &ST = static_cast<const ARMSubtarget &>(MF.getSubtarget());
  52. if (!ST.hasLOB())
  53. return false;
  54. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Running on " << MF.getName() << "\n");
  55. MLI = &getAnalysis<MachineLoopInfo>();
  56. TII = static_cast<const ARMBaseInstrInfo *>(ST.getInstrInfo());
  57. BBUtils = std::unique_ptr<ARMBasicBlockUtils>(new ARMBasicBlockUtils(MF));
  58. MF.RenumberBlocks();
  59. BBUtils->computeAllBlockSizes();
  60. BBUtils->adjustBBOffsetsAfter(&MF.front());
  61. bool Changed = false;
  62. // Find loops with a backwards branching WLS.
  63. // This requires looping over the loops in the function, checking each
  64. // preheader for a WLS and if its target is before the preheader. If moving
  65. // the target block wouldn't produce another backwards WLS or a new forwards
  66. // LE branch then move the target block after the preheader.
  67. for (auto *ML : *MLI) {
  68. MachineBasicBlock *Preheader = ML->getLoopPredecessor();
  69. if (!Preheader)
  70. continue;
  71. for (auto &Terminator : Preheader->terminators()) {
  72. if (Terminator.getOpcode() != ARM::t2WhileLoopStart)
  73. continue;
  74. MachineBasicBlock *LoopExit = Terminator.getOperand(1).getMBB();
  75. // We don't want to move the function's entry block.
  76. if (!LoopExit->getPrevNode())
  77. continue;
  78. if (blockIsBefore(Preheader, LoopExit))
  79. continue;
  80. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Found a backwards WLS from "
  81. << Preheader->getFullName() << " to "
  82. << LoopExit->getFullName() << "\n");
  83. // Make sure that moving the target block doesn't cause any of its WLSs
  84. // that were previously not backwards to become backwards
  85. bool CanMove = true;
  86. for (auto &LoopExitTerminator : LoopExit->terminators()) {
  87. if (LoopExitTerminator.getOpcode() != ARM::t2WhileLoopStart)
  88. continue;
  89. // An example loop structure where the LoopExit can't be moved, since
  90. // bb1's WLS will become backwards once it's moved after bb3 bb1: -
  91. // LoopExit
  92. // WLS bb2 - LoopExit2
  93. // bb2:
  94. // ...
  95. // bb3: - Preheader
  96. // WLS bb1
  97. // bb4: - Header
  98. MachineBasicBlock *LoopExit2 =
  99. LoopExitTerminator.getOperand(1).getMBB();
  100. // If the WLS from LoopExit to LoopExit2 is already backwards then
  101. // moving LoopExit won't affect it, so it can be moved. If LoopExit2 is
  102. // after the Preheader then moving will keep it as a forward branch, so
  103. // it can be moved. If LoopExit2 is between the Preheader and LoopExit
  104. // then moving LoopExit will make it a backwards branch, so it can't be
  105. // moved since we'd fix one and introduce one backwards branch.
  106. // TODO: Analyse the blocks to make a decision if it would be worth
  107. // moving LoopExit even if LoopExit2 is between the Preheader and
  108. // LoopExit.
  109. if (!blockIsBefore(LoopExit2, LoopExit) &&
  110. (LoopExit2 == Preheader || blockIsBefore(LoopExit2, Preheader))) {
  111. LLVM_DEBUG(dbgs() << DEBUG_PREFIX
  112. << "Can't move the target block as it would "
  113. "introduce a new backwards WLS branch\n");
  114. CanMove = false;
  115. break;
  116. }
  117. }
  118. if (CanMove) {
  119. // Make sure no LEs become forwards.
  120. // An example loop structure where the LoopExit can't be moved, since
  121. // bb2's LE will become forwards once bb1 is moved after bb3.
  122. // bb1: - LoopExit
  123. // bb2:
  124. // LE bb1 - Terminator
  125. // bb3: - Preheader
  126. // WLS bb1
  127. // bb4: - Header
  128. for (auto It = LoopExit->getIterator(); It != Preheader->getIterator();
  129. It++) {
  130. MachineBasicBlock *MBB = &*It;
  131. for (auto &Terminator : MBB->terminators()) {
  132. if (Terminator.getOpcode() != ARM::t2LoopEndDec)
  133. continue;
  134. MachineBasicBlock *LETarget = Terminator.getOperand(2).getMBB();
  135. // The LE will become forwards branching if it branches to LoopExit
  136. // which isn't allowed by the architecture, so we should avoid
  137. // introducing these.
  138. // TODO: Analyse the blocks to make a decision if it would be worth
  139. // moving LoopExit even if we'd introduce a forwards LE
  140. if (LETarget == LoopExit) {
  141. LLVM_DEBUG(dbgs() << DEBUG_PREFIX
  142. << "Can't move the target block as it would "
  143. "introduce a new forwards LE branch\n");
  144. CanMove = false;
  145. break;
  146. }
  147. }
  148. }
  149. if (!CanMove)
  150. break;
  151. }
  152. if (CanMove) {
  153. moveBasicBlock(LoopExit, Preheader);
  154. Changed = true;
  155. break;
  156. }
  157. }
  158. }
  159. return Changed;
  160. }
  161. bool ARMBlockPlacement::blockIsBefore(MachineBasicBlock *BB,
  162. MachineBasicBlock *Other) {
  163. return BBUtils->getOffsetOf(Other) > BBUtils->getOffsetOf(BB);
  164. }
  165. void ARMBlockPlacement::moveBasicBlock(MachineBasicBlock *BB,
  166. MachineBasicBlock *After) {
  167. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Moving " << BB->getName() << " after "
  168. << After->getName() << "\n");
  169. MachineBasicBlock *BBPrevious = BB->getPrevNode();
  170. assert(BBPrevious && "Cannot move the function entry basic block");
  171. MachineBasicBlock *AfterNext = After->getNextNode();
  172. MachineBasicBlock *BBNext = BB->getNextNode();
  173. BB->moveAfter(After);
  174. auto FixFallthrough = [&](MachineBasicBlock *From, MachineBasicBlock *To) {
  175. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Checking for fallthrough from "
  176. << From->getName() << " to " << To->getName() << "\n");
  177. assert(From->isSuccessor(To) &&
  178. "'To' is expected to be a successor of 'From'");
  179. MachineInstr &Terminator = *(--From->terminators().end());
  180. if (!Terminator.isUnconditionalBranch()) {
  181. // The BB doesn't have an unconditional branch so it relied on
  182. // fall-through. Fix by adding an unconditional branch to the moved BB.
  183. MachineInstrBuilder MIB =
  184. BuildMI(From, Terminator.getDebugLoc(), TII->get(ARM::t2B));
  185. MIB.addMBB(To);
  186. MIB.addImm(ARMCC::CondCodes::AL);
  187. MIB.addReg(ARM::NoRegister);
  188. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Adding unconditional branch from "
  189. << From->getName() << " to " << To->getName() << ": "
  190. << *MIB.getInstr());
  191. }
  192. };
  193. // Fix fall-through to the moved BB from the one that used to be before it.
  194. if (BBPrevious->isSuccessor(BB))
  195. FixFallthrough(BBPrevious, BB);
  196. // Fix fall through from the destination BB to the one that used to follow.
  197. if (AfterNext && After->isSuccessor(AfterNext))
  198. FixFallthrough(After, AfterNext);
  199. // Fix fall through from the moved BB to the one that used to follow.
  200. if (BBNext && BB->isSuccessor(BBNext))
  201. FixFallthrough(BB, BBNext);
  202. BBUtils->adjustBBOffsetsAfter(After);
  203. }