• 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 "control_dep_analysis.h"
17 #include "mpl_logging.h"
18 
19 namespace maplebe {
GetExistBB(std::vector<BB * > & bbVec,BBID bbId)20 static BB *GetExistBB(std::vector<BB *> &bbVec, BBID bbId)
21 {
22     for (auto *bb : bbVec) {
23         if (bb->GetId() == bbId) {
24             return bb;
25         }
26     }
27     return nullptr;
28 }
29 
Run()30 void ControlDepAnalysis::Run()
31 {
32     // Local-scheduler(after RA) does not need pdom-analysis
33     if (CONTROL_DEP_ANALYSIS_DUMP && phaseName != "localschedule") {
34         pdom->GeneratePdomTreeDot();
35     }
36     if (cgFunc.IsAfterRegAlloc() || isSingleBB) {
37         // For local scheduling
38         ComputeSingleBBRegions();
39     } else {
40         // For global scheduling based on regions
41         BuildCFGInfo();
42         ConstructFCDG();
43         ComputeRegions(false);
44     }
45 }
46 
47 // Augment CFG info
BuildCFGInfo()48 void ControlDepAnalysis::BuildCFGInfo()
49 {
50     CHECK_FATAL(cgFunc.GetCommonExitBB() != nullptr, "there must be a virtual ExitBB in cfg");
51     cfgMST->BuildEdges(cgFunc.GetFirstBB(), cgFunc.GetCommonExitBB());
52     // denote back-edge on CFGEdge
53     for (auto cfgEdge : cfgMST->GetAllEdges()) {
54         BB *srcBB = cfgEdge->GetSrcBB();
55         BB *destBB = cfgEdge->GetDestBB();
56         (void)*srcBB;
57         (void)*destBB;
58         if (loop->IsBackEdge(*srcBB, *destBB)) {
59             cfgEdge->SetIsBackEdge();
60         }
61     }
62     // denote the condition on CFGEdge except for back-edge
63     for (auto &cfgEdge : cfgMST->GetAllEdges()) {
64         if (cfgEdge->IsBackEdge()) {
65             continue;
66         }
67         BB *srcBB = cfgEdge->GetSrcBB();
68         BB *destBB = cfgEdge->GetDestBB();
69         CHECK_FATAL(srcBB != nullptr, "get srcBB of cfgEdge failed");
70         if (srcBB == cgFunc.GetFirstBB()) {
71             cfgEdge->SetCondition(0);
72             continue;
73         } else if (srcBB == cgFunc.GetCommonExitBB()) {
74             continue;
75         }
76         BB::BBKind srcKind = srcBB->GetKind();
77         switch (srcKind) {
78             case BB::kBBFallthru:
79             case BB::kBBGoto:
80             case BB::kBBIgoto:
81             case BB::kBBReturn:
82                 cfgEdge->SetCondition(0);
83                 break;
84             case BB::kBBIntrinsic:
85                 ASSERT_NOT_NULL(srcBB->GetLastMachineInsn());
86                 if (!srcBB->GetLastMachineInsn()->IsBranch()) {
87                     // set default cond number
88                     cfgEdge->SetCondition(0);
89                 }
90                 // else fall through
91                 [[clang::fallthrough]];
92             case BB::kBBIf: {
93                 Insn *branchInsn = srcBB->GetLastMachineInsn();
94                 CHECK_FATAL(branchInsn != nullptr, "ifBB must have a machine insn at the end");
95                 DEBUG_ASSERT(branchInsn->IsCondBranch(), "ifBB must have a conditional branch insn at the end");
96                 int lastOpndIdx = static_cast<int>(branchInsn->GetOperandSize()) - 1;
97                 DEBUG_ASSERT(lastOpndIdx > -1, "lastOpndIdx must greater than -1");
98                 Operand &lastOpnd = branchInsn->GetOperand(static_cast<uint32>(lastOpndIdx));
99                 DEBUG_ASSERT(lastOpnd.IsLabelOpnd(), "lastOpnd must be labelOpnd in branchInsn");
100                 BB *jumpBB = cgFunc.GetBBFromLab2BBMap(static_cast<LabelOperand &>(lastOpnd).GetLabelIndex());
101                 if (jumpBB == destBB) {
102                     cfgEdge->SetCondition(0);
103                 } else {
104                     cfgEdge->SetCondition(1);
105                 }
106                 break;
107             }
108             case BB::kBBRangeGoto: {
109                 // Each successor cfgEdge is assigned a different cond number
110                 cfgEdge->SetCondition(static_cast<int32>(GetAndAccSuccedCondNum(srcBB->GetId())));
111                 break;
112             }
113             default:
114                 // these kindBBs set default cond number [kBBNoReturn kBBThrow kBBLast]
115                 cfgEdge->SetCondition(0);
116                 break;
117         }
118     }
119 }
120 
121 // Construct forward control dependence graph
ConstructFCDG()122 void ControlDepAnalysis::ConstructFCDG()
123 {
124     CreateAllCDGNodes();
125     // 1. Collect all edges(A, B) in CFG that B does not post-dom A
126     for (auto cfgEdge : cfgMST->GetAllEdges()) {
127         if (cfgEdge->IsBackEdge()) {
128             continue;
129         }
130         BB *srcBB = cfgEdge->GetSrcBB();
131         BB *destBB = cfgEdge->GetDestBB();
132         CHECK_FATAL(srcBB != nullptr && destBB != nullptr, "get edge-connected nodes in cfg failed");
133         if (srcBB == cgFunc.GetCommonExitBB()) {
134             continue;
135         }
136         if (!pdom->PostDominate(*destBB, *srcBB)) {
137             AddNonPdomEdges(cfgEdge);
138         }
139     }
140 
141     // 2. Determine control dependence by traversal backward in the post-dom tree for every bbEdge in nonPdomEdges
142     for (auto candiEdge : nonPdomEdges) {
143         BB *srcBB = candiEdge->GetSrcBB();
144         BB *destBB = candiEdge->GetDestBB();
145         CHECK_FATAL(srcBB != nullptr && destBB != nullptr, "get edge-connected nodes in nonPdomEdges failed");
146         // Find the nearest common ancestor (L) of srcBB and destBB in the pdom-tree :
147         //   (1) L == parent of srcBB in the pdom-tree (immediate dominator of srcBB)
148         //   (2) L == srcBB
149         BB *ancestor = (pdom->GetPdom(destBB->GetId()) == srcBB) ? srcBB : pdom->GetPdom(srcBB->GetId());
150         BB *curBB = destBB;
151         while (curBB != nullptr && curBB != ancestor && curBB != cgFunc.GetCommonExitBB()) {
152             (void)BuildControlDependence(*srcBB, *curBB, candiEdge->GetCondition());
153             curBB = pdom->GetPdom(curBB->GetId());
154         }
155     }
156 }
157 
158 /** Divide regions for the CDGNodes :
159  *   Traverse the post-dominator tree by means of a post-order to
160  *   assure that all children in the post-dominator tree are visited before their parent.
161  */
ComputeRegions(bool doCDRegion)162 void ControlDepAnalysis::ComputeRegions(bool doCDRegion)
163 {
164     if (doCDRegion) {
165         ComputeSameCDRegions(false);
166     } else {
167         ComputeGeneralNonLinearRegions();
168     }
169 }
170 
171 // This algorithm computes the general non-linear region, including:
172 //   1). A reducible loops which have a single-in edge
173 //   2). A fallthrough path not in any regions
174 //   3). A single-bb not in other regions as a region
ComputeGeneralNonLinearRegions()175 void ControlDepAnalysis::ComputeGeneralNonLinearRegions()
176 {
177     // If ebo phase was removed, must recalculate loop info
178     // 1. Find all innermost loops
179     std::vector<LoopDesc *> innermostLoops;
180     std::unordered_map<LoopDesc *, bool> visited;
181 
182     for (auto lp : loop->GetLoops()) {
183         FindInnermostLoops(innermostLoops, visited, lp);
184     }
185 
186     // 2. Find reducible loops as a region
187     for (auto innerLoop : innermostLoops) {
188         // Avoid the case as following:
189         //             |
190         //             |
191         //      ----- BB4 ----------
192         //      |    /   \         |
193         //      |   /     \        |
194         //       BB3      BB5      |
195         //               /  \      |
196         //              /    \     |
197         //            BB6     BB10 -
198         //             |
199         //             |
200         //            EXIT
201         // By the current loop analysis, {BB4, BB3, BB5, BB10} are in the same loop, which the headerBB is BB4
202         // By the dom and pdom analysis, {BB4 dom BB5} and {BB5 pdom BB4}, BB4 and BB5 are EQUIVALENT,
203         //   but they cannot schedule in parallel.
204         //
205         // The above case may cause loop-carried dependency instructions to be scheduled, and currently this
206         // dependency is not considered.
207         if (innerLoop->GetBackEdges().size() > 1) {
208             continue;
209         }
210 
211         bool isReducible = true;
212         auto &header = innerLoop->GetHeader();
213         for (auto memberId : innerLoop->GetLoopBBs()) {
214             if (!dom->Dominate(header, *cgFunc.GetBBFromID(memberId))) {
215                 isReducible = false;
216             }
217         }
218         if (isReducible) {
219             auto *region = cdgMemPool.New<CDGRegion>(CDGRegionId(lastRegionId++), cdgAlloc);
220             CDGNode *headerNode = header.GetCDGNode();
221             CHECK_FATAL(headerNode != nullptr, "get cdgNode from bb failed");
222             region->SetRegionRoot(*headerNode);
223             region->SetBackBBId(*innerLoop->GetBackEdges().begin());
224             for (auto memberId : innerLoop->GetLoopBBs()) {
225                 CDGNode *memberNode = cgFunc.GetBBFromID(memberId)->GetCDGNode();
226                 CHECK_FATAL(memberNode != nullptr, "get cdgNode from bb failed");
227                 memberNode->SetRegion(region);
228             }
229             if (AddRegionNodesInTopologicalOrder(*region, *headerNode, innerLoop->GetLoopBBs())) {
230                 fcdg->AddRegion(*region);
231             }
232         }
233     }
234 
235     // 3. Find fallthrough path not in any regions as a region
236     FOR_ALL_BB(bb, &cgFunc)
237     {
238         if (bb->IsUnreachable()) {
239             continue;
240         }
241         std::vector<CDGNode *> regionMembers;
242         CDGNode *cdgNode = bb->GetCDGNode();
243         CHECK_FATAL(cdgNode != nullptr, "get cdgNode from bb failed");
244         if (!cdgNode->IsVisitedInExtendedFind() && bb->GetSuccsSize() == 1 && cdgNode->GetRegion() == nullptr) {
245             // Nodes in the region are in the order of topology in this way
246             FindFallthroughPath(regionMembers, bb, true);
247             auto *region = cdgMemPool.New<CDGRegion>(CDGRegionId(lastRegionId++), cdgAlloc);
248             region->SetRegionRoot(*cdgNode);
249             for (auto memberNode : regionMembers) {
250                 region->AddCDGNode(memberNode);
251                 memberNode->SetRegion(region);
252             }
253             fcdg->AddRegion(*region);
254             regionMembers.clear();
255         }
256     }
257 
258     // 4. Create region for the remaining BBs that are not in any region
259     CreateRegionForSingleBB();
260 }
261 
FindFallthroughPath(std::vector<CDGNode * > & regionMembers,BB * curBB,bool isRoot)262 void ControlDepAnalysis::FindFallthroughPath(std::vector<CDGNode *> &regionMembers, BB *curBB, bool isRoot)
263 {
264     CHECK_FATAL(curBB != nullptr, "invalid bb");
265     CDGNode *curNode = curBB->GetCDGNode();
266     CHECK_FATAL(curNode != nullptr, "get cdgNode from bb failed");
267     if (curNode->IsVisitedInExtendedFind()) {
268         return;
269     }
270     curNode->SetVisitedInExtendedFind();
271     if (isRoot) {
272         if (curBB->GetSuccsSize() == 1 && curNode->GetRegion() == nullptr) {
273             regionMembers.emplace_back(curNode);
274         } else {
275             return;
276         }
277     } else {
278         if (curBB->GetPreds().size() == 1 && curBB->GetSuccsSize() == 1 && curNode->GetRegion() == nullptr) {
279             regionMembers.emplace_back(curNode);
280         } else {
281             return;
282         }
283     }
284     FindFallthroughPath(regionMembers, *curBB->GetSuccsBegin(), false);
285 }
286 
CreateRegionForSingleBB()287 void ControlDepAnalysis::CreateRegionForSingleBB()
288 {
289     FOR_ALL_BB(bb, &cgFunc)
290     {
291         if (bb->IsUnreachable()) {
292             continue;
293         }
294         CDGNode *cdgNode = bb->GetCDGNode();
295         CHECK_FATAL(cdgNode != nullptr, "get cdgNode from bb failed");
296         if (cdgNode->GetRegion() == nullptr) {
297             auto *region = cdgMemPool.New<CDGRegion>(CDGRegionId(lastRegionId++), cdgAlloc);
298             region->AddCDGNode(cdgNode);
299             cdgNode->SetRegion(region);
300             region->SetRegionRoot(*cdgNode);
301             fcdg->AddRegion(*region);
302         }
303     }
304 }
305 
306 // Recursive search for innermost loop
FindInnermostLoops(std::vector<LoopDesc * > & innermostLoops,std::unordered_map<LoopDesc *,bool> & visited,LoopDesc * lp)307 void ControlDepAnalysis::FindInnermostLoops(std::vector<LoopDesc *> &innermostLoops,
308                                             std::unordered_map<LoopDesc *, bool> &visited, LoopDesc *lp)
309 {
310     if (lp == nullptr) {
311         return;
312     }
313     auto it = visited.find(lp);
314     if (it != visited.end() && it->second) {
315         return;
316     }
317     visited.emplace(lp, true);
318     const auto &innerLoops = lp->GetChildLoops();
319     if (innerLoops.empty()) {
320         innermostLoops.emplace_back(lp);
321     } else {
322         for (auto innerLoop : innerLoops) {
323             FindInnermostLoops(innermostLoops, visited, innerLoop);
324         }
325     }
326 }
327 
AddRegionNodesInTopologicalOrder(CDGRegion & region,CDGNode & root,const MapleSet<BBID> & members)328 bool ControlDepAnalysis::AddRegionNodesInTopologicalOrder(CDGRegion &region, CDGNode &root,
329                                                           const MapleSet<BBID> &members)
330 {
331     // Init predSum for memberNode except for root in region
332     for (auto bbId : members) {
333         auto *bb = cgFunc.GetBBFromID(bbId);
334         CDGNode *cdgNode = bb->GetCDGNode();
335         CHECK_FATAL(cdgNode != nullptr, "get cdgNode from bb failed");
336         if (cdgNode == &root) {
337             continue;
338         }
339         int32 predSumInRegion = 0;
340         for (auto predIt = bb->GetPredsBegin(); predIt != bb->GetPredsEnd(); ++predIt) {
341             CDGNode *predNode = (*predIt)->GetCDGNode();
342             CHECK_FATAL(predNode != nullptr, "get CDGNode from bb failed");
343             if (predNode->GetRegion() == &region) {
344                 predSumInRegion++;
345             }
346         }
347         cdgNode->InitPredNodeSumInRegion(predSumInRegion);
348         cdgNode->SetVisitedInTopoSort(false);
349     }
350 
351     // Topological sort
352     std::queue<CDGNode *> topoQueue;
353     topoQueue.push(&root);
354     while (!topoQueue.empty()) {
355         CDGNode *curNode = topoQueue.front();
356         topoQueue.pop();
357         region.AddCDGNode(curNode);
358 
359         for (auto bbId : members) {
360             auto *bb = cgFunc.GetBBFromID(bbId);
361             CDGNode *memberNode = bb->GetCDGNode();
362             CHECK_FATAL(memberNode != nullptr, "get cdgNode from bb failed");
363             if (memberNode == &root || memberNode->IsVisitedInTopoSort()) {
364                 continue;
365             }
366             for (auto predIt = bb->GetPredsBegin(); predIt != bb->GetPredsEnd(); ++predIt) {
367                 CDGNode *predNode = (*predIt)->GetCDGNode();
368                 CHECK_FATAL(predNode != nullptr, "get cdgNode from bb failed");
369                 if (predNode == curNode) {
370                     memberNode->DecPredNodeSumInRegion();
371                 }
372             }
373             if (memberNode->IsAllPredInRegionProcessed()) {
374                 topoQueue.push(memberNode);
375                 memberNode->SetVisitedInTopoSort(true);
376             }
377         }
378     }
379     // To avoid irreducible loops in reducible loops, need to modify the loop analysis algorithm in the future.
380     if (region.GetRegionNodeSize() != members.size()) {
381         return false;
382     }
383     return true;
384 }
385 
386 /** This region computing algorithm is based on this paper:
387  *      The Program Dependence Graph and Its Use in Optimization
388  * It traverses the post-dominator tree by means of a post-order to assure that
389  * all children in the post-dominator tree are visited before their parent.
390  * The region is non-linear too.
391  * If cdgNodes that do not have any control dependency are divided into a region, the region is multi-root,
392  * which is not supported in inter-block data dependence analysis
393  */
ComputeSameCDRegions(bool considerNonDep)394 void ControlDepAnalysis::ComputeSameCDRegions(bool considerNonDep)
395 {
396     // The default bbId starts from 1
397     std::vector<bool> visited(fcdg->GetFCDGNodeSize(), false);
398     for (uint32 bbId = 1; bbId < fcdg->GetFCDGNodeSize(); ++bbId) {
399         if (!visited[bbId]) {
400             ComputeRegionForCurNode(bbId, visited);
401         }
402     }
403     if (considerNonDep) {
404         ComputeRegionForNonDepNodes();
405     }
406 }
407 
408 // Nodes that don't have any control dependency are divided into a region
ComputeRegionForNonDepNodes()409 void ControlDepAnalysis::ComputeRegionForNonDepNodes()
410 {
411     CDGRegion *curRegion = nullptr;
412     CDGNode *mergeNode = nullptr;
413     for (auto node : fcdg->GetAllFCDGNodes()) {
414         if (node == nullptr) {
415             continue;
416         }
417         if (node->GetInEdgesNum() != 0) {
418             continue;
419         }
420         if (curRegion == nullptr) {
421             curRegion = node->GetRegion();
422             CHECK_FATAL(curRegion != nullptr, "each CDGNode must be in a region");
423             mergeNode = node;
424         } else if (node->GetRegion() != curRegion) {
425             // Merge Region
426             CHECK_FATAL(mergeNode != nullptr, "invalid non-dep cdgNode");
427             MergeRegions(*mergeNode, *node);
428         }
429     }
430 }
431 
432 // Recursively computes the region of each node
ComputeRegionForCurNode(uint32 curBBId,std::vector<bool> & visited)433 void ControlDepAnalysis::ComputeRegionForCurNode(uint32 curBBId, std::vector<bool> &visited)
434 {
435     if (visited[curBBId]) {
436         return;
437     }
438     visited[curBBId] = true;
439     MapleVector<uint32> children = pdom->GetPdomChildrenItem(curBBId);
440     if (!children.empty()) {
441         // Check that each child of the node has been computed
442         for (auto childId : children) {
443             if (!visited[childId]) {
444                 ComputeRegionForCurNode(childId, visited);
445             }
446         }
447     }
448     // Leaf nodes and the nodes whose children have been computed in the pdom-tree that can be merged region
449     CreateAndDivideRegion(curBBId);
450 }
451 
CreateAndDivideRegion(uint32 pBBId)452 void ControlDepAnalysis::CreateAndDivideRegion(uint32 pBBId)
453 {
454     // 1. Visit every CDGNode:N, Get and Create the region of the control dependence set
455     CDGNode *parentNode = fcdg->GetCDGNodeFromId(CDGNodeId(pBBId));
456     CHECK_FATAL(parentNode != nullptr, "get CDGNode failed");
457     CDGRegion *region = FindExistRegion(*parentNode);
458     if (region == nullptr) {
459         region = CreateFCDGRegion(*parentNode);
460     } else {
461         region->AddCDGNode(parentNode);
462         parentNode->SetRegion(region);
463     }
464     MapleVector<CDGNode *> &regionNodes = region->GetRegionNodes();
465     // 2. Visit each immediate child of N in the post-dom tree, compute the intersection of CDs
466     BB *curBB = parentNode->GetBB();
467     CHECK_FATAL(curBB != nullptr, "get bb of CDGNode failed");
468     for (auto childBBId : pdom->GetPdomChildrenItem(curBB->GetId())) {
469         CDGNode *childNode = fcdg->GetCDGNodeFromId(CDGNodeId(childBBId));
470         if (std::find(regionNodes.begin(), regionNodes.end(), childNode) != regionNodes.end()) {
471             continue;
472         }
473         if (IsISEqualToCDs(*parentNode, *childNode)) {
474             MergeRegions(*parentNode, *childNode);
475         }
476     }
477 }
478 
479 // Check whether the region corresponding to the control dependence set exists
FindExistRegion(CDGNode & node) const480 CDGRegion *ControlDepAnalysis::FindExistRegion(CDGNode &node) const
481 {
482     MapleVector<CDGRegion *> &allRegions = fcdg->GetAllRegions();
483     MapleVector<CDGEdge *> &curCDs = node.GetAllInEdges();
484     // Nodes that don't have control dependencies are processed in a unified method at last
485     if (curCDs.empty()) {
486         return nullptr;
487     }
488     for (auto region : allRegions) {
489         if (region == nullptr) {
490             continue;
491         }
492         MapleVector<CDGEdge *> &regionCDs = region->GetCDEdges();
493         if (regionCDs.size() != curCDs.size()) {
494             continue;
495         }
496         bool isAllCDExist = true;
497         for (auto curCD : curCDs) {
498             CHECK_FATAL(curCD != nullptr, "invalid control dependence edge");
499             bool isOneCDExist = false;
500             for (auto regionCD : regionCDs) {
501                 CHECK_FATAL(regionCD != nullptr, "invalid control dependence edge");
502                 if (IsSameControlDependence(*curCD, *regionCD)) {
503                     isOneCDExist = true;
504                     break;
505                 }
506             }
507             if (!isOneCDExist) {
508                 isAllCDExist = false;
509                 break;
510             }
511         }
512         if (isAllCDExist) {
513             return region;
514         }
515     }
516     return nullptr;
517 }
518 
519 // Check whether the intersection(IS) of the control dependency set of the parent node (CDs)
520 // and the child node is equal to the control dependency set of the parent node
IsISEqualToCDs(CDGNode & parent,CDGNode & child) const521 bool ControlDepAnalysis::IsISEqualToCDs(CDGNode &parent, CDGNode &child) const
522 {
523     MapleVector<CDGEdge *> &parentCDs = parent.GetAllInEdges();
524     MapleVector<CDGEdge *> &childCDs = child.GetAllInEdges();
525     // Nodes that don't have control dependencies are processed in a unified method at last
526     if (parentCDs.empty() || childCDs.empty()) {
527         return false;
528     }
529     bool equal = true;
530     for (auto parentCD : parentCDs) {
531         CHECK_FATAL(parentCD != nullptr, "invalid CDGEdge in parentCDs");
532         for (auto childCD : childCDs) {
533             if (!IsSameControlDependence(*parentCD, *childCD)) {
534                 equal = false;
535                 continue;
536             }
537         }
538         if (!equal) {
539             return false;
540         }
541     }
542     return true;
543 }
544 
545 // Merge regions of parentNode and childNode
MergeRegions(CDGNode & mergeNode,CDGNode & candiNode)546 void ControlDepAnalysis::MergeRegions(CDGNode &mergeNode, CDGNode &candiNode)
547 {
548     CDGRegion *oldRegion = candiNode.GetRegion();
549     CHECK_FATAL(oldRegion != nullptr, "get child's CDGRegion failed");
550 
551     // Set newRegion of all memberNodes in oldRegion of child
552     CDGRegion *mergeRegion = mergeNode.GetRegion();
553     CHECK_FATAL(mergeRegion != nullptr, "get parent's CDGRegion failed");
554     for (auto node : oldRegion->GetRegionNodes()) {
555         node->SetRegion(mergeRegion);
556         mergeRegion->AddCDGNode(node);
557         oldRegion->RemoveCDGNode(node);
558     }
559 
560     if (oldRegion->GetRegionNodeSize() == 0) {
561         fcdg->RemoveRegionById(oldRegion->GetRegionId());
562     }
563 }
564 
BuildControlDependence(const BB & fromBB,const BB & toBB,int32 condition)565 CDGEdge *ControlDepAnalysis::BuildControlDependence(const BB &fromBB, const BB &toBB, int32 condition)
566 {
567     auto *fromNode = fcdg->GetCDGNodeFromId(CDGNodeId(fromBB.GetId()));
568     auto *toNode = fcdg->GetCDGNodeFromId(CDGNodeId(toBB.GetId()));
569     CHECK_FATAL(fromNode != nullptr && toNode != nullptr, "get CDGNode failed");
570     auto *cdgEdge = cdgMemPool.New<CDGEdge>(*fromNode, *toNode, condition);
571 
572     fromNode->AddOutEdges(cdgEdge);
573     toNode->AddInEdges(cdgEdge);
574     fcdg->AddFCDGEdge(cdgEdge);
575     return cdgEdge;
576 }
577 
CreateFCDGRegion(CDGNode & curNode)578 CDGRegion *ControlDepAnalysis::CreateFCDGRegion(CDGNode &curNode)
579 {
580     MapleVector<CDGEdge *> cdEdges = curNode.GetAllInEdges();
581     auto *region = cdgMemPool.New<CDGRegion>(CDGRegionId(lastRegionId++), cdgAlloc);
582     region->AddCDEdgeSet(cdEdges);
583     region->AddCDGNode(&curNode);
584     fcdg->AddRegion(*region);
585     curNode.SetRegion(region);
586     return region;
587 }
588 
ComputeSingleBBRegions()589 void ControlDepAnalysis::ComputeSingleBBRegions()
590 {
591     CreateAllCDGNodes();
592     CreateRegionForSingleBB();
593 }
594 
595 // Create CDGNode for every BB
CreateAllCDGNodes()596 void ControlDepAnalysis::CreateAllCDGNodes()
597 {
598     fcdg = cdgMemPool.New<FCDG>(cgFunc, cdgAlloc);
599     FOR_ALL_BB(bb, &cgFunc)
600     {
601         if (bb->IsUnreachable()) {
602             continue;
603         }
604         auto *node = cdgMemPool.New<CDGNode>(CDGNodeId(bb->GetId()), *bb, cdgAlloc);
605         if (bb == cgFunc.GetFirstBB()) {
606             node->SetEntryNode();
607         }
608         bb->SetCDGNode(node);
609         fcdg->AddFCDGNode(*node);
610     }
611     // Create CDGNode for exitBB
612     BB *exitBB = cgFunc.GetCommonExitBB();
613     auto *exitNode = cdgMemPool.New<CDGNode>(CDGNodeId(exitBB->GetId()), *exitBB, cdgAlloc);
614     exitNode->SetExitNode();
615     exitBB->SetCDGNode(exitNode);
616     fcdg->AddFCDGNode(*exitNode);
617 }
618 
619 // Compute the pdom info only in the CDGRegion:
620 // we copy the cfg of the CDGRegion and perform pdom analysis on the tmp cfg.
621 // Currently, only for the innermost reducible loops.
622 // e.g.
623 //         tmpCommonEntry
624 //             |
625 //           ....
626 //             | (regionInEdge)
627 //            \|/
628 //    |--|--->BB9
629 //    |  |       \
630 //    |  |      BB10
631 //    |  |       /   \
632 //    |  |     BB11  BB16
633 //    |  |       \   /
634 //    |  |        BB12
635 //    |  |        /    \   (regionOutEdge)
636 //    |  |      BB13   _\/
637 //    |  |      /       ....   ---------
638 //    |--|--->BB14                     |
639 //              \                      |
640 //              _\/ (regionOutEdge)    |
641 //              ....                   |
642 //                \                    |
643 //                  tmpCommonExit ------
644 // based on the global cfg, the BB12 pdom BB9;
645 // but based on the region cfg, the BB12 not pdom BB9.
ComputePdomInRegion(CDGRegion & region,std::vector<BB * > & nonUniformRegionCFG,uint32 & maxBBId)646 Dominance *ControlDepAnalysis::ComputePdomInRegion(CDGRegion &region, std::vector<BB *> &nonUniformRegionCFG,
647                                                    uint32 &maxBBId)
648 {
649     if (region.GetRegionNodeSize() <= 1) {
650         return nullptr;
651     }
652     // Copy the cfg of the CDGRegion
653     std::set<BB *> regionInBBs;
654     std::set<BB *> regionOutBBs;
655     maxBBId = 0;
656     BB *startBB = nullptr;
657     BB *endBB = nullptr;
658     for (auto *memberNode : region.GetRegionNodes()) {
659         BB *memberBB = memberNode->GetBB();
660         ASSERT_NOT_NULL(memberBB);
661         BB *tmpBB = GetExistBB(nonUniformRegionCFG, memberBB->GetId());
662         if (tmpBB == nullptr) {
663             tmpBB = cdgMemPool.New<BB>(memberBB->GetId(), cdgAlloc);
664             nonUniformRegionCFG.emplace_back(tmpBB);
665         }
666         if (memberNode == region.GetRegionRoot()) {
667             startBB = tmpBB;
668         } else if (memberNode == region.GetRegionNodes().back()) {
669             endBB = tmpBB;
670         }
671         maxBBId = (tmpBB->GetId() > maxBBId ? tmpBB->GetId() : maxBBId);
672         bool hasOutSidePred = false;
673         for (auto *predBB : memberBB->GetPreds()) {
674             if (predBB == nullptr) {
675                 continue;
676             }
677             ASSERT_NOT_NULL(predBB->GetCDGNode());
678             BB *existBB = GetExistBB(nonUniformRegionCFG, predBB->GetId());
679             if (existBB != nullptr) {
680                 tmpBB->PushBackPreds(*existBB);
681                 existBB->PushBackSuccs(*tmpBB);
682             } else {
683                 auto *tmpPredBB = cdgMemPool.New<BB>(predBB->GetId(), cdgAlloc);
684                 if (predBB->GetCDGNode()->GetRegion() == &region) {
685                     tmpBB->PushBackPreds(*tmpPredBB);
686                     tmpPredBB->PushBackSuccs(*tmpBB);
687                 } else if (!hasOutSidePred) {
688                     tmpBB->PushBackPreds(*tmpPredBB);
689                     tmpPredBB->PushBackSuccs(*tmpBB);
690                     regionInBBs.insert(tmpPredBB);
691                     hasOutSidePred = true;
692                 } else {
693                     continue;
694                 }
695                 nonUniformRegionCFG.emplace_back(tmpPredBB);
696                 maxBBId = (tmpPredBB->GetId() > maxBBId ? tmpPredBB->GetId() : maxBBId);
697             }
698         }
699         bool hasOutSideSucc = false;
700         for (auto *succBB : memberBB->GetSuccs()) {
701             if (succBB == nullptr) {
702                 continue;
703             }
704             ASSERT_NOT_NULL(succBB->GetCDGNode());
705             BB *existBB = GetExistBB(nonUniformRegionCFG, succBB->GetId());
706             if (existBB != nullptr) {
707                 tmpBB->PushBackSuccs(*existBB);
708                 existBB->PushBackPreds(*tmpBB);
709             } else {
710                 auto *tmpSuccBB = cdgMemPool.New<BB>(succBB->GetId(), cdgAlloc);
711                 if (succBB->GetCDGNode()->GetRegion() == &region) {
712                     tmpBB->PushBackSuccs(*tmpSuccBB);
713                     tmpSuccBB->PushBackPreds(*tmpBB);
714                 } else if (!hasOutSideSucc) {
715                     tmpBB->PushBackSuccs(*tmpSuccBB);
716                     tmpSuccBB->PushBackPreds(*tmpBB);
717                     regionOutBBs.insert(tmpSuccBB);
718                     hasOutSideSucc = true;
719                 } else {
720                     continue;
721                 }
722                 nonUniformRegionCFG.emplace_back(tmpSuccBB);
723                 maxBBId = (tmpSuccBB->GetId() > maxBBId ? tmpSuccBB->GetId() : maxBBId);
724             }
725         }
726     }
727     // Create temp commonEntry
728     maxBBId++;
729     BB *tmpEntry = cdgMemPool.New<BB>(maxBBId, cdgAlloc);
730     if (!regionInBBs.empty()) {
731         for (auto *regionIn : regionInBBs) {
732             tmpEntry->PushBackSuccs(*regionIn);
733         }
734     } else {
735         CHECK_NULL_FATAL(startBB);
736         tmpEntry->PushBackSuccs(*startBB);
737     }
738     nonUniformRegionCFG.emplace_back(tmpEntry);
739     // Create temp CommonExit
740     maxBBId++;
741     BB *tmpExit = cdgMemPool.New<BB>(maxBBId, cdgAlloc);
742     if (!regionOutBBs.empty()) {
743         for (auto *regionOut : regionOutBBs) {
744             tmpExit->PushBackPreds(*regionOut);
745         }
746     } else {
747         CHECK_NULL_FATAL(endBB);
748         tmpExit->PushBackPreds(*endBB);
749     }
750     nonUniformRegionCFG.emplace_back(tmpExit);
751     // Uniform region bb vector: <BBId, BB*>
752     MapleVector<BaseGraphNode *> regionCFG(maxBBId + 1, cdgAlloc.Adapter());
753     for (auto *bb : nonUniformRegionCFG) {
754         regionCFG[bb->GetId()] = bb;
755     }
756     // For pdom analysis, the commonEntry and commonExit need to be reversed
757     auto *regionPdom = cdgMemPool.New<Dominance>(cdgMemPool, regionCFG, *tmpExit, *tmpEntry, true);
758     regionPdom->Init();
759     return regionPdom;
760 }
761 
IsInDifferentSCCNode(CDGRegion & region,std::vector<BB * > & regionCFG,uint32 maxBBId,const BB & curBB,const BB & memberBB)762 bool ControlDepAnalysis::IsInDifferentSCCNode(CDGRegion &region, std::vector<BB *> &regionCFG, uint32 maxBBId,
763                                               const BB &curBB, const BB &memberBB)
764 {
765     // For fallthrough region, we do not need to check this
766     if (region.GetBackBBId() == UINT32_MAX) {
767         return false;
768     }
769     // Before pdom analysis, uniform region bb vector: <BBId, BB*>
770     MapleVector<BaseGraphNode *> uniformedRegionCFG(maxBBId + 1, cdgAlloc.Adapter());
771     for (auto *bb : regionCFG) {
772         uniformedRegionCFG[bb->GetId()] = bb;
773     }
774     // 1. Check SCC
775     // Before buildSCC, record regionCFG, but not record commonEntry and commonExit
776     regionCFG.erase(regionCFG.end() - kNumOne);
777     regionCFG.erase(regionCFG.end() - kNumTwo);
778     MapleVector<SCCNode<BB> *> sccs(cdgAlloc.Adapter());
779     (void)BuildSCC(cdgAlloc, maxBBId, regionCFG, false, sccs, true);
780     for (auto *scc : sccs) {
781         if (!scc->HasRecursion()) {
782             continue;
783         }
784         uint32 count = 0;
785         for (BB *bb : scc->GetNodes()) {
786             if (bb->GetId() == curBB.GetId() || bb->GetId() == memberBB.GetId()) {
787                 count++;
788             }
789         }
790         // The two equivalent candidate BBs are not in the same SCC,
791         // we can not thin they are equivalent.
792         if (count == 1) {
793             return true;
794         }
795     }
796     // 2. Check pdom analysis for cfg of region that removes the back edge.
797     //    Region construction ensures that there is only one back edge in the region.
798     bool allSuccOfBackBBInRegion = true;
799     for (auto *succ : cgFunc.GetBBFromID(region.GetBackBBId())->GetSuccs()) {
800         CDGNode *cdgNode = succ->GetCDGNode();
801         ASSERT_NOT_NULL(cdgNode);
802         if (cdgNode->GetRegion() != &region) {
803             allSuccOfBackBBInRegion = false;
804             break;
805         }
806     }
807     if (allSuccOfBackBBInRegion) {
808         CHECK_FATAL(uniformedRegionCFG.size() > 1, "must not be zero");
809         BB *commonEntryBB = static_cast<BB *>(uniformedRegionCFG[uniformedRegionCFG.size() - 2]);
810         BB *commonExitBB = static_cast<BB *>(uniformedRegionCFG[uniformedRegionCFG.size() - 1]);
811         ASSERT_NOT_NULL(region.GetRegionRoot());
812         ASSERT_NOT_NULL(region.GetRegionRoot()->GetBB());
813         BB *headerBB = static_cast<BB *>(uniformedRegionCFG[region.GetRegionRoot()->GetBB()->GetId()]);
814         BB *backBB = static_cast<BB *>(uniformedRegionCFG[region.GetBackBBId()]);
815         backBB->RemoveSuccs(*headerBB);
816         headerBB->RemovePreds(*backBB);
817         commonExitBB->PushBackPreds(*backBB);
818         auto *pruneRegionPdom =
819             cdgMemPool.New<Dominance>(cdgMemPool, uniformedRegionCFG, *commonExitBB, *commonEntryBB, true);
820         pruneRegionPdom->Init();
821         if (!pruneRegionPdom->Dominate(memberBB.GetId(), curBB.GetId())) {
822             return true;
823         }
824     }
825     return false;
826 }
827 
828 /** Find equivalent candidate nodes of current cdgNode:
829  *   A and B are equivalent if and only if A dominates B and B post-dominates A
830  * And it must be behind the current cdgNode in the topology order
831  */
GetEquivalentNodesInRegion(CDGRegion & region,CDGNode & cdgNode,std::vector<CDGNode * > & equivalentNodes)832 void ControlDepAnalysis::GetEquivalentNodesInRegion(CDGRegion &region, CDGNode &cdgNode,
833                                                     std::vector<CDGNode *> &equivalentNodes)
834 {
835     BB *curBB = cdgNode.GetBB();
836     CHECK_FATAL(curBB != nullptr, "get bb from cdgNode failed");
837     MapleVector<CDGNode *> &memberNodes = region.GetRegionNodes();
838     bool isBehind = false;
839     for (auto member : memberNodes) {
840         if (member == &cdgNode) {
841             isBehind = true;
842             continue;
843         }
844         BB *memberBB = member->GetBB();
845         CHECK_FATAL(memberBB != nullptr, "get bb from cdgNode failed");
846         std::vector<BB *> nonUniformRegionCFG;
847         uint32 maxBBId = 0;
848         Dominance *regionPdom = ComputePdomInRegion(region, nonUniformRegionCFG, maxBBId);
849         if (dom->Dominate(*curBB, *memberBB) &&
850             (regionPdom != nullptr && regionPdom->Dominate(memberBB->GetId(), curBB->GetId())) && isBehind) {
851             // To avoid the loop-carried instructions are scheduled
852             bool isInPartialCycle = false;
853             for (auto predBB : memberBB->GetPreds()) {
854                 if (predBB->GetCDGNode()->GetRegion() == &region && predBB->GetSuccsSize() > 1) {
855                     isInPartialCycle = true;
856                     break;
857                 }
858             }
859             if (!isInPartialCycle && !IsInDifferentSCCNode(region, nonUniformRegionCFG, maxBBId, *curBB, *memberBB)) {
860                 equivalentNodes.emplace_back(member);
861             }
862         }
863     }
864 }
865 
GenerateFCDGDot() const866 void ControlDepAnalysis::GenerateFCDGDot() const
867 {
868     CHECK_FATAL(fcdg != nullptr, "construct FCDG failed");
869     MapleVector<CDGNode *> &allNodes = fcdg->GetAllFCDGNodes();
870     MapleVector<CDGEdge *> &allEdges = fcdg->GetAllFCDGEdges();
871     MapleVector<CDGRegion *> &allRegions = fcdg->GetAllRegions();
872 
873     std::streambuf *coutBuf = std::cout.rdbuf();
874     std::ofstream fcdgFile;
875     std::streambuf *fileBuf = fcdgFile.rdbuf();
876     (void)std::cout.rdbuf(fileBuf);
877 
878     // Define the output file name
879     std::string fileName;
880     (void)fileName.append("fcdg_");
881     (void)fileName.append(cgFunc.GetName());
882     (void)fileName.append(".dot");
883 
884     fcdgFile.open(fileName, std::ios::trunc);
885     if (!fcdgFile.is_open()) {
886         LogInfo::MapleLogger(kLlWarn) << "fileName:" << fileName << " open failed.\n";
887         return;
888     }
889     fcdgFile << "digraph FCDG_" << cgFunc.GetName() << " {\n\n";
890     fcdgFile << "  node [shape=box,style=filled,color=lightgrey];\n\n";
891 
892     // Dump nodes style
893     for (auto node : allNodes) {
894         if (node == nullptr) {
895             continue;
896         }
897         BB *bb = node->GetBB();
898         CHECK_FATAL(bb != nullptr, "get bb of CDGNode failed");
899         fcdgFile << "  BB_" << bb->GetId();
900         fcdgFile << "[label= \"";
901         if (node->IsEntryNode()) {
902             fcdgFile << "ENTRY\n";
903         } else if (node->IsExitNode()) {
904             fcdgFile << "EXIT\n";
905         }
906         fcdgFile << "BB_" << bb->GetId() << " Label_" << bb->GetLabIdx() << ":\n";
907         fcdgFile << "  { " << bb->GetKindName() << " }\"];\n";
908     }
909     fcdgFile << "\n";
910 
911     // Dump edges style
912     for (auto edge : allEdges) {
913         CDGNode &fromNode = edge->GetFromNode();
914         CDGNode &toNode = edge->GetToNode();
915         fcdgFile << "  BB_" << fromNode.GetBB()->GetId() << " -> "
916                  << "BB_" << toNode.GetBB()->GetId();
917         fcdgFile << " [label = \"";
918         fcdgFile << edge->GetCondition() << "\"];\n";
919     }
920     fcdgFile << "\n";
921 
922     // Dump region style using cluster in dot language
923     for (auto region : allRegions) {
924         if (region == nullptr) {
925             continue;
926         }
927         CHECK_FATAL(region->GetRegionNodeSize() != 0, "invalid region");
928         fcdgFile << "  subgraph cluster_" << region->GetRegionId() << " {\n";
929         fcdgFile << "    color=red;\n";
930         fcdgFile << "    label = \"region #" << region->GetRegionId() << "\";\n";
931         MapleVector<CDGNode *> &memberNodes = region->GetRegionNodes();
932         for (auto node : memberNodes) {
933             fcdgFile << "    BB_" << node->GetBB()->GetId() << ";\n";
934         }
935         fcdgFile << "}\n\n";
936     }
937 
938     fcdgFile << "}\n";
939     (void)fcdgFile.flush();
940     fcdgFile.close();
941     (void)std::cout.rdbuf(coutBuf);
942 }
943 
GenerateCFGDot() const944 void ControlDepAnalysis::GenerateCFGDot() const
945 {
946     std::streambuf *coutBuf = std::cout.rdbuf();
947     std::ofstream cfgFile;
948     std::streambuf *fileBuf = cfgFile.rdbuf();
949     (void)std::cout.rdbuf(fileBuf);
950 
951     // Define the output file name
952     std::string fileName;
953     (void)fileName.append("cfg_after_cdg_");
954     (void)fileName.append(cgFunc.GetName());
955     (void)fileName.append(".dot");
956 
957     cfgFile.open(fileName, std::ios::trunc);
958     if (!cfgFile.is_open()) {
959         LogInfo::MapleLogger(kLlWarn) << "fileName:" << fileName << " open failed.\n";
960         return;
961     }
962 
963     cfgFile << "digraph CFG_" << cgFunc.GetName() << " {\n\n";
964     cfgFile << "  node [shape=box];\n\n";
965 
966     // Dump nodes style
967     FOR_ALL_BB_CONST(bb, &cgFunc)
968     {
969         if (bb->IsUnreachable()) {
970             continue;
971         }
972         cfgFile << "  BB_" << bb->GetId();
973         cfgFile << "[label= \"";
974         if (bb == cgFunc.GetFirstBB()) {
975             cfgFile << "ENTRY\n";
976         }
977         cfgFile << "BB_" << bb->GetId() << " Label_" << bb->GetLabIdx() << ":\n";
978         cfgFile << "  { " << bb->GetKindName() << " }\"];\n";
979     }
980     BB *exitBB = cgFunc.GetCommonExitBB();
981     cfgFile << "  BB_" << exitBB->GetId();
982     cfgFile << "[label= \"EXIT\n";
983     cfgFile << "BB_" << exitBB->GetId() << "\"];\n";
984     cfgFile << "\n";
985 
986     // Dump edges style
987     for (auto cfgEdge : cfgMST->GetAllEdges()) {
988         BB *srcBB = cfgEdge->GetSrcBB();
989         BB *destBB = cfgEdge->GetDestBB();
990         CHECK_FATAL(srcBB != nullptr && destBB != nullptr, "get wrong cfg-edge");
991         if (srcBB == cgFunc.GetCommonExitBB()) {
992             continue;
993         }
994         cfgFile << "  BB_" << srcBB->GetId() << " -> "
995                 << "BB_" << destBB->GetId();
996         cfgFile << " [label = \"";
997         cfgFile << cfgEdge->GetCondition() << "\"";
998         if (cfgEdge->IsBackEdge()) {
999             cfgFile << ",color=darkorchid1";
1000         }
1001         cfgFile << "];\n";
1002     }
1003     cfgFile << "\n";
1004 
1005     // Dump region style using cluster in dot language
1006     for (auto region : fcdg->GetAllRegions()) {
1007         if (region == nullptr) {
1008             continue;
1009         }
1010         CHECK_FATAL(region->GetRegionNodeSize() != 0, "invalid region");
1011         cfgFile << "  subgraph cluster_" << region->GetRegionId() << " {\n";
1012         cfgFile << "    color=red;\n";
1013         cfgFile << "    label = \"region #" << region->GetRegionId() << "\";\n";
1014         for (auto cdgNode : region->GetRegionNodes()) {
1015             BB *bb = cdgNode->GetBB();
1016             CHECK_FATAL(bb != nullptr, "get bb from cdgNode failed");
1017             cfgFile << "    BB_" << bb->GetId() << ";\n";
1018         }
1019         cfgFile << "}\n\n";
1020     }
1021 
1022     cfgFile << "}\n";
1023     (void)cfgFile.flush();
1024     cfgFile.close();
1025     (void)std::cout.rdbuf(coutBuf);
1026 }
1027 
GenerateSimplifiedCFGDot() const1028 void ControlDepAnalysis::GenerateSimplifiedCFGDot() const
1029 {
1030     std::streambuf *coutBuf = std::cout.rdbuf();
1031     std::ofstream cfgFile;
1032     std::streambuf *fileBuf = cfgFile.rdbuf();
1033     (void)std::cout.rdbuf(fileBuf);
1034 
1035     // Define the output file name
1036     std::string fileName;
1037     (void)fileName.append("cfg_simplify_");
1038     (void)fileName.append(cgFunc.GetName());
1039     (void)fileName.append(".dot");
1040 
1041     cfgFile.open(fileName.c_str(), std::ios::trunc);
1042     if (!cfgFile.is_open()) {
1043         LogInfo::MapleLogger(kLlWarn) << "fileName:" << fileName << " open failed.\n";
1044         return;
1045     }
1046 
1047     cfgFile << "digraph CFG_SIMPLE" << cgFunc.GetName() << " {\n\n";
1048     cfgFile << "  node [shape=box];\n\n";
1049 
1050     // Dump nodes style
1051     FOR_ALL_BB_CONST(bb, &cgFunc)
1052     {
1053         if (bb->IsUnreachable()) {
1054             continue;
1055         }
1056         cfgFile << "  BB_" << bb->GetId();
1057         cfgFile << "[label= \"";
1058         if (bb == cgFunc.GetFirstBB()) {
1059             cfgFile << "ENTRY\n";
1060         }
1061         cfgFile << bb->GetId() << "\"];\n";
1062     }
1063     BB *exitBB = cgFunc.GetCommonExitBB();
1064     cfgFile << "  BB_" << exitBB->GetId();
1065     cfgFile << "[label= \"EXIT\n";
1066     cfgFile << exitBB->GetId() << "\"];\n";
1067     cfgFile << "\n";
1068 
1069     // Dump edges style
1070     for (auto cfgEdge : cfgMST->GetAllEdges()) {
1071         BB *srcBB = cfgEdge->GetSrcBB();
1072         BB *destBB = cfgEdge->GetDestBB();
1073         CHECK_FATAL(srcBB != nullptr && destBB != nullptr, "get wrong cfg-edge");
1074         if (srcBB == cgFunc.GetCommonExitBB()) {
1075             continue;
1076         }
1077         cfgFile << "  BB_" << srcBB->GetId() << " -> "
1078                 << "BB_" << destBB->GetId();
1079         cfgFile << " [label = \"";
1080         cfgFile << cfgEdge->GetCondition() << "\"";
1081         if (cfgEdge->IsBackEdge()) {
1082             cfgFile << ",color=darkorchid1";
1083         }
1084         cfgFile << "];\n";
1085     }
1086 
1087     cfgFile << "}\n";
1088     (void)cfgFile.flush();
1089     cfgFile.close();
1090     (void)std::cout.rdbuf(coutBuf);
1091 }
1092 
GenerateCFGInRegionDot(CDGRegion & region) const1093 void ControlDepAnalysis::GenerateCFGInRegionDot(CDGRegion &region) const
1094 {
1095     std::streambuf *coutBuf = std::cout.rdbuf();
1096     std::ofstream cfgOfRFile;
1097     std::streambuf *fileBuf = cfgOfRFile.rdbuf();
1098     (void)std::cout.rdbuf(fileBuf);
1099 
1100     // Define the output file name
1101     std::string fileName;
1102     (void)fileName.append("cfg_region");
1103     (void)fileName.append(std::to_string(region.GetRegionId()));
1104     (void)fileName.append("_");
1105     (void)fileName.append(cgFunc.GetName());
1106     (void)fileName.append(".dot");
1107 
1108     cfgOfRFile.open(fileName.c_str(), std::ios::trunc);
1109     if (!cfgOfRFile.is_open()) {
1110         LogInfo::MapleLogger(kLlWarn) << "fileName:" << fileName << " open failed.\n";
1111         return;
1112     }
1113 
1114     cfgOfRFile << "digraph CFG_REGION" << region.GetRegionId() << " {\n\n";
1115     cfgOfRFile << "  node [shape=box];\n\n";
1116 
1117     for (auto cdgNode : region.GetRegionNodes()) {
1118         BB *bb = cdgNode->GetBB();
1119         CHECK_FATAL(bb != nullptr, "get bb from cdgNode failed");
1120 
1121         for (auto succ = bb->GetSuccsBegin(); succ != bb->GetSuccsEnd(); ++succ) {
1122             CDGNode *node = (*succ)->GetCDGNode();
1123             CHECK_FATAL(node != nullptr, "get cdgNode from bb failed");
1124             if (node->GetRegion() == &region) {
1125                 cfgOfRFile << "\tbb_" << bb->GetId() << " -> "
1126                            << "bb_" << (*succ)->GetId() << "\n";
1127             }
1128         }
1129     }
1130     cfgOfRFile << "}\n";
1131     (void)cfgOfRFile.flush();
1132     cfgOfRFile.close();
1133     (void)std::cout.rdbuf(coutBuf);
1134 }
1135 
GetAnalysisDependence(maple::AnalysisDep & aDep) const1136 void CgControlDepAnalysis::GetAnalysisDependence(maple::AnalysisDep &aDep) const
1137 {
1138     aDep.AddRequired<CgDomAnalysis>();
1139     aDep.AddRequired<CgPostDomAnalysis>();
1140     aDep.AddRequired<CgLoopAnalysis>();
1141     aDep.SetPreservedAll();
1142 }
1143 
PhaseRun(maplebe::CGFunc & f)1144 bool CgControlDepAnalysis::PhaseRun(maplebe::CGFunc &f)
1145 {
1146     MemPool *cdgMemPool = GetPhaseMemPool();
1147     MemPool *tmpMemPool = ApplyTempMemPool();
1148     CHECK_FATAL(cdgMemPool != nullptr && tmpMemPool != nullptr, "get memPool failed");
1149     DomAnalysis *domInfo = GET_ANALYSIS(CgDomAnalysis, f);
1150     CHECK_FATAL(domInfo != nullptr, "get result of DomAnalysis failed");
1151     PostDomAnalysis *pdomInfo = GET_ANALYSIS(CgPostDomAnalysis, f);
1152     CHECK_FATAL(pdomInfo != nullptr, "get result of PostDomAnalysis failed");
1153     LoopAnalysis *loopInfo = GET_ANALYSIS(CgLoopAnalysis, f);
1154     CHECK_FATAL(loopInfo != nullptr, "get result of LoopAnalysis failed");
1155     auto *cfgMST = cdgMemPool->New<CFGMST<BBEdge<maplebe::BB>, maplebe::BB>>(*cdgMemPool);
1156     cda = f.IsAfterRegAlloc() ? cdgMemPool->New<ControlDepAnalysis>(f, *cdgMemPool, "localschedule", true)
1157                               : cdgMemPool->New<ControlDepAnalysis>(f, *cdgMemPool, *tmpMemPool, *domInfo, *pdomInfo,
1158                                                                     *loopInfo, cfgMST, "globalschedule");
1159     cda->Run();
1160     return true;
1161 }
1162 MAPLE_ANALYSIS_PHASE_REGISTER(CgControlDepAnalysis, cgcontroldepanalysis)
1163 }  // namespace maplebe
1164