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