summaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/include/llvm/CodeGen/LoopTraversal.h
blob: 644c3bdfd71cd636f09b7d1459ec2c2e283808b3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#pragma once 
 
#ifdef __GNUC__ 
#pragma GCC diagnostic push 
#pragma GCC diagnostic ignored "-Wunused-parameter" 
#endif 
 
//==------ llvm/CodeGen/LoopTraversal.h - Loop Traversal -*- C++ -*---------==// 
// 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
// See https://llvm.org/LICENSE.txt for license information. 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
// 
//===----------------------------------------------------------------------===// 
// 
/// \file Loop Traversal logic. 
/// 
/// This class provides the basic blocks traversal order used by passes like 
/// ReachingDefAnalysis and ExecutionDomainFix. 
/// It identifies basic blocks that are part of loops and should to be visited 
/// twice and returns efficient traversal order for all the blocks. 
// 
//===----------------------------------------------------------------------===// 
 
#ifndef LLVM_CODEGEN_LOOPTRAVERSAL_H 
#define LLVM_CODEGEN_LOOPTRAVERSAL_H 
 
#include "llvm/ADT/SmallVector.h" 
 
namespace llvm { 
 
class MachineBasicBlock; 
class MachineFunction; 
 
/// This class provides the basic blocks traversal order used by passes like 
/// ReachingDefAnalysis and ExecutionDomainFix. 
/// It identifies basic blocks that are part of loops and should to be visited 
/// twice and returns efficient traversal order for all the blocks. 
/// 
/// We want to visit every instruction in every basic block in order to update 
/// it's execution domain or collect clearance information. However, for the 
/// clearance calculation, we need to know clearances from all predecessors 
/// (including any backedges), therfore we need to visit some blocks twice. 
/// As an example, consider the following loop. 
/// 
/// 
///    PH -> A -> B (xmm<Undef> -> xmm<Def>) -> C -> D -> EXIT 
///          ^                                  | 
///          +----------------------------------+ 
/// 
/// The iteration order this pass will return is as follows: 
/// Optimized: PH A B C A' B' C' D 
/// 
/// The basic block order is constructed as follows: 
/// Once we finish processing some block, we update the counters in MBBInfos 
/// and re-process any successors that are now 'done'. 
/// We call a block that is ready for its final round of processing `done` 
/// (isBlockDone), e.g. when all predecessor information is known. 
/// 
/// Note that a naive traversal order would be to do two complete passes over 
/// all basic blocks/instructions, the first for recording clearances, the 
/// second for updating clearance based on backedges. 
/// However, for functions without backedges, or functions with a lot of 
/// straight-line code, and a small loop, that would be a lot of unnecessary 
/// work (since only the BBs that are part of the loop require two passes). 
/// 
/// E.g., the naive iteration order for the above exmple is as follows: 
/// Naive: PH A B C D A' B' C' D' 
/// 
/// In the optimized approach we avoid processing D twice, because we 
/// can entirely process the predecessors before getting to D. 
class LoopTraversal { 
private: 
  struct MBBInfo { 
    /// Whether we have gotten to this block in primary processing yet. 
    bool PrimaryCompleted = false; 
 
    /// The number of predecessors for which primary processing has completed 
    unsigned IncomingProcessed = 0; 
 
    /// The value of `IncomingProcessed` at the start of primary processing 
    unsigned PrimaryIncoming = 0; 
 
    /// The number of predecessors for which all processing steps are done. 
    unsigned IncomingCompleted = 0; 
 
    MBBInfo() = default; 
  }; 
  using MBBInfoMap = SmallVector<MBBInfo, 4>; 
  /// Helps keep track if we proccessed this block and all its predecessors. 
  MBBInfoMap MBBInfos; 
 
public: 
  struct TraversedMBBInfo { 
    /// The basic block. 
    MachineBasicBlock *MBB = nullptr; 
 
    /// True if this is the first time we process the basic block. 
    bool PrimaryPass = true; 
 
    /// True if the block that is ready for its final round of processing. 
    bool IsDone = true; 
 
    TraversedMBBInfo(MachineBasicBlock *BB = nullptr, bool Primary = true, 
                     bool Done = true) 
        : MBB(BB), PrimaryPass(Primary), IsDone(Done) {} 
  }; 
  LoopTraversal() {} 
 
  /// Identifies basic blocks that are part of loops and should to be 
  ///  visited twice and returns efficient traversal order for all the blocks. 
  typedef SmallVector<TraversedMBBInfo, 4> TraversalOrder; 
  TraversalOrder traverse(MachineFunction &MF); 
 
private: 
  /// Returens true if the block is ready for its final round of processing. 
  bool isBlockDone(MachineBasicBlock *MBB); 
}; 
 
} // namespace llvm 
 
#endif // LLVM_CODEGEN_LOOPTRAVERSAL_H 
 
#ifdef __GNUC__ 
#pragma GCC diagnostic pop 
#endif