• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef COMPILER_OPTIMIZER_ANALYSIS_LOOP_ANALYZER_H
17 #define COMPILER_OPTIMIZER_ANALYSIS_LOOP_ANALYZER_H
18 
19 #include "optimizer/ir/inst.h"
20 #include "optimizer/pass.h"
21 
22 namespace panda::compiler {
23 class BasicBlock;
24 class Graph;
25 
26 class Loop final {
27 public:
Loop(ArenaAllocator * allocator,BasicBlock * header,uint32_t id)28     Loop(ArenaAllocator *allocator, BasicBlock *header, uint32_t id)
29         : header_(header),
30           back_edges_(allocator->Adapter()),
31           blocks_(allocator->Adapter()),
32           inner_loops_(allocator->Adapter()),
33           id_(id)
34     {
35     }
36 
37     DEFAULT_MOVE_SEMANTIC(Loop);
38     DEFAULT_COPY_SEMANTIC(Loop);
39     ~Loop() = default;
40 
41     bool operator==(const Loop &other) const
42     {
43         return std::tie(header_, pre_header_, is_irreducible_, is_root_, is_infinite_) ==
44                    std::tie(other.header_, other.pre_header_, other.is_irreducible_, other.is_root_,
45                             other.is_infinite_) &&
46                IsEqualBlocks(blocks_, other.blocks_) && IsEqualBlocks(back_edges_, other.back_edges_);
47     }
48 
GetHeader()49     BasicBlock *GetHeader() const
50     {
51         return header_;
52     }
SetPreHeader(BasicBlock * pre_header)53     void SetPreHeader(BasicBlock *pre_header)
54     {
55         pre_header_ = pre_header;
56     }
57 
GetPreHeader()58     BasicBlock *GetPreHeader() const
59     {
60         return pre_header_;
61     }
AppendBackEdge(BasicBlock * block)62     void AppendBackEdge(BasicBlock *block)
63     {
64         ASSERT(std::find(back_edges_.begin(), back_edges_.end(), block) == back_edges_.end());
65         back_edges_.push_back(block);
66     }
67 
ReplaceBackEdge(BasicBlock * block,BasicBlock * new_block)68     void ReplaceBackEdge(BasicBlock *block, BasicBlock *new_block)
69     {
70         ASSERT(block != new_block);
71         ASSERT(std::find(back_edges_.begin(), back_edges_.end(), new_block) == back_edges_.end());
72         auto it = std::find(back_edges_.begin(), back_edges_.end(), block);
73         ASSERT(it != back_edges_.end());
74         ASSERT(std::find(it + 1, back_edges_.end(), block) == back_edges_.end());
75         back_edges_[std::distance(back_edges_.begin(), it)] = new_block;
76     }
77 
HasBackEdge(BasicBlock * block)78     bool HasBackEdge(BasicBlock *block) const
79     {
80         auto it = std::find(back_edges_.begin(), back_edges_.end(), block);
81         return it != back_edges_.end();
82     }
83 
RemoveBackEdge(BasicBlock * block)84     void RemoveBackEdge(BasicBlock *block)
85     {
86         auto it = std::find(back_edges_.begin(), back_edges_.end(), block);
87         ASSERT(it != back_edges_.end());
88         ASSERT(std::find(it + 1, back_edges_.end(), block) == back_edges_.end());
89         back_edges_[std::distance(back_edges_.begin(), it)] = back_edges_.back();
90         back_edges_.pop_back();
91     }
92 
93     void MoveHeaderToSucc();
94 
GetBackEdges()95     const ArenaVector<BasicBlock *> &GetBackEdges() const
96     {
97         return back_edges_;
98     }
99 
100     void AppendBlock(BasicBlock *block);
101 
102     // NB! please use carefully, ensure that the block
103     // 1. is not a header of the loop
104     // 2. is not a back-edge of the loop
105     // 3. is not a pre-header of any inner loop
106     void RemoveBlock(BasicBlock *block);
107 
GetBlocks()108     ArenaVector<BasicBlock *> &GetBlocks()
109     {
110         return blocks_;
111     }
GetBlocks()112     const ArenaVector<BasicBlock *> &GetBlocks() const
113     {
114         return blocks_;
115     }
AppendInnerLoop(Loop * inner_loop)116     void AppendInnerLoop(Loop *inner_loop)
117     {
118         inner_loops_.push_back(inner_loop);
119     }
GetInnerLoops()120     ArenaVector<Loop *> &GetInnerLoops()
121     {
122         return inner_loops_;
123     }
GetInnerLoops()124     const ArenaVector<Loop *> &GetInnerLoops() const
125     {
126         return inner_loops_;
127     }
SetOuterLoop(Loop * outer_loop)128     void SetOuterLoop(Loop *outer_loop)
129     {
130         outer_loop_ = outer_loop;
131     }
GetOuterLoop()132     Loop *GetOuterLoop() const
133     {
134         return outer_loop_;
135     }
SetIsIrreducible(bool is_irreducible)136     void SetIsIrreducible(bool is_irreducible)
137     {
138         is_irreducible_ = is_irreducible;
139     }
IsIrreducible()140     bool IsIrreducible() const
141     {
142         return is_irreducible_;
143     }
IsInfinite()144     bool IsInfinite() const
145     {
146         return is_infinite_;
147     }
SetIsInfinite(bool is_infinite)148     void SetIsInfinite(bool is_infinite)
149     {
150         is_infinite_ = is_infinite;
151     }
SetAsRoot()152     void SetAsRoot()
153     {
154         is_root_ = true;
155     }
IsRoot()156     bool IsRoot() const
157     {
158         return is_root_;
159     }
GetId()160     uint32_t GetId() const
161     {
162         return id_;
163     }
164 
165     bool IsOsrLoop() const;
166 
167     bool IsTryCatchLoop() const;
168 
169     bool IsInside(Loop *other);
170 
171 private:
172     void CheckInfinity();
173 
174     template <typename T>
IsEqualBlocks(const ArenaVector<T> & blocks,const ArenaVector<T> & others)175     static inline bool IsEqualBlocks(const ArenaVector<T> &blocks, const ArenaVector<T> &others)
176     {
177         return blocks.size() == others.size() && std::is_permutation(blocks.begin(), blocks.end(), others.begin());
178     }
179 
180 private:
181     BasicBlock *header_ {nullptr};
182     BasicBlock *pre_header_ {nullptr};
183     ArenaVector<BasicBlock *> back_edges_;
184     ArenaVector<BasicBlock *> blocks_;
185     ArenaVector<Loop *> inner_loops_;
186     Loop *outer_loop_ {nullptr};
187     bool is_irreducible_ {false};
188     bool is_infinite_ {false};
189     bool is_root_ {false};
190     uint32_t id_ {INVALID_ID};
191 
192     friend class LoopAnalyzer;
193 };
194 
195 class LoopAnalyzer final : public Analysis {
196 public:
197     using Analysis::Analysis;
198 
199     bool RunImpl() override;
200 
GetPassName()201     const char *GetPassName() const override
202     {
203         return "LoopAnalysis";
204     }
205 
206     void CreateRootLoop();
207     Loop *CreateNewLoop(BasicBlock *loop_header);
208 
209 private:
210     void ResetLoopInfo();
211     void CollectBackEdges();
212     void BackEdgeSearch(BasicBlock *block);
213     void ProcessNewBackEdge(BasicBlock *header, BasicBlock *back_edge);
214     void FindAndInsertPreHeaders(Loop *loop);
215     void MovePhiInputsToPreHeader(BasicBlock *header, BasicBlock *pre_header, const ArenaVector<int> &fw_edges_indexes);
216     void UpdateControlFlowWithPreHeader(BasicBlock *header, BasicBlock *pre_header,
217                                         const ArenaVector<int> &fw_edges_indexes);
218     ArenaVector<int> GetForwardEdgesIndexes(BasicBlock *header);
219     bool PreHeaderExists(Loop *loop);
220     BasicBlock *CreatePreHeader(BasicBlock *header);
221     void PopulateLoops();
222     void NaturalLoopSearch(Loop *loop, BasicBlock *block);
223     void SearchInfiniteLoops(Loop *loop);
224 
225 private:
226     Marker black_marker_ {};
227     Marker gray_marker_ {};
228     uint32_t loop_counter_ {0};
229 };
230 
231 BasicBlock *GetLoopOutsideSuccessor(Loop *loop);
232 // NOLINTNEXTLINE(readability-redundant-declaration)
233 bool IsLoopSingleBackEdgeExitPoint(Loop *loop);
234 
235 }  // namespace panda::compiler
236 
237 #endif  // COMPILER_OPTIMIZER_ANALYSIS_LOOP_ANALYZER_H
238