blob: a02d10e09d7d986aec095536b34d0193bb7c95a3 [file] [log] [blame]
Marina Yatsinabe6cfa92018-01-22 10:06:50 +00001//===- LoopTraversal.cpp - Optimal basic block traversal order --*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "llvm/CodeGen/LoopTraversal.h"
11#include "llvm/ADT/PostOrderIterator.h"
12#include "llvm/CodeGen/MachineFunction.h"
13
14using namespace llvm;
15
16bool LoopTraversal::isBlockDone(MachineBasicBlock *MBB) {
Marina Yatsina66bd7d72018-01-22 13:24:10 +000017 unsigned MBBNumber = MBB->getNumber();
Marina Yatsinabe6cfa92018-01-22 10:06:50 +000018 assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
19 return MBBInfos[MBBNumber].PrimaryCompleted &&
20 MBBInfos[MBBNumber].IncomingCompleted ==
21 MBBInfos[MBBNumber].PrimaryIncoming &&
22 MBBInfos[MBBNumber].IncomingProcessed == MBB->pred_size();
23}
24
25LoopTraversal::TraversalOrder LoopTraversal::traverse(MachineFunction &MF) {
26 // Initialize the MMBInfos
27 MBBInfos.assign(MF.getNumBlockIDs(), MBBInfo());
28
29 MachineBasicBlock *Entry = &*MF.begin();
30 ReversePostOrderTraversal<MachineBasicBlock *> RPOT(Entry);
31 SmallVector<MachineBasicBlock *, 4> Workqueue;
32 SmallVector<TraversedMBBInfo, 4> MBBTraversalOrder;
33 for (MachineBasicBlock *MBB : RPOT) {
34 // N.B: IncomingProcessed and IncomingCompleted were already updated while
35 // processing this block's predecessors.
Marina Yatsina66bd7d72018-01-22 13:24:10 +000036 unsigned MBBNumber = MBB->getNumber();
Marina Yatsinabe6cfa92018-01-22 10:06:50 +000037 assert(MBBNumber < MBBInfos.size() && "Unexpected basic block number.");
38 MBBInfos[MBBNumber].PrimaryCompleted = true;
39 MBBInfos[MBBNumber].PrimaryIncoming = MBBInfos[MBBNumber].IncomingProcessed;
40 bool Primary = true;
41 Workqueue.push_back(MBB);
42 while (!Workqueue.empty()) {
43 MachineBasicBlock *ActiveMBB = &*Workqueue.back();
44 Workqueue.pop_back();
45 bool Done = isBlockDone(ActiveMBB);
46 MBBTraversalOrder.push_back(TraversedMBBInfo(ActiveMBB, Primary, Done));
47 for (MachineBasicBlock *Succ : ActiveMBB->successors()) {
Marina Yatsina66bd7d72018-01-22 13:24:10 +000048 unsigned SuccNumber = Succ->getNumber();
Marina Yatsinabe6cfa92018-01-22 10:06:50 +000049 assert(SuccNumber < MBBInfos.size() &&
50 "Unexpected basic block number.");
51 if (!isBlockDone(Succ)) {
52 if (Primary)
53 MBBInfos[SuccNumber].IncomingProcessed++;
54 if (Done)
55 MBBInfos[SuccNumber].IncomingCompleted++;
56 if (isBlockDone(Succ))
57 Workqueue.push_back(Succ);
58 }
59 }
60 Primary = false;
61 }
62 }
63
64 // We need to go through again and finalize any blocks that are not done yet.
65 // This is possible if blocks have dead predecessors, so we didn't visit them
66 // above.
67 for (MachineBasicBlock *MBB : RPOT) {
68 if (!isBlockDone(MBB))
69 MBBTraversalOrder.push_back(TraversedMBBInfo(MBB, false, true));
70 // Don't update successors here. We'll get to them anyway through this
71 // loop.
72 }
73
74 MBBInfos.clear();
75
76 return MBBTraversalOrder;
77}