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 *> ®ionMembers, 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 ®ion, 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() == ®ion) {
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 *> ®ionNodes = 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 *> ®ionCDs = 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 ®ion, 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() == ®ion) {
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() == ®ion) {
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 ®ion, std::vector<BB *> ®ionCFG, 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() != ®ion) {
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 ®ion, 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() == ®ion && 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 ®ion) 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() == ®ion) {
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