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 Andricbool 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 AndricLoopTraversal::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