ARMBlockPlacement.cpp 11 KB

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