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 MAPLEBE_CG_INCLUDE_CGOCCUR_H 17 #define MAPLEBE_CG_INCLUDE_CGOCCUR_H 18 #include "cg_dominance.h" 19 20 // the data structures that represent occurrences and work candidates for PRE 21 namespace maplebe { 22 enum OccType { 23 kOccUndef, 24 kOccReal, 25 kOccDef, 26 kOccStore, 27 kOccPhiocc, 28 kOccPhiopnd, 29 kOccExit, 30 kOccUse, // for use appearances when candidate is dassign 31 kOccMembar, // for representing occurrence of memory barriers (use CgRealOcc) 32 }; 33 34 class CgOccur { 35 public: CgOccur(OccType ty,BB * bb,Insn * insn,Operand * opnd)36 CgOccur(OccType ty, BB *bb, Insn *insn, Operand *opnd) : occTy(ty), cgBB(bb), insn(insn), opnd(opnd) {} 37 CgOccur(OccType ty,int cId,BB & bb,CgOccur * df)38 CgOccur(OccType ty, int cId, BB &bb, CgOccur *df) : occTy(ty), classID(cId), cgBB(&bb), def(df) {} 39 virtual ~CgOccur() = default; 40 41 bool IsDominate(DomAnalysis &dom, CgOccur &occ); GetBB()42 const BB *GetBB() const 43 { 44 return cgBB; 45 } 46 GetBB()47 BB *GetBB() 48 { 49 return cgBB; 50 } 51 SetBB(BB & bb)52 void SetBB(BB &bb) 53 { 54 cgBB = &bb; 55 } 56 GetOccType()57 OccType GetOccType() const 58 { 59 return occTy; 60 } 61 GetClassID()62 int GetClassID() const 63 { 64 return classID; 65 } 66 SetClassID(int id)67 void SetClassID(int id) 68 { 69 classID = id; 70 } 71 GetDef()72 const CgOccur *GetDef() const 73 { 74 return def; 75 } 76 GetDef()77 CgOccur *GetDef() 78 { 79 return def; 80 } 81 SetDef(CgOccur * define)82 void SetDef(CgOccur *define) 83 { 84 def = define; 85 } 86 GetInsn()87 const Insn *GetInsn() const 88 { 89 return insn; 90 } 91 GetInsn()92 Insn *GetInsn() 93 { 94 return insn; 95 } 96 GetOperand()97 const Operand *GetOperand() const 98 { 99 return opnd; 100 } 101 GetOperand()102 Operand *GetOperand() 103 { 104 return opnd; 105 } 106 Processed()107 bool Processed() const 108 { 109 return processed; 110 } 111 SetProcessed(bool val)112 void SetProcessed(bool val) 113 { 114 processed = val; 115 } 116 GetPrevVersionOccur()117 virtual CgOccur *GetPrevVersionOccur() 118 { 119 CHECK_FATAL(false, "has no prev version occur"); 120 } 121 SetPrevVersionOccur(CgOccur *)122 virtual void SetPrevVersionOccur(CgOccur *) 123 { 124 CHECK_FATAL(false, "has no prev version occur"); 125 } 126 Dump()127 virtual void Dump() const 128 { 129 if (occTy == kOccExit) { 130 LogInfo::MapleLogger() << "ExitOcc at bb " << GetBB()->GetId() << std::endl; 131 } 132 }; 133 134 private: 135 OccType occTy = kOccUndef; // kinds of occ 136 int classID = 0; // class id 137 BB *cgBB = nullptr; // the BB it occurs in 138 Insn *insn = nullptr; 139 Operand *opnd = nullptr; 140 CgOccur *def = nullptr; 141 bool processed = false; 142 }; 143 144 class CgUseOcc : public CgOccur { 145 public: CgUseOcc(BB * bb,Insn * insn,Operand * opnd)146 CgUseOcc(BB *bb, Insn *insn, Operand *opnd) : CgOccur(kOccUse, bb, insn, opnd), needReload(false) {} 147 148 ~CgUseOcc() = default; 149 Reload()150 bool Reload() const 151 { 152 return needReload; 153 } 154 SetReload(bool val)155 void SetReload(bool val) 156 { 157 needReload = val; 158 } 159 GetPrevVersionOccur()160 CgOccur *GetPrevVersionOccur() override 161 { 162 return prevVersion; 163 } 164 SetPrevVersionOccur(CgOccur * val)165 void SetPrevVersionOccur(CgOccur *val) override 166 { 167 prevVersion = val; 168 } 169 Dump()170 void Dump() const override 171 { 172 LogInfo::MapleLogger() << "UseOcc " << GetClassID() << " at bb " << GetBB()->GetId() << ": " 173 << (needReload ? "need-reload, " : "not need-reload, ") << "\n"; 174 } 175 176 private: 177 bool needReload = false; 178 CgOccur *prevVersion = nullptr; 179 }; 180 181 class CgStoreOcc : public CgOccur { 182 public: CgStoreOcc(BB * bb,Insn * insn,Operand * opnd)183 CgStoreOcc(BB *bb, Insn *insn, Operand *opnd) : CgOccur(kOccStore, bb, insn, opnd) {} 184 ~CgStoreOcc() = default; 185 Reload()186 bool Reload() const 187 { 188 return needReload; 189 } 190 SetReload(bool val)191 void SetReload(bool val) 192 { 193 needReload = val; 194 } 195 GetPrevVersionOccur()196 CgOccur *GetPrevVersionOccur() override 197 { 198 return prevVersion; 199 } 200 SetPrevVersionOccur(CgOccur * val)201 void SetPrevVersionOccur(CgOccur *val) override 202 { 203 prevVersion = val; 204 } 205 Dump()206 void Dump() const override 207 { 208 LogInfo::MapleLogger() << "StoreOcc " << GetClassID() << " at bb " << GetBB()->GetId() << ": " 209 << (needReload ? "reload, " : "not reload, ") << "\n"; 210 } 211 212 private: 213 bool needReload = false; 214 CgOccur *prevVersion = nullptr; 215 }; 216 217 class CgDefOcc : public CgOccur { 218 public: CgDefOcc(BB * bb,Insn * insn,Operand * opnd)219 CgDefOcc(BB *bb, Insn *insn, Operand *opnd) : CgOccur(kOccDef, bb, insn, opnd) {} 220 ~CgDefOcc() = default; 221 Loaded()222 bool Loaded() const 223 { 224 return needStore; 225 } 226 SetLoaded(bool val)227 void SetLoaded(bool val) 228 { 229 needStore = val; 230 } 231 GetPrevVersionOccur()232 CgOccur *GetPrevVersionOccur() override 233 { 234 return prevVersion; 235 } 236 SetPrevVersionOccur(CgOccur * val)237 void SetPrevVersionOccur(CgOccur *val) override 238 { 239 prevVersion = val; 240 } 241 Dump()242 void Dump() const override 243 { 244 LogInfo::MapleLogger() << "DefOcc " << GetClassID() << " at bb " << GetBB()->GetId() << ": " 245 << (needStore ? "store" : "not store") << "\n"; 246 } 247 248 private: 249 bool needStore = false; 250 CgOccur *prevVersion = nullptr; 251 }; 252 253 class CgPhiOpndOcc; 254 enum AvailState { kFullyAvailable, kPartialAvailable, kNotAvailable }; 255 class CgPhiOcc : public CgOccur { 256 public: CgPhiOcc(BB & bb,Operand * opnd,MapleAllocator & alloc)257 CgPhiOcc(BB &bb, Operand *opnd, MapleAllocator &alloc) 258 : CgOccur(kOccPhiocc, 0, bb, nullptr), regOpnd(opnd), isDownSafe(!bb.IsCatch()), phiOpnds(alloc.Adapter()) 259 { 260 } 261 262 virtual ~CgPhiOcc() = default; 263 IsDownSafe()264 bool IsDownSafe() const 265 { 266 return isDownSafe; 267 } 268 SetIsDownSafe(bool downSafe)269 void SetIsDownSafe(bool downSafe) 270 { 271 isDownSafe = downSafe; 272 } 273 GetPhiOpnds()274 const MapleVector<CgPhiOpndOcc *> &GetPhiOpnds() const 275 { 276 return phiOpnds; 277 } 278 GetPhiOpnds()279 MapleVector<CgPhiOpndOcc *> &GetPhiOpnds() 280 { 281 return phiOpnds; 282 } 283 GetOpnd()284 Operand *GetOpnd() 285 { 286 return regOpnd; 287 } 288 GetPhiOpnd(size_t idx)289 CgPhiOpndOcc *GetPhiOpnd(size_t idx) 290 { 291 DEBUG_ASSERT(idx < phiOpnds.size(), "out of range in CgPhiOcc::GetPhiOpnd"); 292 return phiOpnds.at(idx); 293 } 294 GetPhiOpnd(size_t idx)295 const CgPhiOpndOcc *GetPhiOpnd(size_t idx) const 296 { 297 DEBUG_ASSERT(idx < phiOpnds.size(), "out of range in CgPhiOcc::GetPhiOpnd"); 298 return phiOpnds.at(idx); 299 } 300 AddPhiOpnd(CgPhiOpndOcc & opnd)301 void AddPhiOpnd(CgPhiOpndOcc &opnd) 302 { 303 phiOpnds.push_back(&opnd); 304 } 305 GetPrevVersionOccur()306 CgOccur *GetPrevVersionOccur() override 307 { 308 return prevVersion; 309 } 310 SetPrevVersionOccur(CgOccur * val)311 void SetPrevVersionOccur(CgOccur *val) override 312 { 313 prevVersion = val; 314 } 315 IsFullyAvailable()316 bool IsFullyAvailable() const 317 { 318 return availState == kFullyAvailable; 319 } 320 IsPartialAvailable()321 bool IsPartialAvailable() const 322 { 323 return availState == kPartialAvailable; 324 } 325 IsNotAvailable()326 bool IsNotAvailable() const 327 { 328 return availState == kNotAvailable; 329 } 330 SetAvailability(AvailState val)331 void SetAvailability(AvailState val) 332 { 333 availState = val; 334 } 335 Dump()336 void Dump() const override 337 { 338 LogInfo::MapleLogger() << "PhiOcc " << GetClassID() << " at bb " << GetBB()->GetId() << ": " 339 << (isDownSafe ? "downsafe, " : "not downsafe, ") 340 << (availState == kNotAvailable 341 ? "not avail" 342 : (availState == kPartialAvailable ? "part avail" : "fully avail")) 343 << "\n"; 344 } 345 346 private: 347 Operand *regOpnd; 348 bool isDownSafe = true; // default is true 349 AvailState availState = kFullyAvailable; 350 MapleVector<CgPhiOpndOcc *> phiOpnds; 351 CgOccur *prevVersion = nullptr; 352 }; 353 354 class CgPhiOpndOcc : public CgOccur { 355 public: CgPhiOpndOcc(BB * bb,Operand * opnd,CgPhiOcc * defPhi)356 CgPhiOpndOcc(BB *bb, Operand *opnd, CgPhiOcc *defPhi) 357 : CgOccur(kOccPhiopnd, bb, nullptr, opnd), hasRealUse(false), phiOcc(defPhi) 358 { 359 } 360 361 ~CgPhiOpndOcc() = default; 362 HasRealUse()363 bool HasRealUse() const 364 { 365 return hasRealUse; 366 } 367 SetHasRealUse(bool realUse)368 void SetHasRealUse(bool realUse) 369 { 370 hasRealUse = realUse; 371 } 372 GetPhiOcc()373 const CgPhiOcc *GetPhiOcc() const 374 { 375 return phiOcc; 376 } 377 GetPhiOcc()378 CgPhiOcc *GetPhiOcc() 379 { 380 return phiOcc; 381 } 382 SetPhiOcc(CgPhiOcc & occ)383 void SetPhiOcc(CgPhiOcc &occ) 384 { 385 phiOcc = &occ; 386 } 387 Reload()388 bool Reload() const 389 { 390 return reload; 391 } SetReload(bool val)392 void SetReload(bool val) 393 { 394 reload = val; 395 } 396 Dump()397 void Dump() const override 398 { 399 LogInfo::MapleLogger() << "PhiOpndOcc " << GetClassID() << " at bb " << GetBB()->GetId() << ": " 400 << (hasRealUse ? "hasRealUse, " : "not hasRealUse, ") 401 << (reload ? "reload" : "not reload") << std::endl; 402 } 403 404 private: 405 bool hasRealUse; 406 bool reload = false; 407 CgPhiOcc *phiOcc = nullptr; // its lhs 408 }; 409 410 // each singly linked list represents each bucket in workCandHashTable 411 class PreWorkCand { 412 public: PreWorkCand(MapleAllocator & alloc,Operand * curOpnd,PUIdx pIdx)413 PreWorkCand(MapleAllocator &alloc, Operand *curOpnd, PUIdx pIdx) 414 : next(nullptr), 415 allOccs(alloc.Adapter()), 416 realOccs(alloc.Adapter()), 417 phiOccs(alloc.Adapter()), 418 theOperand(curOpnd), 419 puIdx(pIdx), 420 redo2HandleCritEdges(false) 421 { 422 DEBUG_ASSERT(pIdx != 0, "PreWorkCand: initial puIdx cannot be 0"); 423 } 424 425 virtual ~PreWorkCand() = default; 426 AddRealOccAsLast(CgOccur & occ,PUIdx pIdx)427 void AddRealOccAsLast(CgOccur &occ, PUIdx pIdx) 428 { 429 realOccs.push_back(&occ); // add as last 430 DEBUG_ASSERT(pIdx != 0, "puIdx of realocc cannot be 0"); 431 if (pIdx != puIdx) { 432 puIdx = 0; 433 } 434 } 435 GetNext()436 const PreWorkCand *GetNext() const 437 { 438 return next; 439 } 440 GetNext()441 PreWorkCand *GetNext() 442 { 443 return next; 444 } 445 SetNext(PreWorkCand & workCand)446 void SetNext(PreWorkCand &workCand) 447 { 448 next = &workCand; 449 } 450 GetIndex()451 int32 GetIndex() const 452 { 453 return index; 454 } 455 SetIndex(int idx)456 void SetIndex(int idx) 457 { 458 index = idx; 459 } 460 GetRealOccs()461 const MapleVector<CgOccur *> &GetRealOccs() const 462 { 463 return realOccs; 464 } 465 GetRealOccs()466 MapleVector<CgOccur *> &GetRealOccs() 467 { 468 return realOccs; 469 } 470 GetRealOcc(size_t idx)471 const CgOccur *GetRealOcc(size_t idx) const 472 { 473 DEBUG_ASSERT(idx < realOccs.size(), "out of range in PreWorkCand::GetRealOccAt"); 474 return realOccs.at(idx); 475 } 476 GetRealOcc(size_t idx)477 CgOccur *GetRealOcc(size_t idx) 478 { 479 DEBUG_ASSERT(idx < realOccs.size(), "out of range in PreWorkCand::GetRealOccAt"); 480 return realOccs.at(idx); 481 } 482 PhiOccs()483 const MapleVector<CgPhiOcc *> &PhiOccs() const 484 { 485 return phiOccs; 486 } 487 PhiOccs()488 MapleVector<CgPhiOcc *> &PhiOccs() 489 { 490 return phiOccs; 491 } 492 GetTheOperand()493 const Operand *GetTheOperand() const 494 { 495 return theOperand; 496 } 497 GetTheOperand()498 Operand *GetTheOperand() 499 { 500 return theOperand; 501 } 502 SetTheOperand(Operand & expr)503 void SetTheOperand(Operand &expr) 504 { 505 theOperand = &expr; 506 } 507 GetPUIdx()508 PUIdx GetPUIdx() const 509 { 510 return puIdx; 511 } 512 SetPUIdx(PUIdx idx)513 void SetPUIdx(PUIdx idx) 514 { 515 puIdx = idx; 516 } 517 Redo2HandleCritEdges()518 bool Redo2HandleCritEdges() const 519 { 520 return redo2HandleCritEdges; 521 } 522 SetRedo2HandleCritEdges(bool redo)523 void SetRedo2HandleCritEdges(bool redo) 524 { 525 redo2HandleCritEdges = redo; 526 } 527 528 private: 529 PreWorkCand *next; 530 int32 index = 0; 531 MapleVector<CgOccur *> allOccs; 532 MapleVector<CgOccur *> realOccs; // maintained in order of dt_preorder 533 MapleVector<CgPhiOcc *> phiOccs; 534 Operand *theOperand; // the expression of this workcand 535 PUIdx puIdx; // if 0, its occ span multiple PUs; initial value must 536 // puIdx cannot be 0 if hasLocalOpnd is true 537 bool redo2HandleCritEdges : 1; // redo to make critical edges affect canbevail 538 }; 539 540 class PreWorkCandHashTable { 541 public: 542 static const uint32 workCandHashLength = 229; 543 static uint32 ComputeWorkCandHashIndex(const Operand &opnd); 544 static uint32 ComputeStmtWorkCandHashIndex(const Insn &insn); 545 546 PreWorkCandHashTable() = default; 547 ~PreWorkCandHashTable() = default; 548 GetWorkcandHashTable()549 std::array<PreWorkCand *, workCandHashLength> &GetWorkcandHashTable() 550 { 551 return workCandHashTable; 552 } 553 GetWorkcandFromIndex(size_t idx)554 PreWorkCand *GetWorkcandFromIndex(size_t idx) 555 { 556 return workCandHashTable[idx]; 557 } 558 SetWorkCandAt(size_t idx,PreWorkCand & workCand)559 void SetWorkCandAt(size_t idx, PreWorkCand &workCand) 560 { 561 workCandHashTable[idx] = &workCand; 562 } 563 564 private: 565 std::array<PreWorkCand *, workCandHashLength> workCandHashTable; 566 }; 567 } // namespace maplebe 568 #endif // MAPLEBE_CG_INCLUDE_CGOCCUR_H 569