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