10bf841acSMarina Yatsina //===- LoopTraversal.cpp - Optimal basic block traversal order --*- C++ -*-===//
20bf841acSMarina Yatsina //
30bf841acSMarina Yatsina //                     The LLVM Compiler Infrastructure
40bf841acSMarina Yatsina //
50bf841acSMarina Yatsina // This file is distributed under the University of Illinois Open Source
60bf841acSMarina Yatsina // License. See LICENSE.TXT for details.
70bf841acSMarina Yatsina //
80bf841acSMarina Yatsina //===----------------------------------------------------------------------===//
90bf841acSMarina Yatsina 
100bf841acSMarina Yatsina #include "llvm/CodeGen/LoopTraversal.h"
110bf841acSMarina Yatsina #include "llvm/ADT/PostOrderIterator.h"
120bf841acSMarina Yatsina #include "llvm/CodeGen/MachineFunction.h"
130bf841acSMarina Yatsina 
140bf841acSMarina Yatsina using namespace llvm;
150bf841acSMarina Yatsina 
160bf841acSMarina Yatsina bool LoopTraversal::isBlockDone(MachineBasicBlock *MBB) {
17*e4d63a49SMarina Yatsina   unsigned MBBNumber = MBB->getNumber();
180bf841acSMarina Yatsina   assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
190bf841acSMarina Yatsina   return MBBInfos[MBBNumber].PrimaryCompleted &&
200bf841acSMarina Yatsina          MBBInfos[MBBNumber].IncomingCompleted ==
210bf841acSMarina Yatsina              MBBInfos[MBBNumber].PrimaryIncoming &&
220bf841acSMarina Yatsina          MBBInfos[MBBNumber].IncomingProcessed == MBB->pred_size();
230bf841acSMarina Yatsina }
240bf841acSMarina Yatsina 
250bf841acSMarina Yatsina LoopTraversal::TraversalOrder LoopTraversal::traverse(MachineFunction &MF) {
260bf841acSMarina Yatsina   // Initialize the MMBInfos
270bf841acSMarina Yatsina   MBBInfos.assign(MF.getNumBlockIDs(), MBBInfo());
280bf841acSMarina Yatsina 
290bf841acSMarina Yatsina   MachineBasicBlock *Entry = &*MF.begin();
300bf841acSMarina Yatsina   ReversePostOrderTraversal<MachineBasicBlock *> RPOT(Entry);
310bf841acSMarina Yatsina   SmallVector<MachineBasicBlock *, 4> Workqueue;
320bf841acSMarina Yatsina   SmallVector<TraversedMBBInfo, 4> MBBTraversalOrder;
330bf841acSMarina Yatsina   for (MachineBasicBlock *MBB : RPOT) {
340bf841acSMarina Yatsina     // N.B: IncomingProcessed and IncomingCompleted were already updated while
350bf841acSMarina Yatsina     // processing this block's predecessors.
36*e4d63a49SMarina Yatsina     unsigned MBBNumber = MBB->getNumber();
370bf841acSMarina Yatsina     assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
380bf841acSMarina Yatsina     MBBInfos[MBBNumber].PrimaryCompleted = true;
390bf841acSMarina Yatsina     MBBInfos[MBBNumber].PrimaryIncoming = MBBInfos[MBBNumber].IncomingProcessed;
400bf841acSMarina Yatsina     bool Primary = true;
410bf841acSMarina Yatsina     Workqueue.push_back(MBB);
420bf841acSMarina Yatsina     while (!Workqueue.empty()) {
430bf841acSMarina Yatsina       MachineBasicBlock *ActiveMBB = &*Workqueue.back();
440bf841acSMarina Yatsina       Workqueue.pop_back();
450bf841acSMarina Yatsina       bool Done = isBlockDone(ActiveMBB);
460bf841acSMarina Yatsina       MBBTraversalOrder.push_back(TraversedMBBInfo(ActiveMBB, Primary, Done));
470bf841acSMarina Yatsina       for (MachineBasicBlock *Succ : ActiveMBB->successors()) {
48*e4d63a49SMarina Yatsina         unsigned SuccNumber = Succ->getNumber();
490bf841acSMarina Yatsina         assert(SuccNumber < MBBInfos.size() &&
500bf841acSMarina Yatsina                "Unexpected basic block number.");
510bf841acSMarina Yatsina         if (!isBlockDone(Succ)) {
520bf841acSMarina Yatsina           if (Primary)
530bf841acSMarina Yatsina             MBBInfos[SuccNumber].IncomingProcessed++;
540bf841acSMarina Yatsina           if (Done)
550bf841acSMarina Yatsina             MBBInfos[SuccNumber].IncomingCompleted++;
560bf841acSMarina Yatsina           if (isBlockDone(Succ))
570bf841acSMarina Yatsina             Workqueue.push_back(Succ);
580bf841acSMarina Yatsina         }
590bf841acSMarina Yatsina       }
600bf841acSMarina Yatsina       Primary = false;
610bf841acSMarina Yatsina     }
620bf841acSMarina Yatsina   }
630bf841acSMarina Yatsina 
640bf841acSMarina Yatsina   // We need to go through again and finalize any blocks that are not done yet.
650bf841acSMarina Yatsina   // This is possible if blocks have dead predecessors, so we didn't visit them
660bf841acSMarina Yatsina   // above.
670bf841acSMarina Yatsina   for (MachineBasicBlock *MBB : RPOT) {
680bf841acSMarina Yatsina     if (!isBlockDone(MBB))
690bf841acSMarina Yatsina       MBBTraversalOrder.push_back(TraversedMBBInfo(MBB, false, true));
700bf841acSMarina Yatsina     // Don't update successors here. We'll get to them anyway through this
710bf841acSMarina Yatsina     // loop.
720bf841acSMarina Yatsina   }
730bf841acSMarina Yatsina 
740bf841acSMarina Yatsina   MBBInfos.clear();
750bf841acSMarina Yatsina 
760bf841acSMarina Yatsina   return MBBTraversalOrder;
770bf841acSMarina Yatsina }
78