• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "cg_dominance.h"
17 #include <set>
18 #include "cg_option.h"
19 #include "cgfunc.h"
20 
21 /*
22  * This phase build dominance
23  */
24 namespace maplebe {
25 constexpr uint32 kBBVectorInitialSize = 2;
PostOrderWalk(const BB & bb,int32 & pid,MapleVector<bool> & visitedMap)26 void DomAnalysis::PostOrderWalk(const BB &bb, int32 &pid, MapleVector<bool> &visitedMap)
27 {
28     DEBUG_ASSERT(bb.GetId() < visitedMap.size(), "index out of range in Dominance::PostOrderWalk");
29     if (visitedMap[bb.GetId()]) {
30         return;
31     }
32     visitedMap[bb.GetId()] = true;
33     for (const BB *suc : bb.GetSuccs()) {
34         PostOrderWalk(*suc, pid, visitedMap);
35     }
36     DEBUG_ASSERT(bb.GetId() < postOrderIDVec.size(), "index out of range in Dominance::PostOrderWalk");
37     postOrderIDVec[bb.GetId()] = pid++;
38 }
39 
GenPostOrderID()40 void DomAnalysis::GenPostOrderID()
41 {
42     DEBUG_ASSERT(!bbVec.empty(), "size to be allocated is 0");
43     MapleVector<bool> visitedMap(bbVec.size() + 1, false, cgFunc.GetFuncScopeAllocator()->Adapter());
44     int32 postOrderID = 0;
45     PostOrderWalk(commonEntryBB, postOrderID, visitedMap);
46     // initialize reversePostOrder
47     int32 maxPostOrderID = postOrderID - 1;
48     reversePostOrder.resize(static_cast<uint32>(maxPostOrderID + 1));
49     for (size_t i = 0; i < postOrderIDVec.size(); ++i) {
50         int32 postOrderNo = postOrderIDVec[i];
51         if (postOrderNo == -1) {
52             continue;
53         }
54         reversePostOrder[static_cast<uint32>(maxPostOrderID - postOrderNo)] = bbVec[i];
55     }
56 }
57 
Intersect(BB & bb1,const BB & bb2)58 BB *DomAnalysis::Intersect(BB &bb1, const BB &bb2)
59 {
60     auto *ptrBB1 = &bb1;
61     auto *ptrBB2 = &bb2;
62     while (ptrBB1 != ptrBB2) {
63         while (postOrderIDVec[ptrBB1->GetId()] < postOrderIDVec[ptrBB2->GetId()]) {
64             ptrBB1 = GetDom(ptrBB1->GetId());
65         }
66         while (postOrderIDVec[ptrBB2->GetId()] < postOrderIDVec[ptrBB1->GetId()]) {
67             ptrBB2 = GetDom(ptrBB2->GetId());
68         }
69     }
70     return ptrBB1;
71 }
72 
CommonEntryBBIsPred(const BB & bb) const73 bool DominanceBase::CommonEntryBBIsPred(const BB &bb) const
74 {
75     for (const BB *suc : commonEntryBB.GetSuccs()) {
76         if (suc == &bb) {
77             return true;
78         }
79     }
80     return false;
81 }
82 
83 // Figure 3 in "A Simple, Fast Dominance Algorithm" by Keith Cooper et al.
ComputeDominance()84 void DomAnalysis::ComputeDominance()
85 {
86     SetDom(commonEntryBB.GetId(), &commonEntryBB);
87     bool changed;
88     do {
89         changed = false;
90         for (size_t i = 1; i < reversePostOrder.size(); ++i) {
91             BB *bb = reversePostOrder[i];
92             if (bb == nullptr) {
93                 continue;
94             }
95             BB *pre = nullptr;
96             auto it = bb->GetPredsBegin();
97             if (CommonEntryBBIsPred(*bb) || bb->GetPreds().empty()) {
98                 pre = &commonEntryBB;
99             } else {
100                 pre = *it;
101             }
102             ++it;
103             while ((GetDom(pre->GetId()) == nullptr || pre == bb) && it != bb->GetPredsEnd()) {
104                 pre = *it;
105                 ++it;
106             }
107             BB *newIDom = pre;
108             for (; it != bb->GetPredsEnd(); ++it) {
109                 pre = *it;
110                 if (GetDom(pre->GetId()) != nullptr && pre != bb) {
111                     newIDom = Intersect(*pre, *newIDom);
112                 }
113             }
114             if (GetDom(bb->GetId()) != newIDom) {
115                 SetDom(bb->GetId(), newIDom);
116                 changed = true;
117             }
118         }
119     } while (changed);
120 }
121 
122 // Figure 5 in "A Simple, Fast Dominance Algorithm" by Keith Cooper et al.
ComputeDomFrontiers()123 void DomAnalysis::ComputeDomFrontiers()
124 {
125     for (const BB *bb : bbVec) {
126         if (bb == nullptr || bb == &commonExitBB) {
127             continue;
128         }
129         if (bb->GetPreds().size() < kBBVectorInitialSize) {
130             continue;
131         }
132         for (BB *pre : bb->GetPreds()) {
133             BB *runner = pre;
134             while (runner != nullptr && runner != GetDom(bb->GetId()) && runner != &commonEntryBB) {
135                 if (!HasDomFrontier(runner->GetId(), bb->GetId())) {
136                     domFrontier[runner->GetId()].push_back(bb->GetId());
137                 }
138                 runner = GetDom(runner->GetId());
139             }
140         }
141     }
142     // check entry bb's predBB, such as :
143     // bb1 is commonEntryBB, bb2 is entryBB, bb2 is domFrontier of bb3 and bb7.
144     //       1
145     //       |
146     //       2 <-
147     //      /   |
148     //     3    |
149     //    / \   |
150     //   4   7---
151     //  / \  ^
152     // |   | |
153     // 5-->6--
154     for (BB *succ : commonEntryBB.GetSuccs()) {
155         if (succ->GetPreds().size() != 1) {  // Only deal with one pred bb.
156             continue;
157         }
158         for (BB *pre : succ->GetPreds()) {
159             BB *runner = pre;
160             while (runner != GetDom(succ->GetId()) && runner != &commonEntryBB && runner != succ) {
161                 if (!HasDomFrontier(runner->GetId(), succ->GetId())) {
162                     domFrontier[runner->GetId()].push_back(succ->GetId());
163                 }
164                 runner = GetDom(runner->GetId());
165             }
166         }
167     }
168 }
169 
ComputeDomChildren()170 void DomAnalysis::ComputeDomChildren()
171 {
172     for (auto *bb : reversePostOrder) {
173         if (bb == nullptr || GetDom(bb->GetId()) == nullptr) {
174             continue;
175         }
176         BB *parent = GetDom(bb->GetId());
177         if (parent == bb) {
178             continue;
179         }
180         domChildren[parent->GetId()].push_back(bb->GetId());
181     }
182 }
183 
184 // bbidMarker indicates that the iterDomFrontier results for bbid < bbidMarker
185 // have been computed
GetIterDomFrontier(const BB * bb,MapleSet<uint32> * dfset,uint32 bbidMarker,std::vector<bool> & visitedMap)186 void DomAnalysis::GetIterDomFrontier(const BB *bb, MapleSet<uint32> *dfset, uint32 bbidMarker,
187                                      std::vector<bool> &visitedMap)
188 {
189     if (visitedMap[bb->GetId()]) {
190         return;
191     }
192     visitedMap[bb->GetId()] = true;
193     for (uint32 frontierbbid : domFrontier[bb->GetId()]) {
194         (void)dfset->insert(frontierbbid);
195         if (frontierbbid < bbidMarker) {  // union with its computed result
196             dfset->insert(iterDomFrontier[frontierbbid].begin(), iterDomFrontier[frontierbbid].end());
197         } else {  // recursive call
198             BB *frontierbb = bbVec[frontierbbid];
199             GetIterDomFrontier(frontierbb, dfset, bbidMarker, visitedMap);
200         }
201     }
202 }
203 
ComputeIterDomFrontiers()204 void DomAnalysis::ComputeIterDomFrontiers()
205 {
206     for (BB *bb : bbVec) {
207         if (bb == nullptr || bb == &commonExitBB) {
208             continue;
209         }
210         std::vector<bool> visitedMap(bbVec.size(), false);
211         GetIterDomFrontier(bb, &iterDomFrontier[bb->GetId()], bb->GetId(), visitedMap);
212     }
213 }
214 
ComputeDtPreorder(const BB & bb,uint32 & num)215 uint32 DomAnalysis::ComputeDtPreorder(const BB &bb, uint32 &num)
216 {
217     DEBUG_ASSERT(num < dtPreOrder.size(), "index out of range in Dominance::ComputeDtPreorder");
218     dtPreOrder[num] = bb.GetId();
219     dtDfn[bb.GetId()] = num;
220     uint32 maxDtDfnOut = num;
221     ++num;
222 
223     for (uint32 k : domChildren[bb.GetId()]) {
224         maxDtDfnOut = ComputeDtPreorder(*bbVec[k], num);
225     }
226 
227     dtDfnOut[bb.GetId()] = maxDtDfnOut;
228     return maxDtDfnOut;
229 }
230 
231 // true if b1 dominates b2
Dominate(const BB & bb1,const BB & bb2)232 bool DomAnalysis::Dominate(const BB &bb1, const BB &bb2)
233 {
234     return dtDfn[bb1.GetId()] <= dtDfn[bb2.GetId()] && dtDfnOut[bb1.GetId()] >= dtDfnOut[bb2.GetId()];
235 }
236 
Compute()237 void DomAnalysis::Compute()
238 {
239     GenPostOrderID();
240     ComputeDominance();
241     ComputeDomFrontiers();
242     ComputeDomChildren();
243     ComputeIterDomFrontiers();
244     uint32 num = 0;
245     (void)ComputeDtPreorder(*cgFunc.GetFirstBB(), num);
246     GetDtPreOrder().resize(num);
247 }
248 
Dump()249 void DomAnalysis::Dump()
250 {
251     for (BB *bb : reversePostOrder) {
252         LogInfo::MapleLogger() << "postorder no " << postOrderIDVec[bb->GetId()];
253         LogInfo::MapleLogger() << " is bb:" << bb->GetId();
254         LogInfo::MapleLogger() << " im_dom is bb:" << GetDom(bb->GetId())->GetId();
255         LogInfo::MapleLogger() << " domfrontier: [";
256         for (uint32 id : domFrontier[bb->GetId()]) {
257             LogInfo::MapleLogger() << id << " ";
258         }
259         LogInfo::MapleLogger() << "] domchildren: [";
260         for (uint32 id : domChildren[bb->GetId()]) {
261             LogInfo::MapleLogger() << id << " ";
262         }
263         LogInfo::MapleLogger() << "]\n";
264     }
265     LogInfo::MapleLogger() << "\npreorder traversal of dominator tree:";
266     for (uint32 id : dtPreOrder) {
267         LogInfo::MapleLogger() << id << " ";
268     }
269     LogInfo::MapleLogger() << "\n\n";
270 }
271 
272 /* ================= for PostDominance ================= */
PdomPostOrderWalk(const BB & bb,int32 & pid,MapleVector<bool> & visitedMap)273 void PostDomAnalysis::PdomPostOrderWalk(const BB &bb, int32 &pid, MapleVector<bool> &visitedMap)
274 {
275     DEBUG_ASSERT(bb.GetId() < visitedMap.size(), "index out of range in  Dominance::PdomPostOrderWalk");
276     if (bbVec[bb.GetId()] == nullptr) {
277         return;
278     }
279     if (visitedMap[bb.GetId()]) {
280         return;
281     }
282     visitedMap[bb.GetId()] = true;
283     for (BB *pre : bb.GetPreds()) {
284         PdomPostOrderWalk(*pre, pid, visitedMap);
285     }
286     DEBUG_ASSERT(bb.GetId() < pdomPostOrderIDVec.size(), "index out of range in  Dominance::PdomPostOrderWalk");
287     pdomPostOrderIDVec[bb.GetId()] = pid++;
288 }
289 
PdomGenPostOrderID()290 void PostDomAnalysis::PdomGenPostOrderID()
291 {
292     DEBUG_ASSERT(!bbVec.empty(), "call calloc failed in Dominance::PdomGenPostOrderID");
293     MapleVector<bool> visitedMap(bbVec.size(), false, cgFunc.GetFuncScopeAllocator()->Adapter());
294     int32 postOrderID = 0;
295     PdomPostOrderWalk(commonExitBB, postOrderID, visitedMap);
296     // initialize pdomReversePostOrder
297     int32 maxPostOrderID = postOrderID - 1;
298     pdomReversePostOrder.resize(static_cast<uint32>(maxPostOrderID + 1));
299     for (size_t i = 0; i < pdomPostOrderIDVec.size(); ++i) {
300         int32 postOrderNo = pdomPostOrderIDVec[i];
301         if (postOrderNo == -1) {
302             continue;
303         }
304         pdomReversePostOrder[static_cast<uint32>(maxPostOrderID - postOrderNo)] = bbVec[i];
305     }
306 }
307 
PdomIntersect(BB & bb1,const BB & bb2)308 BB *PostDomAnalysis::PdomIntersect(BB &bb1, const BB &bb2)
309 {
310     auto *ptrBB1 = &bb1;
311     auto *ptrBB2 = &bb2;
312     while (ptrBB1 != ptrBB2) {
313         while (pdomPostOrderIDVec[ptrBB1->GetId()] < pdomPostOrderIDVec[ptrBB2->GetId()]) {
314             ptrBB1 = GetPdom(ptrBB1->GetId());
315         }
316         while (pdomPostOrderIDVec[ptrBB2->GetId()] < pdomPostOrderIDVec[ptrBB1->GetId()]) {
317             ptrBB2 = GetPdom(ptrBB2->GetId());
318         }
319     }
320     return ptrBB1;
321 }
322 
323 // Figure 3 in "A Simple, Fast Dominance Algorithm" by Keith Cooper et al.
ComputePostDominance()324 void PostDomAnalysis::ComputePostDominance()
325 {
326     SetPdom(commonExitBB.GetId(), &commonExitBB);
327     bool changed = false;
328     do {
329         changed = false;
330         for (size_t i = 1; i < pdomReversePostOrder.size(); ++i) {
331             BB *bb = pdomReversePostOrder[i];
332             BB *suc = nullptr;
333             auto it = bb->GetSuccsBegin();
334             if (cgFunc.IsExitBB(*bb) || bb->GetSuccs().empty() || (bb->IsWontExit() && bb->GetKind() == BB::kBBGoto)) {
335                 suc = &commonExitBB;
336             } else {
337                 suc = *it;
338             }
339             ++it;
340             while ((GetPdom(suc->GetId()) == nullptr || suc == bb) && it != bb->GetSuccsEnd()) {
341                 suc = *it;
342                 ++it;
343             }
344             if (GetPdom(suc->GetId()) == nullptr) {
345                 suc = &commonExitBB;
346             }
347             BB *newIDom = suc;
348             for (; it != bb->GetSuccsEnd(); ++it) {
349                 suc = *it;
350                 if (GetPdom(suc->GetId()) != nullptr && suc != bb) {
351                     newIDom = PdomIntersect(*suc, *newIDom);
352                 }
353             }
354             if (GetPdom(bb->GetId()) != newIDom) {
355                 SetPdom(bb->GetId(), newIDom);
356                 DEBUG_ASSERT(GetPdom(newIDom->GetId()) != nullptr, "null ptr check");
357                 changed = true;
358             }
359         }
360     } while (changed);
361 }
362 
363 // Figure 5 in "A Simple, Fast Dominance Algorithm" by Keith Cooper et al.
ComputePdomFrontiers()364 void PostDomAnalysis::ComputePdomFrontiers()
365 {
366     for (const BB *bb : bbVec) {
367         if (bb == nullptr || bb == &commonEntryBB) {
368             continue;
369         }
370         if (bb->GetSuccs().size() < kBBVectorInitialSize) {
371             continue;
372         }
373         for (BB *suc : bb->GetSuccs()) {
374             BB *runner = suc;
375             while (runner != GetPdom(bb->GetId()) && runner != &commonEntryBB) {
376                 if (!HasPdomFrontier(runner->GetId(), bb->GetId())) {
377                     pdomFrontier[runner->GetId()].push_back(bb->GetId());
378                 }
379                 DEBUG_ASSERT(GetPdom(runner->GetId()) != nullptr, "ComputePdomFrontiers: pdoms[] is nullptr");
380                 runner = GetPdom(runner->GetId());
381             }
382         }
383     }
384 }
385 
ComputePdomChildren()386 void PostDomAnalysis::ComputePdomChildren()
387 {
388     for (const BB *bb : bbVec) {
389         if (bb == nullptr || GetPdom(bb->GetId()) == nullptr) {
390             continue;
391         }
392         const BB *parent = GetPdom(bb->GetId());
393         if (parent == bb) {
394             continue;
395         }
396         pdomChildren[parent->GetId()].push_back(bb->GetId());
397     }
398 }
399 
400 // bbidMarker indicates that the iterPdomFrontier results for bbid < bbidMarker
401 // have been computed
GetIterPdomFrontier(const BB * bb,MapleSet<uint32> * dfset,uint32 bbidMarker,std::vector<bool> & visitedMap)402 void PostDomAnalysis::GetIterPdomFrontier(const BB *bb, MapleSet<uint32> *dfset, uint32 bbidMarker,
403                                           std::vector<bool> &visitedMap)
404 {
405     if (visitedMap[bb->GetId()]) {
406         return;
407     }
408     visitedMap[bb->GetId()] = true;
409     for (uint32 frontierbbid : pdomFrontier[bb->GetId()]) {
410         (void)dfset->insert(frontierbbid);
411         if (frontierbbid < bbidMarker) {  // union with its computed result
412             dfset->insert(iterPdomFrontier[frontierbbid].begin(), iterPdomFrontier[frontierbbid].end());
413         } else {  // recursive call
414             BB *frontierbb = bbVec[frontierbbid];
415             GetIterPdomFrontier(frontierbb, dfset, bbidMarker, visitedMap);
416         }
417     }
418 }
419 
ComputeIterPdomFrontiers()420 void PostDomAnalysis::ComputeIterPdomFrontiers()
421 {
422     for (BB *bb : bbVec) {
423         if (bb == nullptr || bb == &commonEntryBB) {
424             continue;
425         }
426         std::vector<bool> visitedMap(bbVec.size(), false);
427         GetIterPdomFrontier(bb, &iterPdomFrontier[bb->GetId()], bb->GetId(), visitedMap);
428     }
429 }
430 
ComputePdtPreorder(const BB & bb,uint32 & num)431 uint32 PostDomAnalysis::ComputePdtPreorder(const BB &bb, uint32 &num)
432 {
433     DEBUG_ASSERT(num < pdtPreOrder.size(), "index out of range in Dominance::ComputePdtPreOrder");
434     pdtPreOrder[num] = bb.GetId();
435     pdtDfn[bb.GetId()] = num;
436     uint32 maxDtDfnOut = num;
437     ++num;
438 
439     for (uint32 k : pdomChildren[bb.GetId()]) {
440         maxDtDfnOut = ComputePdtPreorder(*bbVec[k], num);
441     }
442 
443     pdtDfnOut[bb.GetId()] = maxDtDfnOut;
444     return maxDtDfnOut;
445 }
446 
447 // true if b1 postdominates b2
PostDominate(const BB & bb1,const BB & bb2)448 bool PostDomAnalysis::PostDominate(const BB &bb1, const BB &bb2)
449 {
450     return pdtDfn[bb1.GetId()] <= pdtDfn[bb2.GetId()] && pdtDfnOut[bb1.GetId()] >= pdtDfnOut[bb2.GetId()];
451 }
452 
Dump()453 void PostDomAnalysis::Dump()
454 {
455     for (BB *bb : pdomReversePostOrder) {
456         LogInfo::MapleLogger() << "pdom_postorder no " << pdomPostOrderIDVec[bb->GetId()];
457         LogInfo::MapleLogger() << " is bb:" << bb->GetId();
458         LogInfo::MapleLogger() << " im_pdom is bb:" << GetPdom(bb->GetId())->GetId();
459         LogInfo::MapleLogger() << " pdomfrontier: [";
460         for (uint32 id : pdomFrontier[bb->GetId()]) {
461             LogInfo::MapleLogger() << id << " ";
462         }
463         LogInfo::MapleLogger() << "] pdomchildren: [";
464         for (uint32 id : pdomChildren[bb->GetId()]) {
465             LogInfo::MapleLogger() << id << " ";
466         }
467         LogInfo::MapleLogger() << "]\n";
468     }
469     LogInfo::MapleLogger() << "\n";
470     LogInfo::MapleLogger() << "preorder traversal of post-dominator tree:";
471     for (uint32 id : pdtPreOrder) {
472         LogInfo::MapleLogger() << id << " ";
473     }
474     LogInfo::MapleLogger() << "\n\n";
475 }
476 
Compute()477 void PostDomAnalysis::Compute()
478 {
479     PdomGenPostOrderID();
480     ComputePostDominance();
481     ComputePdomFrontiers();
482     ComputePdomChildren();
483     ComputeIterPdomFrontiers();
484     uint32 num = 0;
485     (void)ComputePdtPreorder(GetCommonExitBB(), num);
486     ResizePdtPreOrder(num);
487 }
488 
PhaseRun(maplebe::CGFunc & f)489 bool CgDomAnalysis::PhaseRun(maplebe::CGFunc &f)
490 {
491     MemPool *domMemPool = GetPhaseMemPool();
492     domAnalysis =
493         domMemPool->New<DomAnalysis>(f, *domMemPool, *domMemPool, f.GetAllBBs(), *f.GetFirstBB(), *f.GetCommonExitBB());
494     domAnalysis->Compute();
495     if (CG_DEBUG_FUNC(f)) {
496         domAnalysis->Dump();
497     }
498     return false;
499 }
MAPLE_ANALYSIS_PHASE_REGISTER(CgDomAnalysis,domanalysis)500 MAPLE_ANALYSIS_PHASE_REGISTER(CgDomAnalysis, domanalysis)
501 
502 bool CgPostDomAnalysis::PhaseRun(maplebe::CGFunc &f)
503 {
504     MemPool *pdomMemPool = GetPhaseMemPool();
505     pdomAnalysis = pdomMemPool->New<PostDomAnalysis>(f, *pdomMemPool, *pdomMemPool, f.GetAllBBs(), *f.GetFirstBB(),
506                                                      *f.GetCommonExitBB());
507     pdomAnalysis->Compute();
508     if (CG_DEBUG_FUNC(f)) {
509         pdomAnalysis->Dump();
510     }
511     return false;
512 }
513 MAPLE_ANALYSIS_PHASE_REGISTER(CgPostDomAnalysis, pdomanalysis)
514 } /* namespace maplebe */
515