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