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 #include "loop.h"
17 #include "optimize_common.h"
18
19 // This phase analyses the CFG and identify the loops. The implementation is
20 // based on the idea that, given two basic block a and b, if b is a's pred and
21 // a dominates b, then there is a loop from a to b. Loop identification is done
22 // in a preorder traversal of the dominator tree. In this order, outer loop is
23 // always detected before its nested loop(s). The building of the LoopDesc data
24 // structure takes advantage of this ordering.
25 namespace maplebe {
Dump() const26 void LoopDesc::Dump() const
27 {
28 LogInfo::MapleLogger() << "LoopDesc:" << header.GetId() << ", nest depth:" << nestDepth;
29 if (parentLoop != nullptr) {
30 LogInfo::MapleLogger() << ", parent:" << parentLoop->GetHeader().GetId();
31 }
32 LogInfo::MapleLogger() << "\n\tbackedge:";
33 for (auto bbId : backEdges) {
34 LogInfo::MapleLogger() << bbId << " ";
35 }
36 LogInfo::MapleLogger() << "\n\tmembers:";
37 for (auto bbId : loopBBs) {
38 LogInfo::MapleLogger() << bbId << " ";
39 }
40 LogInfo::MapleLogger() << "\n\texitBB:";
41 for (auto bbId : exitBBs) {
42 LogInfo::MapleLogger() << bbId << " ";
43 }
44 if (!childLoops.empty()) {
45 LogInfo::MapleLogger() << "\n\tchild loops:";
46 for (auto *childLoop : childLoops) {
47 LogInfo::MapleLogger() << childLoop->GetHeader().GetId() << " ";
48 }
49 }
50 LogInfo::MapleLogger() << "\n\n";
51 }
52
GetOrCreateLoopDesc(BB &headBB)53 LoopDesc *LoopAnalysis::GetOrCreateLoopDesc(BB &headBB)
54 {
55 auto *loop = bbLoopParent[headBB.GetId()];
56 if (loop == nullptr || loop->GetHeader().GetId() != headBB.GetId()) {
57 // If the headBB is not in loop or loop's header is not the headBB, create a new loop.
58 loop = alloc.New<LoopDesc>(alloc, headBB);
59 loops.push_back(loop);
60 }
61 return loop;
62 }
63
SetLoopParent4BB(const BB &bb, LoopDesc &loopDesc)64 void LoopAnalysis::SetLoopParent4BB(const BB &bb, LoopDesc &loopDesc)
65 {
66 if (bbLoopParent[bb.GetId()] != nullptr && bbLoopParent[bb.GetId()] != &loopDesc) {
67 if (loopDesc.GetParentLoop() == nullptr) {
68 loopDesc.SetParentLoop(*bbLoopParent[bb.GetId()]);
69 ASSERT_NOT_NULL(loopDesc.GetParentLoop());
70 loopDesc.GetParentLoop()->InsertChildLoops(loopDesc);
71 loopDesc.SetNestDepth(loopDesc.GetParentLoop()->GetNestDepth() + 1);
72 }
73 }
74 loopDesc.InsertLoopBBs(bb);
75 bbLoopParent[bb.GetId()] = &loopDesc;
76 }
77
SetExitBBs(LoopDesc &loop) const78 void LoopAnalysis::SetExitBBs(LoopDesc &loop) const
79 {
80 // if loopBBs succs not in the loop, the succs is the loop's exitBB
81 for (auto bbId : loop.GetLoopBBs()) {
82 auto *bb = cgFunc.GetBBFromID(bbId);
83 for (auto *succ : bb->GetSuccs()) {
84 if (loop.Has(*succ)) {
85 continue;
86 }
87 loop.InsertExitBBs(*succ);
88 }
89 }
90 }
91
GenerateLoop(BB *bb)92 void LoopAnalysis::GenerateLoop(BB *bb)
93 {
94 for (auto *pred : bb->GetPreds()) {
95 if (!dom.Dominate(*bb, *pred)) {
96 continue;
97 }
98 auto *loop = GetOrCreateLoopDesc(*bb);
99 loop->InsertBackEdges(*pred);
100 std::list<BB*> bodyList;
101 bodyList.push_back(pred);
102 while (!bodyList.empty()) {
103 auto *curBB = bodyList.front();
104 bodyList.pop_front();
105 // skip bb or if it has already been dealt with
106 if (curBB == bb || loop->Has(*curBB)) {
107 continue;
108 }
109 SetLoopParent4BB(*curBB, *loop);
110 for (auto *curPred : curBB->GetPreds()) {
111 bodyList.push_back(curPred);
112 }
113 }
114 SetLoopParent4BB(*bb, *loop);
115 SetExitBBs(*loop);
116 }
117 }
118
ProcessBB(BB &entryBB)119 void LoopAnalysis::ProcessBB(BB &entryBB)
120 {
121 std::queue<BB *> allBBs;
122 allBBs.emplace(&entryBB);
123 while (!allBBs.empty()) {
124 BB *bb = allBBs.front();
125 allBBs.pop();
126 if (bb == cgFunc.GetCommonExitBB()) {
127 continue;
128 }
129
130 // generate loop based on the dom information
131 GenerateLoop(bb);
132 // process dom tree
133 for (auto domChildBBId : dom.GetDomChildren(bb->GetId())) {
134 allBBs.emplace(cgFunc.GetBBFromID(domChildBBId));
135 }
136 }
137 }
138
Analysis()139 void LoopAnalysis::Analysis()
140 {
141 std::vector<BB*> entryBBs;
142 FOR_ALL_BB(bb, (&cgFunc))
143 {
144 if (bb->GetPreds().size() == 0) {
145 entryBBs.push_back(bb);
146 }
147 }
148
149 for (auto *bb : entryBBs) {
150 ProcessBB(*bb);
151 }
152 }
153
GetAnalysisDependence(AnalysisDep &aDep) const154 void CgLoopAnalysis::GetAnalysisDependence(AnalysisDep &aDep) const
155 {
156 aDep.AddRequired<CgDomAnalysis>();
157 aDep.SetPreservedAll();
158 }
159
PhaseRun(maplebe::CGFunc &f)160 bool CgLoopAnalysis::PhaseRun(maplebe::CGFunc &f)
161 {
162 auto *domInfo = GET_ANALYSIS(CgDomAnalysis, f);
163 auto *memPool = GetPhaseMemPool();
164 loop = memPool->New<LoopAnalysis>(f, *memPool, *domInfo);
165 loop->Analysis();
166 if (CG_DEBUG_FUNC(f)) {
167 loop->Dump();
168 // do dot gen after detection so the loop backedge can be properly colored using the loop info
169 DotGenerator::GenerateDot("buildloop", f, f.GetMirModule(), f.GetName());
170 }
171 return false;
172 }
173 MAPLE_ANALYSIS_PHASE_REGISTER(CgLoopAnalysis, loopanalysis)
174 } /* namespace maplebe */
175