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