1 /*
2 * Copyright (c) 2023 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 MAPLEBE_INCLUDE_CG_LOOP_H
17 #define MAPLEBE_INCLUDE_CG_LOOP_H
18
19 #include "cgfunc.h"
20 #include "cg_dominance.h"
21 #include "maple_phase.h"
22
23 namespace maplebe {
24 class LoopDesc {
25 public:
26 struct LoopDescCmp {
operatorLoopDescCmp27 bool operator()(const LoopDesc *loop1, const LoopDesc *loop2) const
28 {
29 CHECK_NULL_FATAL(loop1);
30 CHECK_NULL_FATAL(loop2);
31 return (loop1->GetHeader().GetId() < loop2->GetHeader().GetId());
32 }
33 };
34
LoopDesc(MapleAllocator & allocator,BB & head)35 LoopDesc(MapleAllocator &allocator, BB &head)
36 : alloc(allocator),
37 header(head),
38 loopBBs(alloc.Adapter()),
39 exitBBs(alloc.Adapter()),
40 backEdges(alloc.Adapter()),
41 childLoops(alloc.Adapter())
42 {
43 }
44
45 ~LoopDesc() = default;
46
47 void Dump() const;
48
GetHeader()49 BB &GetHeader()
50 {
51 return header;
52 }
53
GetHeader()54 const BB &GetHeader() const
55 {
56 return header;
57 }
58
59 // get all bbIds in the loop
GetLoopBBs()60 const MapleSet<BBID> &GetLoopBBs() const
61 {
62 return loopBBs;
63 }
64
65 // check whether the BB exists in the current loop
Has(const BB & bb)66 bool Has(const BB &bb) const
67 {
68 return loopBBs.find(bb.GetId()) != loopBBs.end();
69 }
70
InsertLoopBBs(const BB & bb)71 void InsertLoopBBs(const BB &bb)
72 {
73 (void)loopBBs.insert(bb.GetId());
74 }
75
GetExitBBs()76 const MapleSet<BBID> &GetExitBBs() const
77 {
78 return exitBBs;
79 }
80
InsertExitBBs(const BB & bb)81 void InsertExitBBs(const BB &bb)
82 {
83 (void)exitBBs.insert(bb.GetId());
84 }
85
InsertBackEdges(const BB & bb)86 void InsertBackEdges(const BB &bb)
87 {
88 (void)backEdges.insert(bb.GetId());
89 }
90
91 // check whether from->to is the back edge of the current loop
IsBackEdge(const BB & from,const BB & to)92 bool IsBackEdge(const BB &from, const BB &to) const
93 {
94 return (to.GetId() == header.GetId()) && (backEdges.find(from.GetId()) != backEdges.end());
95 }
96
97 // get the BBId of all back edges
GetBackEdges()98 const MapleSet<BBID> &GetBackEdges() const
99 {
100 return backEdges;
101 }
102
GetParentLoop()103 const LoopDesc *GetParentLoop() const
104 {
105 return parentLoop;
106 }
107
GetParentLoop()108 LoopDesc *GetParentLoop()
109 {
110 return parentLoop;
111 }
112
SetParentLoop(LoopDesc & loop)113 void SetParentLoop(LoopDesc &loop)
114 {
115 parentLoop = &loop;
116 }
117
GetNestDepth()118 uint32 GetNestDepth() const
119 {
120 return nestDepth;
121 }
122
SetNestDepth(uint32 depth)123 void SetNestDepth(uint32 depth)
124 {
125 nestDepth = depth;
126 }
127
GetChildLoops()128 const MapleSet<LoopDesc*, LoopDescCmp> &GetChildLoops() const
129 {
130 return childLoops;
131 }
132
InsertChildLoops(LoopDesc & loop)133 void InsertChildLoops(LoopDesc &loop)
134 {
135 (void)childLoops.insert(&loop);
136 }
137
138 private:
139 MapleAllocator &alloc;
140 BB &header; // BB's header
141 MapleSet<BBID> loopBBs; // BBs in loop
142 MapleSet<BBID> exitBBs; // loop exit BBs
143 MapleSet<BBID> backEdges; // loop back edges, backBB -> headBB
144 LoopDesc *parentLoop = nullptr; // points to its closest nesting loop
145 uint32 nestDepth = 1; // the nesting depth
146 MapleSet<LoopDesc*, LoopDescCmp> childLoops;
147 };
148
149 class LoopAnalysis : public AnalysisResult {
150 public:
LoopAnalysis(CGFunc & func,MemPool & memPool,DomAnalysis & domInfo)151 LoopAnalysis(CGFunc &func, MemPool &memPool, DomAnalysis &domInfo)
152 : AnalysisResult(&memPool),
153 alloc(&memPool),
154 cgFunc(func),
155 dom(domInfo),
156 loops(alloc.Adapter()),
157 bbLoopParent(cgFunc.GetAllBBSize(), nullptr, alloc.Adapter())
158 {
159 }
160
161 ~LoopAnalysis() override = default;
162
GetLoops()163 const MapleVector<LoopDesc*> &GetLoops() const
164 {
165 return loops;
166 }
167
GetLoops()168 MapleVector<LoopDesc*> &GetLoops()
169 {
170 return loops;
171 }
172
173 // get the loop to which the BB belong, null -> not in loop.
GetBBLoopParent(BBID bbID)174 LoopDesc *GetBBLoopParent(BBID bbID) const
175 {
176 if (bbID >= bbLoopParent.size()) {
177 return nullptr;
178 }
179 return bbLoopParent[bbID];
180 }
181
182 // check whether from->to is the back edge
IsBackEdge(const BB & from,const BB & to)183 bool IsBackEdge(const BB &from, const BB &to) const
184 {
185 auto *loop = GetBBLoopParent(to.GetId());
186 if (loop && loop->IsBackEdge(from, to)) {
187 return true;
188 }
189 loop = GetBBLoopParent(from.GetId());
190 return loop && loop->IsBackEdge(from, to);
191 }
192
193 void Analysis();
194
Dump()195 void Dump() const
196 {
197 LogInfo::MapleLogger() << "Dump LoopAnalysis Result For Func " << cgFunc.GetName() << ":\n";
198 for (const auto *loop : loops) {
199 loop->Dump();
200 }
201 for (BBID bbId = 0; bbId < bbLoopParent.size(); ++bbId) {
202 if (bbLoopParent[bbId] == nullptr) {
203 continue;
204 }
205 LogInfo::MapleLogger() << "BB " << bbId << " in loop " << bbLoopParent[bbId]->GetHeader().GetId() << "\n";
206 }
207 }
208
IsLoopHeaderBB(const BB & bb)209 bool IsLoopHeaderBB(const BB &bb) const
210 {
211 if (GetBBLoopParent(bb.GetId()) == nullptr) {
212 return false;
213 } else if (GetBBLoopParent(bb.GetId())->GetHeader().GetId() == bb.GetId()) {
214 return true;
215 }
216 return false;
217 }
218
219 private:
220 MapleAllocator alloc;
221 CGFunc &cgFunc;
222 DomAnalysis &dom;
223 MapleVector<LoopDesc*> loops; // all loops in func
224 MapleVector<LoopDesc*> bbLoopParent; // gives closest nesting loop for each bb
225
226 LoopDesc *GetOrCreateLoopDesc(BB &headBB);
227 void SetLoopParent4BB(const BB &bb, LoopDesc &loopDesc);
228 void SetExitBBs(LoopDesc &loop) const;
229 void GenerateLoop(BB *bb);
230 void ProcessBB(BB &bb);
231 };
232
233 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgLoopAnalysis, maplebe::CGFunc);
GetResult()234 LoopAnalysis *GetResult()
235 {
236 return loop;
237 }
238 LoopAnalysis *loop = nullptr;
239 OVERRIDE_DEPENDENCE
240 MAPLE_FUNC_PHASE_DECLARE_END
241 } /* namespace maplebe */
242
243 #endif /* MAPLEBE_INCLUDE_CG_LOOP_H */
244