LoopTraversal.cpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. //===- LoopTraversal.cpp - Optimal basic block traversal order --*- C++ -*-===//
  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. #include "llvm/CodeGen/LoopTraversal.h"
  9. #include "llvm/ADT/PostOrderIterator.h"
  10. #include "llvm/CodeGen/MachineFunction.h"
  11. using namespace llvm;
  12. bool LoopTraversal::isBlockDone(MachineBasicBlock *MBB) {
  13. unsigned MBBNumber = MBB->getNumber();
  14. assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
  15. return MBBInfos[MBBNumber].PrimaryCompleted &&
  16. MBBInfos[MBBNumber].IncomingCompleted ==
  17. MBBInfos[MBBNumber].PrimaryIncoming &&
  18. MBBInfos[MBBNumber].IncomingProcessed == MBB->pred_size();
  19. }
  20. LoopTraversal::TraversalOrder LoopTraversal::traverse(MachineFunction &MF) {
  21. // Initialize the MMBInfos
  22. MBBInfos.assign(MF.getNumBlockIDs(), MBBInfo());
  23. MachineBasicBlock *Entry = &*MF.begin();
  24. ReversePostOrderTraversal<MachineBasicBlock *> RPOT(Entry);
  25. SmallVector<MachineBasicBlock *, 4> Workqueue;
  26. SmallVector<TraversedMBBInfo, 4> MBBTraversalOrder;
  27. for (MachineBasicBlock *MBB : RPOT) {
  28. // N.B: IncomingProcessed and IncomingCompleted were already updated while
  29. // processing this block's predecessors.
  30. unsigned MBBNumber = MBB->getNumber();
  31. assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
  32. MBBInfos[MBBNumber].PrimaryCompleted = true;
  33. MBBInfos[MBBNumber].PrimaryIncoming = MBBInfos[MBBNumber].IncomingProcessed;
  34. bool Primary = true;
  35. Workqueue.push_back(MBB);
  36. while (!Workqueue.empty()) {
  37. MachineBasicBlock *ActiveMBB = &*Workqueue.back();
  38. Workqueue.pop_back();
  39. bool Done = isBlockDone(ActiveMBB);
  40. MBBTraversalOrder.push_back(TraversedMBBInfo(ActiveMBB, Primary, Done));
  41. for (MachineBasicBlock *Succ : ActiveMBB->successors()) {
  42. unsigned SuccNumber = Succ->getNumber();
  43. assert(SuccNumber < MBBInfos.size() &&
  44. "Unexpected basic block number.");
  45. if (!isBlockDone(Succ)) {
  46. if (Primary)
  47. MBBInfos[SuccNumber].IncomingProcessed++;
  48. if (Done)
  49. MBBInfos[SuccNumber].IncomingCompleted++;
  50. if (isBlockDone(Succ))
  51. Workqueue.push_back(Succ);
  52. }
  53. }
  54. Primary = false;
  55. }
  56. }
  57. // We need to go through again and finalize any blocks that are not done yet.
  58. // This is possible if blocks have dead predecessors, so we didn't visit them
  59. // above.
  60. for (MachineBasicBlock *MBB : RPOT) {
  61. if (!isBlockDone(MBB))
  62. MBBTraversalOrder.push_back(TraversedMBBInfo(MBB, false, true));
  63. // Don't update successors here. We'll get to them anyway through this
  64. // loop.
  65. }
  66. MBBInfos.clear();
  67. return MBBTraversalOrder;
  68. }