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_BB_H 17 #define MAPLE_ME_INCLUDE_BB_H 18 #include "utils.h" 19 #include "mpl_number.h" 20 #include "ptr_list_ref.h" 21 #include "orig_symbol.h" 22 #include "ver_symbol.h" 23 #include "ssa.h" 24 #include "scc.h" 25 #include "base_graph_node.h" 26 27 namespace maple { 28 class MeStmt; // circular dependency exists, no other choice 29 class MePhiNode; // circular dependency exists, no other choice 30 class PiassignMeStmt; // circular dependency exists, no other choice 31 class IRMap; // circular dependency exists, no other choice 32 enum BBKind { 33 kBBUnknown, // uninitialized 34 kBBCondGoto, 35 kBBGoto, // unconditional branch 36 kBBFallthru, 37 kBBReturn, 38 kBBAfterGosub, // the BB that follows a gosub, as it is an entry point 39 kBBSwitch, 40 kBBIgoto, 41 kBBInvalid 42 }; 43 44 enum BBAttr : uint32 { 45 kBBAttrIsEntry = utils::bit_field_v<1>, 46 kBBAttrIsExit = utils::bit_field_v<2>, 47 kBBAttrWontExit = utils::bit_field_v<3>, 48 kBBAttrIsTry = utils::bit_field_v<4>, 49 kBBAttrIsTryEnd = utils::bit_field_v<5>, 50 kBBAttrIsJSCatch = utils::bit_field_v<6>, 51 kBBAttrIsJSFinally = utils::bit_field_v<7>, 52 kBBAttrIsCatch = utils::bit_field_v<8>, 53 kBBAttrArtificial = utils::bit_field_v<10>, 54 kBBAttrIsInLoop = utils::bit_field_v<11>, 55 kBBAttrIsInLoopForEA = utils::bit_field_v<12>, 56 kBBAttrIsInstrument = utils::bit_field_v<13> 57 }; 58 59 constexpr uint32 kBBVectorInitialSize = 2; 60 using StmtNodes = PtrListRef<StmtNode>; 61 using MeStmts = PtrListRef<MeStmt>; 62 63 class BB : public BaseGraphNode { 64 public: 65 using BBId = utils::Index<BB>; 66 BB(MapleAllocator * alloc,MapleAllocator * versAlloc,BBId id)67 BB(MapleAllocator *alloc, MapleAllocator *versAlloc, BBId id) 68 : id(id), 69 pred(kBBVectorInitialSize, nullptr, alloc->Adapter()), 70 succ(kBBVectorInitialSize, nullptr, alloc->Adapter()), 71 succFreq(alloc->Adapter()), 72 phiList(versAlloc->Adapter()), 73 mePhiList(alloc->Adapter()), 74 meVarPiList(alloc->Adapter()), 75 group(this) 76 { 77 pred.pop_back(); 78 pred.pop_back(); 79 succ.pop_back(); 80 succ.pop_back(); 81 } 82 BB(MapleAllocator * alloc,MapleAllocator * versAlloc,BBId id,StmtNode * firstStmt,StmtNode * lastStmt)83 BB(MapleAllocator *alloc, MapleAllocator *versAlloc, BBId id, StmtNode *firstStmt, StmtNode *lastStmt) 84 : id(id), 85 pred(kBBVectorInitialSize, nullptr, alloc->Adapter()), 86 succ(kBBVectorInitialSize, nullptr, alloc->Adapter()), 87 succFreq(alloc->Adapter()), 88 phiList(versAlloc->Adapter()), 89 mePhiList(alloc->Adapter()), 90 meVarPiList(alloc->Adapter()), 91 stmtNodeList(firstStmt, lastStmt), 92 group(this) 93 { 94 pred.pop_back(); 95 pred.pop_back(); 96 succ.pop_back(); 97 succ.pop_back(); 98 } 99 100 virtual ~BB() = default; GetSCCNode()101 SCCNode<BB> *GetSCCNode() 102 { 103 return sccNode; 104 } SetSCCNode(SCCNode<BB> * scc)105 void SetSCCNode(SCCNode<BB> *scc) 106 { 107 sccNode = scc; 108 } 109 GetIdentity()110 const std::string GetIdentity() 111 { 112 return "BBId: " + std::to_string(GetID()); 113 } 114 GetOutNodes(std::vector<BaseGraphNode * > & outNodes)115 void GetOutNodes(std::vector<BaseGraphNode *> &outNodes) const final 116 { 117 outNodes.resize(succ.size(), nullptr); 118 std::copy(succ.begin(), succ.end(), outNodes.begin()); 119 } 120 GetOutNodes(std::vector<BaseGraphNode * > & outNodes)121 void GetOutNodes(std::vector<BaseGraphNode *> &outNodes) final 122 { 123 static_cast<const BB *>(this)->GetOutNodes(outNodes); 124 } 125 GetInNodes(std::vector<BaseGraphNode * > & inNodes)126 void GetInNodes(std::vector<BaseGraphNode *> &inNodes) const final 127 { 128 inNodes.resize(pred.size(), nullptr); 129 std::copy(pred.begin(), pred.end(), inNodes.begin()); 130 } 131 GetInNodes(std::vector<BaseGraphNode * > & inNodes)132 void GetInNodes(std::vector<BaseGraphNode *> &inNodes) final 133 { 134 static_cast<const BB *>(this)->GetInNodes(inNodes); 135 } 136 GetAttributes(uint32 attrKind)137 bool GetAttributes(uint32 attrKind) const 138 { 139 return (attributes & attrKind) != 0; 140 } 141 GetAttributes()142 uint32 GetAttributes() const 143 { 144 return attributes; 145 } 146 SetAttributes(uint32 attrKind)147 void SetAttributes(uint32 attrKind) 148 { 149 attributes |= attrKind; 150 } 151 ClearAttributes(uint32 attrKind)152 void ClearAttributes(uint32 attrKind) 153 { 154 attributes &= (~attrKind); 155 } 156 IsGoto()157 virtual bool IsGoto() const 158 { 159 return kind == kBBGoto; 160 } 161 AddBackEndTry()162 virtual bool AddBackEndTry() const 163 { 164 return GetAttributes(kBBAttrIsTryEnd); 165 } 166 167 void Dump(const MIRModule *mod); 168 void DumpHeader(const MIRModule *mod) const; 169 void DumpPhi(); 170 void DumpBBAttribute(const MIRModule *mod) const; 171 std::string StrAttribute() const; 172 173 // Only use for common entry bb AddEntry(BB & bb)174 void AddEntry(BB &bb) 175 { 176 succ.push_back(&bb); 177 } 178 179 // Only use for common exit bb AddExit(BB & bb)180 void AddExit(BB &bb) 181 { 182 pred.push_back(&bb); 183 } 184 185 // This is to help new bb to keep some flags from original bb after logically splitting. CopyFlagsAfterSplit(const BB & bb)186 void CopyFlagsAfterSplit(const BB &bb) 187 { 188 bb.GetAttributes(kBBAttrIsTry) ? SetAttributes(kBBAttrIsTry) : ClearAttributes(kBBAttrIsTry); 189 bb.GetAttributes(kBBAttrIsTryEnd) ? SetAttributes(kBBAttrIsTryEnd) : ClearAttributes(kBBAttrIsTryEnd); 190 bb.GetAttributes(kBBAttrIsExit) ? SetAttributes(kBBAttrIsExit) : ClearAttributes(kBBAttrIsExit); 191 bb.GetAttributes(kBBAttrWontExit) ? SetAttributes(kBBAttrWontExit) : ClearAttributes(kBBAttrWontExit); 192 } 193 GetBBId()194 BBId GetBBId() const 195 { 196 return id; 197 } 198 SetBBId(BBId idx)199 void SetBBId(BBId idx) 200 { 201 id = idx; 202 } 203 UintID()204 uint32 UintID() const 205 { 206 return static_cast<uint32>(id); 207 } 208 GetID()209 uint32 GetID() const 210 { 211 return static_cast<uint32>(id); 212 } 213 IsEmpty()214 bool IsEmpty() const 215 { 216 return stmtNodeList.empty(); 217 } 218 SetFirst(StmtNode * stmt)219 void SetFirst(StmtNode *stmt) 220 { 221 stmtNodeList.update_front(stmt); 222 } 223 SetLast(StmtNode * stmt)224 void SetLast(StmtNode *stmt) 225 { 226 stmtNodeList.update_back(stmt); 227 } 228 229 // should test IsEmpty first GetFirst()230 StmtNode &GetFirst() 231 { 232 return stmtNodeList.front(); 233 } 234 // should test IsEmpty first GetFirst()235 const StmtNode &GetFirst() const 236 { 237 return stmtNodeList.front(); 238 } 239 240 // should test IsEmpty first GetLast()241 StmtNode &GetLast() 242 { 243 return stmtNodeList.back(); 244 } 245 // should test IsEmpty first GetLast()246 const StmtNode &GetLast() const 247 { 248 return stmtNodeList.back(); 249 } 250 251 void SetFirstMe(MeStmt *stmt); 252 void SetLastMe(MeStmt *stmt); 253 MeStmt *GetFirstMe(); 254 const MeStmt *GetFirstMe() const; 255 256 void DumpMeBB(const IRMap &irMap); 257 void MoveAllPredToSucc(BB *newSucc, BB *commonEntry); 258 void MoveAllSuccToPred(BB *newPred, BB *commonExit); 259 void RemoveStmtNode(StmtNode *stmt); 260 InsertPi(BB & bb,PiassignMeStmt & s)261 void InsertPi(BB &bb, PiassignMeStmt &s) 262 { 263 if (meVarPiList.find(&bb) == meVarPiList.end()) { 264 std::vector<PiassignMeStmt *> tmp; 265 meVarPiList[&bb] = tmp; 266 } 267 meVarPiList[&bb].push_back(&s); 268 } 269 GetPiList()270 MapleMap<BB *, std::vector<PiassignMeStmt *>> &GetPiList() 271 { 272 return meVarPiList; 273 } 274 IsMeStmtEmpty()275 bool IsMeStmtEmpty() const 276 { 277 return meStmtList.empty(); 278 } 279 IsReturnBB()280 bool IsReturnBB() const 281 { 282 return kind == kBBReturn && !stmtNodeList.empty() && stmtNodeList.back().GetOpCode() == OP_return; 283 } 284 285 void FindWillExitBBs(std::vector<bool> &visitedBBs) const; 286 const PhiNode *PhiofVerStInserted(const VersionSt &versionSt) const; 287 bool InsertPhi(MapleAllocator *alloc, VersionSt *versionSt); 288 void PrependMeStmt(MeStmt *meStmt); 289 void RemoveMeStmt(MeStmt *meStmt); 290 void AddMeStmtFirst(MeStmt *meStmt); 291 void AddMeStmtLast(MeStmt *meStmt); 292 void InsertMeStmtBefore(const MeStmt *meStmt, MeStmt *inStmt); 293 void InsertMeStmtAfter(const MeStmt *meStmt, MeStmt *inStmt); 294 void InsertMeStmtLastBr(MeStmt *inStmt); 295 void ReplaceMeStmt(MeStmt *stmt, MeStmt *newStmt); 296 void RemoveLastMeStmt(); 297 void DumpMePhiList(const IRMap *irMap); 298 void DumpMeVarPiList(const IRMap *irMap); 299 void EmitBB(SSATab &ssaTab, BlockNode &curblk, bool needAnotherPass); GetStmtNodes()300 StmtNodes &GetStmtNodes() 301 { 302 return stmtNodeList; 303 } 304 GetStmtNodes()305 const StmtNodes &GetStmtNodes() const 306 { 307 return stmtNodeList; 308 } 309 GetMeStmts()310 MeStmts &GetMeStmts() 311 { 312 return meStmtList; 313 } 314 GetMeStmts()315 const MeStmts &GetMeStmts() const 316 { 317 return meStmtList; 318 } 319 GetBBLabel()320 LabelIdx GetBBLabel() const 321 { 322 return bbLabel; 323 } 324 SetBBLabel(LabelIdx idx)325 void SetBBLabel(LabelIdx idx) 326 { 327 bbLabel = idx; 328 } 329 GetFrequency()330 uint32 GetFrequency() const 331 { 332 return frequency; 333 } 334 SetFrequency(uint32 f)335 void SetFrequency(uint32 f) 336 { 337 frequency = f; 338 } 339 GetKind()340 BBKind GetKind() const 341 { 342 return kind; 343 } 344 SetKind(BBKind bbKind)345 void SetKind(BBKind bbKind) 346 { 347 kind = bbKind; 348 } 349 SetKindReturn()350 void SetKindReturn() 351 { 352 SetKind(kBBReturn); 353 SetAttributes(kBBAttrIsExit); 354 } 355 GetPred()356 const MapleVector<BB *> &GetPred() const 357 { 358 return pred; 359 } 360 GetPred()361 MapleVector<BB *> &GetPred() 362 { 363 return pred; 364 } 365 GetUniquePred()366 BB *GetUniquePred() const 367 { 368 if (pred.empty()) { 369 return nullptr; 370 } 371 if (pred.size() == 1) { 372 return pred.front(); 373 } 374 for (size_t i = 0; i < pred.size(); ++i) { 375 if (pred.at(i) != pred.at(0)) { 376 return nullptr; 377 } 378 } 379 return pred.front(); 380 } 381 GetPred(size_t cnt)382 const BB *GetPred(size_t cnt) const 383 { 384 DEBUG_ASSERT(cnt < pred.size(), "out of range in BB::GetPred"); 385 return pred.at(cnt); 386 } 387 GetPred(size_t cnt)388 BB *GetPred(size_t cnt) 389 { 390 DEBUG_ASSERT(cnt < pred.size(), "out of range in BB::GetPred"); 391 return pred.at(cnt); 392 } 393 SetPred(size_t cnt,BB * pp)394 void SetPred(size_t cnt, BB *pp) 395 { 396 CHECK_FATAL(cnt < pred.size(), "out of range in BB::SetPred"); 397 pred[cnt] = pp; 398 } 399 PushBackSuccFreq(uint64 freq)400 void PushBackSuccFreq(uint64 freq) 401 { 402 return succFreq.push_back(freq); 403 } 404 GetSuccFreq()405 MapleVector<uint64> &GetSuccFreq() 406 { 407 return succFreq; 408 } SetSuccFreq(int idx,uint64 freq)409 void SetSuccFreq(int idx, uint64 freq) 410 { 411 DEBUG_ASSERT(idx >= 0 && static_cast<size_t>(idx) <= succFreq.size(), "sanity check"); 412 succFreq[static_cast<size_t>(idx)] = freq; 413 } 414 GetSucc()415 const MapleVector<BB *> &GetSucc() const 416 { 417 return succ; 418 } 419 GetSucc()420 MapleVector<BB *> &GetSucc() 421 { 422 return succ; 423 } 424 GetUniqueSucc()425 BB *GetUniqueSucc() 426 { 427 if (succ.empty()) { 428 return nullptr; 429 } 430 if (succ.size() == 1) { 431 return succ.front(); 432 } 433 for (size_t i = 0; i < succ.size(); ++i) { 434 if (succ.at(i) != succ.at(0)) { 435 return nullptr; 436 } 437 } 438 return succ.front(); 439 } 440 GetSucc(size_t cnt)441 const BB *GetSucc(size_t cnt) const 442 { 443 DEBUG_ASSERT(cnt < succ.size(), "out of range in BB::GetSucc"); 444 return succ.at(cnt); 445 } 446 GetSucc(size_t cnt)447 BB *GetSucc(size_t cnt) 448 { 449 DEBUG_ASSERT(cnt < succ.size(), "out of range in BB::GetSucc"); 450 return succ.at(cnt); 451 } 452 SetSucc(size_t cnt,BB * ss)453 void SetSucc(size_t cnt, BB *ss) 454 { 455 CHECK_FATAL(cnt < succ.size(), "out of range in BB::SetSucc"); 456 succ[cnt] = ss; 457 } 458 GetPhiList()459 const MapleMap<OStIdx, PhiNode> &GetPhiList() const 460 { 461 return phiList; 462 } GetPhiList()463 MapleMap<OStIdx, PhiNode> &GetPhiList() 464 { 465 return phiList; 466 } ClearPhiList()467 void ClearPhiList() 468 { 469 phiList.clear(); 470 } 471 GetMePhiList()472 MapleMap<OStIdx, MePhiNode *> &GetMePhiList() 473 { 474 return mePhiList; 475 } 476 GetMePhiList()477 const MapleMap<OStIdx, MePhiNode *> &GetMePhiList() const 478 { 479 return mePhiList; 480 } 481 ClearMePhiList()482 void ClearMePhiList() 483 { 484 mePhiList.clear(); 485 } 486 GetEdgeFreq(const BB * bb)487 uint64 GetEdgeFreq(const BB *bb) const 488 { 489 auto iter = std::find(succ.begin(), succ.end(), bb); 490 CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID()); 491 CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size doesn't match succ size"); 492 const size_t idx = static_cast<size_t>(std::distance(succ.begin(), iter)); 493 return succFreq[idx]; 494 } 495 GetEdgeFreq(size_t idx)496 uint64 GetEdgeFreq(size_t idx) const 497 { 498 CHECK_FATAL(idx < succFreq.size(), "out of range in BB::GetEdgeFreq"); 499 CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size doesn't match succ size"); 500 return succFreq[idx]; 501 } 502 SetEdgeFreq(const BB * bb,uint64 freq)503 void SetEdgeFreq(const BB *bb, uint64 freq) 504 { 505 auto iter = std::find(succ.begin(), succ.end(), bb); 506 CHECK_FATAL(iter != std::end(succ), "%d is not the successor of %d", bb->UintID(), this->UintID()); 507 CHECK_FATAL(succ.size() == succFreq.size(), "succfreq size %d doesn't match succ size %d", succFreq.size(), 508 succ.size()); 509 const size_t idx = static_cast<size_t>(std::distance(succ.begin(), iter)); 510 succFreq[idx] = freq; 511 } 512 InitEdgeFreq()513 void InitEdgeFreq() 514 { 515 succFreq.resize(succ.size()); 516 } 517 GetGroup()518 BB *GetGroup() const 519 { 520 return group; 521 } 522 SetGroup(BB * g)523 void SetGroup(BB *g) 524 { 525 group = g; 526 } 527 ClearGroup()528 void ClearGroup() 529 { 530 group = this; 531 } 532 533 void RemoveBBFromSucc(const BB &bb); 534 int GetPredIndex(const BB &predBB) const; 535 int GetSuccIndex(const BB &succBB) const; 536 void RemovePhiOpnd(int index); 537 538 private: 539 BBId id; 540 LabelIdx bbLabel = 0; // the BB's label 541 MapleVector<BB *> pred; // predecessor list 542 MapleVector<BB *> succ; // successor list 543 // record the edge freq from curBB to succ BB 544 MapleVector<uint64> succFreq; 545 MapleMap<OStIdx, PhiNode> phiList; 546 MapleMap<OStIdx, MePhiNode *> mePhiList; 547 MapleMap<BB *, std::vector<PiassignMeStmt *>> meVarPiList; 548 uint32 frequency = 0; 549 BBKind kind = kBBUnknown; 550 uint32 attributes = 0; 551 552 public: 553 StmtNodes stmtNodeList; 554 555 private: 556 MeStmts meStmtList; 557 BB *group; 558 SCCNode<BB> *sccNode = nullptr; 559 }; 560 561 using BBId = BB::BBId; 562 563 class SCCOfBBs { 564 public: SCCOfBBs(uint32 index,BB * bb,MapleAllocator * alloc)565 SCCOfBBs(uint32 index, BB *bb, MapleAllocator *alloc) 566 : id(index), 567 entry(bb), 568 bbs(alloc->Adapter()), 569 predSCC(std::less<SCCOfBBs *>(), alloc->Adapter()), 570 succSCC(std::less<SCCOfBBs *>(), alloc->Adapter()) 571 { 572 } 573 ~SCCOfBBs() = default; 574 void Dump(); 575 void Verify(MapleVector<SCCOfBBs *> &sccOfBB); 576 void SetUp(MapleVector<SCCOfBBs *> &sccOfBB); 577 bool HasCycle() const; AddBBNode(BB * bb)578 void AddBBNode(BB *bb) 579 { 580 bbs.push_back(bb); 581 } Clear()582 void Clear() 583 { 584 bbs.clear(); 585 } GetID()586 uint32 GetID() const 587 { 588 return id; 589 } GetBBs()590 const MapleVector<BB *> &GetBBs() const 591 { 592 return bbs; 593 } GetSucc()594 const MapleSet<SCCOfBBs *> &GetSucc() const 595 { 596 return succSCC; 597 } GetPred()598 const MapleSet<SCCOfBBs *> &GetPred() const 599 { 600 return predSCC; 601 } HasPred()602 bool HasPred() const 603 { 604 return !predSCC.empty(); 605 } GetEntry()606 BB *GetEntry() 607 { 608 return entry; 609 } 610 611 private: 612 uint32 id; 613 BB *entry; 614 MapleVector<BB *> bbs; 615 MapleSet<SCCOfBBs *> predSCC; 616 MapleSet<SCCOfBBs *> succSCC; 617 }; 618 619 bool ControlFlowInInfiniteLoop(const BB &bb, Opcode opcode); 620 } // namespace maple 621 622 namespace std { 623 template <> 624 struct hash<maple::BBId> { 625 size_t operator()(const maple::BBId &x) const 626 { 627 return x; 628 } 629 }; 630 } // namespace std 631 #endif // MAPLE_ME_INCLUDE_BB_H 632