xref: /llvm-project/llvm/lib/CodeGen/LoopTraversal.cpp (revision 84b07c9b3aa79e073a97290bdd30d98b1941a536)
10bf841acSMarina Yatsina //===- LoopTraversal.cpp - Optimal basic block traversal order --*- C++ -*-===//
20bf841acSMarina Yatsina //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60bf841acSMarina Yatsina //
70bf841acSMarina Yatsina //===----------------------------------------------------------------------===//
80bf841acSMarina Yatsina 
90bf841acSMarina Yatsina #include "llvm/CodeGen/LoopTraversal.h"
100bf841acSMarina Yatsina #include "llvm/ADT/PostOrderIterator.h"
110bf841acSMarina Yatsina #include "llvm/CodeGen/MachineFunction.h"
120bf841acSMarina Yatsina 
130bf841acSMarina Yatsina using namespace llvm;
140bf841acSMarina Yatsina 
isBlockDone(MachineBasicBlock * MBB)150bf841acSMarina Yatsina bool LoopTraversal::isBlockDone(MachineBasicBlock *MBB) {
16e4d63a49SMarina Yatsina   unsigned MBBNumber = MBB->getNumber();
170bf841acSMarina Yatsina   assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
180bf841acSMarina Yatsina   return MBBInfos[MBBNumber].PrimaryCompleted &&
190bf841acSMarina Yatsina          MBBInfos[MBBNumber].IncomingCompleted ==
200bf841acSMarina Yatsina              MBBInfos[MBBNumber].PrimaryIncoming &&
210bf841acSMarina Yatsina          MBBInfos[MBBNumber].IncomingProcessed == MBB->pred_size();
220bf841acSMarina Yatsina }
230bf841acSMarina Yatsina 
traverse(MachineFunction & MF)240bf841acSMarina Yatsina LoopTraversal::TraversalOrder LoopTraversal::traverse(MachineFunction &MF) {
250bf841acSMarina Yatsina   // Initialize the MMBInfos
260bf841acSMarina Yatsina   MBBInfos.assign(MF.getNumBlockIDs(), MBBInfo());
270bf841acSMarina Yatsina 
280bf841acSMarina Yatsina   MachineBasicBlock *Entry = &*MF.begin();
290bf841acSMarina Yatsina   ReversePostOrderTraversal<MachineBasicBlock *> RPOT(Entry);
300bf841acSMarina Yatsina   SmallVector<MachineBasicBlock *, 4> Workqueue;
310bf841acSMarina Yatsina   SmallVector<TraversedMBBInfo, 4> MBBTraversalOrder;
320bf841acSMarina Yatsina   for (MachineBasicBlock *MBB : RPOT) {
330bf841acSMarina Yatsina     // N.B: IncomingProcessed and IncomingCompleted were already updated while
340bf841acSMarina Yatsina     // processing this block's predecessors.
35e4d63a49SMarina Yatsina     unsigned MBBNumber = MBB->getNumber();
360bf841acSMarina Yatsina     assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
370bf841acSMarina Yatsina     MBBInfos[MBBNumber].PrimaryCompleted = true;
380bf841acSMarina Yatsina     MBBInfos[MBBNumber].PrimaryIncoming = MBBInfos[MBBNumber].IncomingProcessed;
390bf841acSMarina Yatsina     bool Primary = true;
400bf841acSMarina Yatsina     Workqueue.push_back(MBB);
410bf841acSMarina Yatsina     while (!Workqueue.empty()) {
42*84b07c9bSKazu Hirata       MachineBasicBlock *ActiveMBB = Workqueue.pop_back_val();
430bf841acSMarina Yatsina       bool Done = isBlockDone(ActiveMBB);
440bf841acSMarina Yatsina       MBBTraversalOrder.push_back(TraversedMBBInfo(ActiveMBB, Primary, Done));
450bf841acSMarina Yatsina       for (MachineBasicBlock *Succ : ActiveMBB->successors()) {
46e4d63a49SMarina Yatsina         unsigned SuccNumber = Succ->getNumber();
470bf841acSMarina Yatsina         assert(SuccNumber < MBBInfos.size() &&
480bf841acSMarina Yatsina                "Unexpected basic block number.");
490bf841acSMarina Yatsina         if (!isBlockDone(Succ)) {
500bf841acSMarina Yatsina           if (Primary)
510bf841acSMarina Yatsina             MBBInfos[SuccNumber].IncomingProcessed++;
520bf841acSMarina Yatsina           if (Done)
530bf841acSMarina Yatsina             MBBInfos[SuccNumber].IncomingCompleted++;
540bf841acSMarina Yatsina           if (isBlockDone(Succ))
550bf841acSMarina Yatsina             Workqueue.push_back(Succ);
560bf841acSMarina Yatsina         }
570bf841acSMarina Yatsina       }
580bf841acSMarina Yatsina       Primary = false;
590bf841acSMarina Yatsina     }
600bf841acSMarina Yatsina   }
610bf841acSMarina Yatsina 
620bf841acSMarina Yatsina   // We need to go through again and finalize any blocks that are not done yet.
630bf841acSMarina Yatsina   // This is possible if blocks have dead predecessors, so we didn't visit them
640bf841acSMarina Yatsina   // above.
650bf841acSMarina Yatsina   for (MachineBasicBlock *MBB : RPOT) {
660bf841acSMarina Yatsina     if (!isBlockDone(MBB))
670bf841acSMarina Yatsina       MBBTraversalOrder.push_back(TraversedMBBInfo(MBB, false, true));
680bf841acSMarina Yatsina     // Don't update successors here. We'll get to them anyway through this
690bf841acSMarina Yatsina     // loop.
700bf841acSMarina Yatsina   }
710bf841acSMarina Yatsina 
720bf841acSMarina Yatsina   MBBInfos.clear();
730bf841acSMarina Yatsina 
740bf841acSMarina Yatsina   return MBBTraversalOrder;
750bf841acSMarina Yatsina }
76