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