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 Yatsinabool 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 YatsinaLoopTraversal::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