xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/LoopTraversal.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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 Andric bool 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 Andric LoopTraversal::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