• 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 #ifndef MAPLE_ME_INCLUDE_DOMINANCE_H
17 #define MAPLE_ME_INCLUDE_DOMINANCE_H
18 #include "mpl_number.h"
19 #include "mempool.h"
20 #include "mempool_allocator.h"
21 #include "types_def.h"
22 #include "base_graph_node.h"
23 namespace maple {
24 class Dominance {
25 public:
26     using NodeId = uint32;
27 
Dominance(MemPool & memPool,MapleVector<BaseGraphNode * > & nodeVec,BaseGraphNode & commonEntryNode,BaseGraphNode & commonExitNode,bool isPdom)28     Dominance(MemPool &memPool, MapleVector<BaseGraphNode *> &nodeVec, BaseGraphNode &commonEntryNode,
29               BaseGraphNode &commonExitNode, bool isPdom)
30         : domAllocator(&memPool),
31           nodeVec(nodeVec),
32           commonEntryNode(commonEntryNode),
33           commonExitNode(commonExitNode),
34           isPdom(isPdom),
35           postOrderIDVec(nodeVec.size(), -1, domAllocator.Adapter()),
36           reversePostOrder(domAllocator.Adapter()),
37           reversePostOrderId(domAllocator.Adapter()),
38           doms(domAllocator.Adapter()),
39           domFrontier(nodeVec.size(), MapleSet<NodeId>(domAllocator.Adapter()), domAllocator.Adapter()),
40           domChildren(nodeVec.size(), MapleVector<NodeId>(domAllocator.Adapter()), domAllocator.Adapter()),
41           iterDomFrontier(nodeVec.size(), MapleSet<NodeId>(domAllocator.Adapter()), domAllocator.Adapter()),
42           dtPreOrder(nodeVec.size(), NodeId(0), domAllocator.Adapter()),
43           dtDfn(nodeVec.size(), -1, domAllocator.Adapter())
44     {
45     }
46 
47     ~Dominance() = default;
48 
GetNodeVec()49     const MapleVector<BaseGraphNode *> &GetNodeVec() const
50     {
51         return nodeVec;
52     }
53 
IsNodeVecEmpty()54     bool IsNodeVecEmpty() const
55     {
56         return nodeVec.empty();
57     }
58 
GetNodeVecSize()59     size_t GetNodeVecSize() const
60     {
61         return nodeVec.size();
62     }
63 
GetNodeAt(size_t i)64     BaseGraphNode *GetNodeAt(size_t i) const
65     {
66         return nodeVec.at(i);
67     }
68 
GetCommonEntryNode()69     const BaseGraphNode &GetCommonEntryNode() const
70     {
71         return commonEntryNode;
72     }
73 
GetCommonExitNode()74     const BaseGraphNode &GetCommonExitNode() const
75     {
76         return commonExitNode;
77     }
78 
GetReversePostOrder(size_t idx)79     const BaseGraphNode *GetReversePostOrder(size_t idx) const
80     {
81         return reversePostOrder[idx];
82     }
83 
GetReversePostOrder()84     const MapleVector<BaseGraphNode *> &GetReversePostOrder() const
85     {
86         return reversePostOrder;
87     }
88 
GetReversePostOrder()89     MapleVector<BaseGraphNode *> &GetReversePostOrder()
90     {
91         return reversePostOrder;
92     }
93 
GetReversePostOrderId()94     const MapleVector<uint32> &GetReversePostOrderId()
95     {
96         if (reversePostOrderId.empty()) {
97             reversePostOrderId.resize(nodeVec.size(), 0);
98             for (size_t id = 0; id < reversePostOrder.size(); ++id) {
99                 reversePostOrderId[reversePostOrder[id]->GetID()] = static_cast<uint32>(id);
100             }
101         }
102         return reversePostOrderId;
103     }
104 
GetDom(NodeId id)105     BaseGraphNode *GetDom(NodeId id)
106     {
107         auto it = doms.find(id);
108         if (it == doms.end()) {
109             return nullptr;
110         }
111         return it->second;
112     }
113 
GetDomFrontier(size_t idx)114     MapleSet<NodeId> &GetDomFrontier(size_t idx)
115     {
116         return domFrontier[idx];
117     }
118 
GetDomFrontier(size_t idx)119     const MapleSet<NodeId> &GetDomFrontier(size_t idx) const
120     {
121         return domFrontier.at(idx);
122     }
123 
GetDomFrontierSize()124     size_t GetDomFrontierSize() const
125     {
126         return domFrontier.size();
127     }
128 
GetIterDomFrontier(const NodeId & idx)129     const MapleSet<NodeId> &GetIterDomFrontier(const NodeId &idx) const
130     {
131         return iterDomFrontier[idx];
132     }
133 
GetIterDomFrontier(const NodeId & idx)134     MapleSet<NodeId> &GetIterDomFrontier(const NodeId &idx)
135     {
136         return iterDomFrontier[idx];
137     }
138 
GetIterDomFrontierSize()139     size_t GetIterDomFrontierSize() const
140     {
141         return iterDomFrontier.size();
142     }
143 
GetDomChildren(const NodeId & idx)144     const MapleVector<NodeId> &GetDomChildren(const NodeId &idx) const
145     {
146         return domChildren[idx];
147     }
148 
GetDomChildren(const NodeId & idx)149     MapleVector<NodeId> &GetDomChildren(const NodeId &idx)
150     {
151         return domChildren[idx];
152     }
153 
GetDomChildrenSize()154     size_t GetDomChildrenSize() const
155     {
156         return domChildren.size();
157     }
158 
GetDtPreOrderItem(size_t idx)159     const NodeId &GetDtPreOrderItem(size_t idx) const
160     {
161         return dtPreOrder[idx];
162     }
163 
GetDtPreOrder()164     const MapleVector<NodeId> &GetDtPreOrder() const
165     {
166         return dtPreOrder;
167     }
168 
GetDtPreOrderSize()169     size_t GetDtPreOrderSize() const
170     {
171         return dtPreOrder.size();
172     }
173 
GetDtDfnItem(size_t idx)174     uint32 GetDtDfnItem(size_t idx) const
175     {
176         return dtDfn[idx];
177     }
178 
GetDtDfnSize()179     size_t GetDtDfnSize() const
180     {
181         return dtDfn.size();
182     }
183 
DumpDoms()184     void DumpDoms() const
185     {
186         const std::string tag = isPdom ? "pdom" : "dom";
187         for (auto &node : reversePostOrder) {
188             auto nodeId = node->GetID();
189             LogInfo::MapleLogger() << tag << "_postorder no " << postOrderIDVec[nodeId];
190             LogInfo::MapleLogger() << " is node:" << nodeId;
191             LogInfo::MapleLogger() << " im_" << tag << " is node:" << doms.at(nodeId)->GetID();
192             LogInfo::MapleLogger() << " " << tag << "frontier: [";
193             for (auto &id : domFrontier[nodeId]) {
194                 LogInfo::MapleLogger() << id << " ";
195             }
196             LogInfo::MapleLogger() << "] iter" << tag << "Frontier: [";
197             for (auto &id : iterDomFrontier[nodeId]) {
198                 LogInfo::MapleLogger() << id << " ";
199             }
200             LogInfo::MapleLogger() << "] " << tag << "children: [";
201             for (auto &id : domChildren[nodeId]) {
202                 LogInfo::MapleLogger() << id << " ";
203             }
204             LogInfo::MapleLogger() << "]\n";
205         }
206         LogInfo::MapleLogger() << "\npreorder traversal of " << tag << " tree:";
207         for (auto &id : dtPreOrder) {
208             LogInfo::MapleLogger() << id << " ";
209         }
210         LogInfo::MapleLogger() << "\n\n";
211     }
212 
Init()213     void Init()
214     {
215         GenPostOrderID();
216         ComputeDominance();
217         ComputeDomFrontiers();
218         ComputeDomChildren();
219         ComputeIterDomFrontiers();
220         size_t num = 0;
221         ComputeDtPreorder(num);
222         dtPreOrder.resize(num);
223         ComputeDtDfn();
224     }
225 
226     // true if b1 dominates b2
Dominate(const BaseGraphNode & node1,const BaseGraphNode & node2)227     bool Dominate(const BaseGraphNode &node1, const BaseGraphNode &node2) const
228     {
229         if (&node1 == &node2) {
230             return true;
231         }
232         const auto *iDom = &node2;
233         while (iDom != &commonEntryNode) {
234             auto it = doms.find(iDom->GetID());
235             if (it == doms.end() || it->second == nullptr) {
236                 return false;
237             }
238             iDom = it->second;
239             if (iDom == &node1) {
240                 return true;
241             }
242         }
243         return false;
244     }
245 
246     // true if b1 dominates b2
Dominate(const uint32 nodeId1,const uint32 nodeId2)247     bool Dominate(const uint32 nodeId1, const uint32 nodeId2) const
248     {
249         if (nodeId1 == nodeId2) {
250             return true;
251         }
252         uint32 curId = nodeId2;
253         while (curId != commonEntryNode.GetID()) {
254             auto it = doms.find(curId);
255             if (it == doms.end() || it->second == nullptr) {
256                 return false;
257             }
258             curId = it->second->GetID();
259             if (curId == nodeId1) {
260                 return true;
261             }
262         }
263         return false;
264     }
265 
266 private:
GenPostOrderID()267     void GenPostOrderID()
268     {
269         DEBUG_ASSERT(!nodeVec.empty(), "size to be allocated is 0");
270         std::vector<bool> visitedMap(nodeVec.size(), false);
271         size_t postOrderID = 0;
272         PostOrderWalk(commonEntryNode, postOrderID, visitedMap);
273         // initialize reversePostOrder
274         reversePostOrder.resize(postOrderID);
275         CHECK_FATAL(postOrderID > 0, "must not be zero");
276         auto maxPostOrderID = postOrderID - 1;
277         for (size_t i = 0; i < postOrderIDVec.size(); ++i) {
278             auto postOrderNo = postOrderIDVec[i];
279             if (postOrderNo == -1) {
280                 continue;
281             }
282             reversePostOrder[maxPostOrderID - static_cast<uint32>(postOrderNo)] = nodeVec[i];
283         }
284     }
285 
286     // Figure 5 in "A Simple, Fast Dominance Algorithm" by Keith Cooper et al.
ComputeDomFrontiers()287     void ComputeDomFrontiers()
288     {
289         constexpr uint32 kNodeVectorInitialSize = 2;
290         for (const auto node : nodeVec) {
291             if (node == nullptr || node == &commonExitNode) {
292                 continue;
293             }
294             std::vector<BaseGraphNode *> prevNodes;
295             GetPrevNodesToVisit(*node, prevNodes);
296 
297             if (prevNodes.size() < kNodeVectorInitialSize) {
298                 continue;
299             }
300             for (auto *pre : prevNodes) {
301                 auto runner = pre;
302                 while (runner != doms.at(node->GetID()) && runner != &commonEntryNode) {
303                     (void)domFrontier[runner->GetID()].insert(node->GetID());
304                     runner = doms.at(runner->GetID());
305                 }
306             }
307         }
308     }
309 
ComputeDomChildren()310     void ComputeDomChildren()
311     {
312         for (const auto node : reversePostOrder) {
313             if (node == nullptr) {
314                 continue;
315             }
316             auto *parent = doms.at(node->GetID());
317             if (parent == nullptr || parent == node) {
318                 continue;
319             }
320             domChildren[parent->GetID()].push_back(node->GetID());
321         }
322     }
323 
ComputeIterDomFrontiers()324     void ComputeIterDomFrontiers()
325     {
326         for (auto &node : nodeVec) {
327             if (node == nullptr || node == &commonExitNode) {
328                 continue;
329             }
330             std::vector<bool> visitedMap(nodeVec.size(), false);
331             GetIterDomFrontier(*node, iterDomFrontier[node->GetID()], node->GetID(), visitedMap);
332         }
333     }
334 
ComputeDtPreorder(size_t & num)335     void ComputeDtPreorder(size_t &num)
336     {
337         ComputeDtPreorder(commonEntryNode, num);
338     }
339 
ComputeDtDfn()340     void ComputeDtDfn()
341     {
342         for (size_t i = 0; i < dtPreOrder.size(); ++i) {
343             dtDfn[dtPreOrder[i]] = static_cast<uint32>(i);
344         }
345     }
346 
347     // Figure 3 in "A Simple, Fast Dominance Algorithm" by Keith Cooper et al.
ComputeDominance()348     void ComputeDominance()
349     {
350         doms[commonEntryNode.GetID()] = &commonEntryNode;
351         bool changed;
352         do {
353             changed = false;
354             for (size_t i = 1; i < reversePostOrder.size(); ++i) {
355                 auto node = reversePostOrder[i];
356                 BaseGraphNode *pre = nullptr;
357                 std::vector<BaseGraphNode *> prevNodes;
358                 GetPrevNodesToVisit(*node, prevNodes);
359                 auto numOfPrevNodes = prevNodes.size();
360                 if (InitNodeIsPred(*node) || numOfPrevNodes == 0) {
361                     pre = &commonEntryNode;
362                 } else {
363                     pre = prevNodes[0];
364                 }
365                 size_t j = 1;
366                 while ((doms[pre->GetID()] == nullptr || pre == node) && j < numOfPrevNodes) {
367                     pre = prevNodes[j];
368                     ++j;
369                 }
370                 BaseGraphNode *newIDom = pre;
371                 for (; j < numOfPrevNodes; ++j) {
372                     pre = prevNodes[j];
373                     if (doms[pre->GetID()] != nullptr && pre != node) {
374                         newIDom = Intersect(*pre, *newIDom);
375                     }
376                 }
377                 if (doms[node->GetID()] != newIDom) {
378                     doms[node->GetID()] = newIDom;
379                     changed = true;
380                 }
381             }
382         } while (changed);
383     }
384 
Intersect(BaseGraphNode & node1,const BaseGraphNode & node2)385     BaseGraphNode *Intersect(BaseGraphNode &node1, const BaseGraphNode &node2) const
386     {
387         auto *ptrNode1 = &node1;
388         auto *ptrNode2 = &node2;
389         while (ptrNode1 != ptrNode2) {
390             while (postOrderIDVec[ptrNode1->GetID()] < postOrderIDVec[ptrNode2->GetID()]) {
391                 ptrNode1 = doms.at(ptrNode1->GetID());
392             }
393             while (postOrderIDVec[ptrNode2->GetID()] < postOrderIDVec[ptrNode1->GetID()]) {
394                 ptrNode2 = doms.at(ptrNode2->GetID());
395             }
396         }
397         return ptrNode1;
398     }
399 
InitNodeIsPred(const BaseGraphNode & node)400     bool InitNodeIsPred(const BaseGraphNode &node) const
401     {
402         std::vector<BaseGraphNode *> succNodes;
403         GetNextNodesToVisit(commonEntryNode, succNodes);
404         for (const auto &suc : succNodes) {
405             if (suc == &node) {
406                 return true;
407             }
408         }
409         return false;
410     }
411 
PostOrderWalk(const BaseGraphNode & root,size_t & pid,std::vector<bool> & visitedMap)412     void PostOrderWalk(const BaseGraphNode &root, size_t &pid, std::vector<bool> &visitedMap)
413     {
414         std::stack<const BaseGraphNode *> s;
415         s.push(&root);
416         visitedMap[root.GetID()] = true;
417         while (!s.empty()) {
418             auto node = s.top();
419             auto nodeId = node->GetID();
420             if (nodeVec[nodeId] == nullptr) {
421                 s.pop();
422                 continue;
423             }
424             DEBUG_ASSERT(nodeId < visitedMap.size() && nodeId < postOrderIDVec.size(), "index out of range");
425             bool tail = true;
426             std::vector<BaseGraphNode *> succNodes;
427             GetNextNodesToVisit(*node, succNodes);
428             for (auto succ : succNodes) {
429                 if (!visitedMap[succ->GetID()]) {
430                     tail = false;
431                     visitedMap[succ->GetID()] = true;
432                     s.push(succ);
433                     break;
434                 }
435             }
436             if (tail) {
437                 s.pop();
438                 postOrderIDVec[nodeId] = static_cast<int32>(pid++);
439             }
440         }
441     }
442 
ComputeDtPreorder(const BaseGraphNode & node,size_t & num)443     void ComputeDtPreorder(const BaseGraphNode &node, size_t &num)
444     {
445         CHECK_FATAL(num < dtPreOrder.size(), "index out of range");
446         dtPreOrder[num++] = node.GetID();
447         for (auto &k : domChildren[node.GetID()]) {
448             ComputeDtPreorder(*nodeVec[k], num);
449         }
450     }
451 
GetNextNodesToVisit(const BaseGraphNode & node,std::vector<BaseGraphNode * > & nodesToVisit)452     void GetNextNodesToVisit(const BaseGraphNode &node, std::vector<BaseGraphNode *> &nodesToVisit) const
453     {
454         if (isPdom) {
455             node.GetInNodes(nodesToVisit);
456         } else {
457             node.GetOutNodes(nodesToVisit);
458         }
459     }
460 
GetPrevNodesToVisit(const BaseGraphNode & node,std::vector<BaseGraphNode * > & nodesToVisit)461     void GetPrevNodesToVisit(const BaseGraphNode &node, std::vector<BaseGraphNode *> &nodesToVisit) const
462     {
463         if (isPdom) {
464             node.GetOutNodes(nodesToVisit);
465         } else {
466             node.GetInNodes(nodesToVisit);
467         }
468     }
469 
470     // nodeIdMarker indicates that the iterDomFrontier results for nodeId < nodeIdMarker have been computed
GetIterDomFrontier(const BaseGraphNode & node,MapleSet<NodeId> & dfSet,const NodeId & nodeIdMarker,std::vector<bool> & visitedMap)471     void GetIterDomFrontier(const BaseGraphNode &node, MapleSet<NodeId> &dfSet, const NodeId &nodeIdMarker,
472                             std::vector<bool> &visitedMap)
473     {
474         if (visitedMap[node.GetID()]) {
475             return;
476         }
477         visitedMap[node.GetID()] = true;
478         for (auto frontierNodeId : domFrontier[node.GetID()]) {
479             (void)dfSet.insert(frontierNodeId);
480             if (frontierNodeId < nodeIdMarker) {  // union with its computed result
481                 dfSet.insert(iterDomFrontier[frontierNodeId].cbegin(), iterDomFrontier[frontierNodeId].cend());
482             } else {  // recursive call
483                 auto frontierNode = nodeVec[frontierNodeId];
484                 if (frontierNode == nullptr) {
485                     continue;
486                 }
487                 GetIterDomFrontier(*frontierNode, dfSet, nodeIdMarker, visitedMap);
488             }
489         }
490     }
491 
492     MapleAllocator domAllocator;  // stores the analysis results
493     MapleVector<BaseGraphNode *> &nodeVec;
494     BaseGraphNode &commonEntryNode;
495     BaseGraphNode &commonExitNode;
496     bool isPdom;
497     MapleVector<int32> postOrderIDVec;                // index is node id
498     MapleVector<BaseGraphNode *> reversePostOrder;    // an ordering of the node in reverse postorder
499     MapleVector<uint32> reversePostOrderId;           // gives position of each node in reversePostOrder
500     MapleUnorderedMap<NodeId, BaseGraphNode *> doms;  // index is node id; immediate dominator for each node
501     MapleVector<MapleSet<NodeId>> domFrontier;        // index is node id
502     MapleVector<MapleVector<NodeId>> domChildren;     // index is node id; for dom tree
503     MapleVector<MapleSet<NodeId>> iterDomFrontier;    // index is node id
504     MapleVector<NodeId> dtPreOrder;  // ordering of the nodes in a preorder traversal of the dominator tree
505     MapleVector<uint32> dtDfn;       // gives position of each node in dt_preorder
506 };
507 }  // namespace maple
508 #endif  // MAPLE_UTIL_INCLUDE_DOMINANCE_H
509