ARMBlockPlacement.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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 "MVETailPredUtils.h"
  18. #include "llvm/CodeGen/LivePhysRegs.h"
  19. #include "llvm/CodeGen/MachineFunctionPass.h"
  20. #include "llvm/CodeGen/MachineInstrBuilder.h"
  21. #include "llvm/CodeGen/MachineLoopInfo.h"
  22. using namespace llvm;
  23. #define DEBUG_TYPE "arm-block-placement"
  24. #define DEBUG_PREFIX "ARM Block Placement: "
  25. namespace llvm {
  26. class ARMBlockPlacement : public MachineFunctionPass {
  27. private:
  28. const ARMBaseInstrInfo *TII;
  29. std::unique_ptr<ARMBasicBlockUtils> BBUtils = nullptr;
  30. MachineLoopInfo *MLI = nullptr;
  31. // A list of WLS instructions that need to be reverted to DLS.
  32. SmallVector<MachineInstr *> RevertedWhileLoops;
  33. public:
  34. static char ID;
  35. ARMBlockPlacement() : MachineFunctionPass(ID) {}
  36. bool runOnMachineFunction(MachineFunction &MF) override;
  37. void moveBasicBlock(MachineBasicBlock *BB, MachineBasicBlock *Before);
  38. bool blockIsBefore(MachineBasicBlock *BB, MachineBasicBlock *Other);
  39. bool fixBackwardsWLS(MachineLoop *ML);
  40. bool processPostOrderLoops(MachineLoop *ML);
  41. bool revertWhileToDoLoop(MachineInstr *WLS);
  42. void getAnalysisUsage(AnalysisUsage &AU) const override {
  43. AU.addRequired<MachineLoopInfo>();
  44. MachineFunctionPass::getAnalysisUsage(AU);
  45. }
  46. };
  47. } // namespace llvm
  48. FunctionPass *llvm::createARMBlockPlacementPass() {
  49. return new ARMBlockPlacement();
  50. }
  51. char ARMBlockPlacement::ID = 0;
  52. INITIALIZE_PASS(ARMBlockPlacement, DEBUG_TYPE, "ARM block placement", false,
  53. false)
  54. static MachineInstr *findWLSInBlock(MachineBasicBlock *MBB) {
  55. for (auto &Terminator : MBB->terminators()) {
  56. if (isWhileLoopStart(Terminator))
  57. return &Terminator;
  58. }
  59. return nullptr;
  60. }
  61. /// Find WhileLoopStart in the loop predecessor BB or otherwise in its only
  62. /// predecessor. If found, returns (BB, WLS Instr) pair, otherwise a null pair.
  63. static MachineInstr *findWLS(MachineLoop *ML) {
  64. MachineBasicBlock *Predecessor = ML->getLoopPredecessor();
  65. if (!Predecessor)
  66. return nullptr;
  67. MachineInstr *WlsInstr = findWLSInBlock(Predecessor);
  68. if (WlsInstr)
  69. return WlsInstr;
  70. if (Predecessor->pred_size() == 1)
  71. return findWLSInBlock(*Predecessor->pred_begin());
  72. return nullptr;
  73. }
  74. // Revert a WhileLoopStart to an equivalent DoLoopStart and branch. Note that
  75. // because of the branches this requires an extra block to be created.
  76. bool ARMBlockPlacement::revertWhileToDoLoop(MachineInstr *WLS) {
  77. // lr = t2WhileLoopStartTP r0, r1, TgtBB
  78. // t2Br Ph
  79. // ->
  80. // cmp r0, 0
  81. // brcc TgtBB
  82. // block2:
  83. // LR = t2DoLoopStartTP r0, r1
  84. // t2Br Ph
  85. MachineBasicBlock *Preheader = WLS->getParent();
  86. assert(WLS != &Preheader->back());
  87. assert(WLS->getNextNode() == &Preheader->back());
  88. MachineInstr *Br = &Preheader->back();
  89. assert(Br->getOpcode() == ARM::t2B);
  90. assert(Br->getOperand(1).getImm() == 14);
  91. // Clear the kill flags, as the cmp/bcc will no longer kill any operands.
  92. WLS->getOperand(1).setIsKill(false);
  93. if (WLS->getOpcode() == ARM::t2WhileLoopStartTP)
  94. WLS->getOperand(2).setIsKill(false);
  95. // Create the new block
  96. MachineBasicBlock *NewBlock = Preheader->getParent()->CreateMachineBasicBlock(
  97. Preheader->getBasicBlock());
  98. Preheader->getParent()->insert(++Preheader->getIterator(), NewBlock);
  99. // Move the Br to it
  100. Br->removeFromParent();
  101. NewBlock->insert(NewBlock->end(), Br);
  102. // And setup the successors correctly.
  103. Preheader->replaceSuccessor(Br->getOperand(0).getMBB(), NewBlock);
  104. NewBlock->addSuccessor(Br->getOperand(0).getMBB());
  105. // Create a new DLS to replace the WLS
  106. MachineInstrBuilder MIB =
  107. BuildMI(*NewBlock, Br, WLS->getDebugLoc(),
  108. TII->get(WLS->getOpcode() == ARM::t2WhileLoopStartTP
  109. ? ARM::t2DoLoopStartTP
  110. : ARM::t2DoLoopStart));
  111. MIB.add(WLS->getOperand(0));
  112. MIB.add(WLS->getOperand(1));
  113. if (WLS->getOpcode() == ARM::t2WhileLoopStartTP)
  114. MIB.add(WLS->getOperand(2));
  115. LLVM_DEBUG(dbgs() << DEBUG_PREFIX
  116. << "Reverting While Loop to Do Loop: " << *WLS << "\n");
  117. RevertWhileLoopStartLR(WLS, TII, ARM::t2Bcc, true);
  118. LivePhysRegs LiveRegs;
  119. computeAndAddLiveIns(LiveRegs, *NewBlock);
  120. Preheader->getParent()->RenumberBlocks();
  121. BBUtils->computeAllBlockSizes();
  122. BBUtils->adjustBBOffsetsAfter(Preheader);
  123. return true;
  124. }
  125. /// Checks if loop has a backwards branching WLS, and if possible, fixes it.
  126. /// This requires checking the predecessor (ie. preheader or it's predecessor)
  127. /// for a WLS and if its loopExit/target is before it.
  128. /// If moving the predecessor won't convert a WLS (to the predecessor) from
  129. /// a forward to a backward branching WLS, then move the predecessor block
  130. /// to before the loopExit/target.
  131. bool ARMBlockPlacement::fixBackwardsWLS(MachineLoop *ML) {
  132. MachineInstr *WlsInstr = findWLS(ML);
  133. if (!WlsInstr)
  134. return false;
  135. MachineBasicBlock *Predecessor = WlsInstr->getParent();
  136. MachineBasicBlock *LoopExit = getWhileLoopStartTargetBB(*WlsInstr);
  137. // We don't want to move Preheader to before the function's entry block.
  138. if (!LoopExit->getPrevNode())
  139. return false;
  140. if (blockIsBefore(Predecessor, LoopExit))
  141. return false;
  142. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Found a backwards WLS from "
  143. << Predecessor->getFullName() << " to "
  144. << LoopExit->getFullName() << "\n");
  145. // Make sure no forward branching WLSs to the Predecessor become backwards
  146. // branching. An example loop structure where the Predecessor can't be moved,
  147. // since bb2's WLS will become forwards once bb3 is moved before/above bb1.
  148. //
  149. // bb1: - LoopExit
  150. // bb2:
  151. // WLS bb3
  152. // bb3: - Predecessor
  153. // WLS bb1
  154. // bb4: - Header
  155. for (auto It = ++LoopExit->getIterator(); It != Predecessor->getIterator();
  156. ++It) {
  157. MachineBasicBlock *MBB = &*It;
  158. for (auto &Terminator : MBB->terminators()) {
  159. if (!isWhileLoopStart(Terminator))
  160. continue;
  161. MachineBasicBlock *WLSTarget = getWhileLoopStartTargetBB(Terminator);
  162. // TODO: Analyse the blocks to make a decision if it would be worth
  163. // moving Preheader even if we'd introduce a backwards WLS
  164. if (WLSTarget == Predecessor) {
  165. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Can't move Predecessor block as "
  166. << "it would convert a WLS from forward to a "
  167. << "backwards branching WLS\n");
  168. RevertedWhileLoops.push_back(WlsInstr);
  169. return false;
  170. }
  171. }
  172. }
  173. moveBasicBlock(Predecessor, LoopExit);
  174. return true;
  175. }
  176. /// Updates ordering (of WLS BB and their loopExits) in inner loops first
  177. /// Returns true if any change was made in any of the loops
  178. bool ARMBlockPlacement::processPostOrderLoops(MachineLoop *ML) {
  179. bool Changed = false;
  180. for (auto *InnerML : *ML)
  181. Changed |= processPostOrderLoops(InnerML);
  182. return Changed | fixBackwardsWLS(ML);
  183. }
  184. bool ARMBlockPlacement::runOnMachineFunction(MachineFunction &MF) {
  185. if (skipFunction(MF.getFunction()))
  186. return false;
  187. const ARMSubtarget &ST = MF.getSubtarget<ARMSubtarget>();
  188. if (!ST.hasLOB())
  189. return false;
  190. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Running on " << MF.getName() << "\n");
  191. MLI = &getAnalysis<MachineLoopInfo>();
  192. TII = static_cast<const ARMBaseInstrInfo *>(ST.getInstrInfo());
  193. BBUtils = std::unique_ptr<ARMBasicBlockUtils>(new ARMBasicBlockUtils(MF));
  194. MF.RenumberBlocks();
  195. BBUtils->computeAllBlockSizes();
  196. BBUtils->adjustBBOffsetsAfter(&MF.front());
  197. bool Changed = false;
  198. RevertedWhileLoops.clear();
  199. // Find loops with a backwards branching WLS and fix if possible.
  200. for (auto *ML : *MLI)
  201. Changed |= processPostOrderLoops(ML);
  202. // Revert any While loops still out of range to DLS loops.
  203. for (auto *WlsInstr : RevertedWhileLoops)
  204. Changed |= revertWhileToDoLoop(WlsInstr);
  205. return Changed;
  206. }
  207. bool ARMBlockPlacement::blockIsBefore(MachineBasicBlock *BB,
  208. MachineBasicBlock *Other) {
  209. return BBUtils->getOffsetOf(Other) > BBUtils->getOffsetOf(BB);
  210. }
  211. // Moves a BasicBlock before another, without changing the control flow
  212. void ARMBlockPlacement::moveBasicBlock(MachineBasicBlock *BB,
  213. MachineBasicBlock *Before) {
  214. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Moving " << BB->getName() << " before "
  215. << Before->getName() << "\n");
  216. MachineBasicBlock *BBPrevious = BB->getPrevNode();
  217. assert(BBPrevious && "Cannot move the function entry basic block");
  218. MachineBasicBlock *BBNext = BB->getNextNode();
  219. MachineBasicBlock *BeforePrev = Before->getPrevNode();
  220. assert(BeforePrev &&
  221. "Cannot move the given block to before the function entry block");
  222. MachineFunction *F = BB->getParent();
  223. BB->moveBefore(Before);
  224. // Since only the blocks are to be moved around (but the control flow must
  225. // not change), if there were any fall-throughs (to/from adjacent blocks),
  226. // replace with unconditional branch to the fall through block.
  227. auto FixFallthrough = [&](MachineBasicBlock *From, MachineBasicBlock *To) {
  228. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Checking for fallthrough from "
  229. << From->getName() << " to " << To->getName() << "\n");
  230. assert(From->isSuccessor(To) &&
  231. "'To' is expected to be a successor of 'From'");
  232. MachineInstr &Terminator = *(--From->terminators().end());
  233. if (!TII->isPredicated(Terminator) &&
  234. (isUncondBranchOpcode(Terminator.getOpcode()) ||
  235. isIndirectBranchOpcode(Terminator.getOpcode()) ||
  236. isJumpTableBranchOpcode(Terminator.getOpcode()) ||
  237. Terminator.isReturn()))
  238. return;
  239. // The BB doesn't have an unconditional branch so it relied on
  240. // fall-through. Fix by adding an unconditional branch to the moved BB.
  241. MachineInstrBuilder MIB =
  242. BuildMI(From, Terminator.getDebugLoc(), TII->get(ARM::t2B));
  243. MIB.addMBB(To);
  244. MIB.addImm(ARMCC::CondCodes::AL);
  245. MIB.addReg(ARM::NoRegister);
  246. LLVM_DEBUG(dbgs() << DEBUG_PREFIX << "Adding unconditional branch from "
  247. << From->getName() << " to " << To->getName() << ": "
  248. << *MIB.getInstr());
  249. };
  250. // Fix fall-through to the moved BB from the one that used to be before it.
  251. if (BBPrevious->isSuccessor(BB))
  252. FixFallthrough(BBPrevious, BB);
  253. // Fix fall through from the destination BB to the one that used to before it.
  254. if (BeforePrev->isSuccessor(Before))
  255. FixFallthrough(BeforePrev, Before);
  256. // Fix fall through from the moved BB to the one that used to follow.
  257. if (BBNext && BB->isSuccessor(BBNext))
  258. FixFallthrough(BB, BBNext);
  259. F->RenumberBlocks();
  260. BBUtils->computeAllBlockSizes();
  261. BBUtils->adjustBBOffsetsAfter(BB);
  262. }