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