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_ORIG_SYMBOL_H 17 #define MAPLE_ME_INCLUDE_ORIG_SYMBOL_H 18 #include "mir_module.h" 19 #include "mir_symbol.h" 20 #include "mir_preg.h" 21 #include "mir_function.h" 22 #include "mpl_number.h" 23 #include "scc.h" 24 25 // This file defines the data structure OriginalSt that represents a program 26 // symbol occurring in the code of the program being optimized. 27 namespace maple { 28 class OStTag; 29 using OStIdx = utils::Index<OStTag, uint32>; 30 31 constexpr int kInitVersion = 0; 32 class VarMeExpr; // circular dependency exists, no other choice 33 class VersionSt; // circular dependency exists, no other choice 34 class OriginalSt { 35 public: 36 struct OriginalStPtrComparator { operatorOriginalStPtrComparator37 bool operator()(const OriginalSt *x, const OriginalSt *y) const 38 { 39 return x->GetIndex() < y->GetIndex(); 40 } 41 }; 42 OriginalSt(uint32 index,PregIdx rIdx,PUIdx pIdx,MapleAllocator & alloc)43 OriginalSt(uint32 index, PregIdx rIdx, PUIdx pIdx, MapleAllocator &alloc) 44 : OriginalSt(OStIdx(index), alloc, true, false, 0, pIdx, kPregOst, false, {.pregIdx = rIdx}) 45 { 46 } 47 48 ~OriginalSt() = default; 49 50 void Dump() const; GetPregIdx()51 PregIdx GetPregIdx() const 52 { 53 DEBUG_ASSERT(ostType == kPregOst, "OriginalSt must be PregOst"); 54 return symOrPreg.pregIdx; 55 } 56 GetMIRPreg()57 MIRPreg *GetMIRPreg() const 58 { 59 DEBUG_ASSERT(ostType == kPregOst, "OriginalSt must be PregOst"); 60 return GlobalTables::GetGsymTable().GetModule()->CurFunction()->GetPregTab()->PregFromPregIdx( 61 symOrPreg.pregIdx); 62 } 63 GetMIRSymbol()64 MIRSymbol *GetMIRSymbol() const 65 { 66 DEBUG_ASSERT(ostType == kSymbolOst, "OriginalSt must be SymbolOst"); 67 return symOrPreg.mirSt; 68 } 69 HasAttr(AttrKind attrKind)70 bool HasAttr(AttrKind attrKind) const 71 { 72 if (ostType == kSymbolOst) { 73 TypeAttrs typeAttr = symOrPreg.mirSt->GetAttrs(); 74 if (typeAttr.GetAttr(attrKind)) { 75 return true; 76 } 77 } 78 return false; 79 } 80 HasOneElemSimdAttr()81 bool HasOneElemSimdAttr() const 82 { 83 if (ostType == kSymbolOst) { 84 TypeAttrs typeAttr = symOrPreg.mirSt->GetAttrs(); 85 if (typeAttr.GetAttr(ATTR_oneelem_simd)) { 86 return true; 87 } 88 } 89 return false; 90 } 91 IsLocal()92 bool IsLocal() const 93 { 94 return isLocal; 95 } 96 IsFormal()97 bool IsFormal() const 98 { 99 return isFormal; 100 } SetIsFormal(bool isFormal)101 void SetIsFormal(bool isFormal) 102 { 103 this->isFormal = isFormal; 104 } 105 IsFinal()106 bool IsFinal() const 107 { 108 return isFinal; 109 } 110 void SetIsFinal(bool isFinal = true) 111 { 112 this->isFinal = isFinal; 113 } 114 IsPrivate()115 bool IsPrivate() const 116 { 117 return isPrivate; 118 } SetIsPrivate(bool isPrivate)119 void SetIsPrivate(bool isPrivate) 120 { 121 this->isPrivate = isPrivate; 122 } 123 IsVolatile()124 bool IsVolatile() const 125 { 126 return (ostType == kSymbolOst) ? symOrPreg.mirSt->IsVolatile() : false; 127 } 128 IsVrNeeded()129 bool IsVrNeeded() const 130 { 131 return (ostType == kSymbolOst) ? symOrPreg.mirSt->GetIsTmp() : false; 132 } 133 134 bool Equal(const OriginalSt &ost) const; 135 IsRealSymbol()136 bool IsRealSymbol() const 137 { 138 return (ostType == kSymbolOst || ostType == kPregOst); 139 } 140 IsSymbolOst()141 bool IsSymbolOst() const 142 { 143 return ostType == kSymbolOst; 144 } 145 IsPregOst()146 bool IsPregOst() const 147 { 148 return (ostType == kPregOst); 149 } 150 IsSpecialPreg()151 bool IsSpecialPreg() const 152 { 153 return ostType == kPregOst && symOrPreg.pregIdx < 0; 154 } 155 IsSameSymOrPreg(const OriginalSt * ost)156 bool IsSameSymOrPreg(const OriginalSt *ost) const 157 { 158 if (ostType != ost->ostType) { 159 return false; 160 } 161 if (IsSymbolOst()) { 162 return symOrPreg.mirSt == ost->symOrPreg.mirSt; 163 } 164 return symOrPreg.pregIdx == ost->symOrPreg.pregIdx; 165 } 166 GetIndirectLev()167 int8 GetIndirectLev() const 168 { 169 return indirectLev; 170 } 171 SetIndirectLev(int8 level)172 void SetIndirectLev(int8 level) 173 { 174 indirectLev = level; 175 } 176 GetIndex()177 OStIdx GetIndex() const 178 { 179 return index; 180 } 181 GetVersionIndex(size_t version)182 size_t GetVersionIndex(size_t version) const 183 { 184 DEBUG_ASSERT(version < versionsIndices.size(), "version out of range"); 185 return versionsIndices.at(version); 186 } 187 GetVersionsIndices()188 const MapleVector<size_t> &GetVersionsIndices() const 189 { 190 return versionsIndices; 191 } PushbackVersionsIndices(size_t versionIndex)192 void PushbackVersionsIndices(size_t versionIndex) 193 { 194 versionsIndices.push_back(versionIndex); 195 } 196 GetZeroVersionIndex()197 size_t GetZeroVersionIndex() const 198 { 199 return zeroVersionIndex; 200 } 201 SetZeroVersionIndex(size_t zeroVersionIndexParam)202 void SetZeroVersionIndex(size_t zeroVersionIndexParam) 203 { 204 zeroVersionIndex = zeroVersionIndexParam; 205 } 206 GetTyIdx()207 TyIdx GetTyIdx() const 208 { 209 return tyIdx; 210 } 211 SetTyIdx(TyIdx tyIdxPara)212 void SetTyIdx(TyIdx tyIdxPara) 213 { 214 tyIdx = tyIdxPara; 215 } 216 GetFieldID()217 FieldID GetFieldID() const 218 { 219 return fieldID; 220 } 221 SetFieldID(FieldID fieldID)222 void SetFieldID(FieldID fieldID) 223 { 224 this->fieldID = fieldID; 225 } 226 GetOffset()227 const OffsetType &GetOffset() const 228 { 229 return offset; 230 } 231 SetOffset(const OffsetType & offsetVal)232 void SetOffset(const OffsetType &offsetVal) 233 { 234 offset = offsetVal; 235 } 236 IsIgnoreRC()237 bool IsIgnoreRC() const 238 { 239 return ignoreRC; 240 } 241 IsAddressTaken()242 bool IsAddressTaken() const 243 { 244 return addressTaken; 245 } 246 247 void SetAddressTaken(bool addrTaken = true) 248 { 249 addressTaken = addrTaken; 250 } 251 252 // current ost can not be define by MayDef, or used by mayUse 253 bool IsTopLevelOst() const; 254 IsEPreLocalRefVar()255 bool IsEPreLocalRefVar() const 256 { 257 return epreLocalRefVar; 258 } 259 260 void SetEPreLocalRefVar(bool epreLocalrefvarPara = true) 261 { 262 epreLocalRefVar = epreLocalrefvarPara; 263 } 264 GetPuIdx()265 PUIdx GetPuIdx() const 266 { 267 return puIdx; 268 } 269 IsIVCandidate()270 bool IsIVCandidate() const 271 { 272 if (indirectLev != 0 || (IsSymbolOst() && GetMIRSymbol()->GetName() == "__nads_dummysym__")) { 273 return false; 274 } 275 MIRType *mirtype = GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx); 276 if (IsPrimitiveInteger(mirtype->GetPrimType())) { 277 // additional check using MIRSymbol's tyIdx 278 if (IsSymbolOst()) { 279 return IsPrimitiveInteger(GetMIRSymbol()->GetType()->GetPrimType()); 280 } 281 return true; 282 } else { 283 return false; 284 } 285 } 286 GetType()287 MIRType *GetType() const 288 { 289 return GlobalTables::GetTypeTable().GetTypeFromTyIdx(tyIdx); 290 } 291 GetPrevLevelOst()292 const OriginalSt *GetPrevLevelOst() const 293 { 294 return prevLevOst; 295 } 296 GetPrevLevelOst()297 OriginalSt *GetPrevLevelOst() 298 { 299 return prevLevOst; 300 } 301 GetPointerVstIdx()302 size_t GetPointerVstIdx() const 303 { 304 return pointerVstIdx; 305 } 306 307 void SetPointerVst(const VersionSt *vst); 308 NumSSAVersions()309 uint32 NumSSAVersions() const 310 { 311 if (zeroVersionIndex == 0 || !IsPregOst()) { 312 return static_cast<uint32>(versionsIndices.size()); 313 } 314 return static_cast<uint32>(versionsIndices.size()) - 1; // preg's zero version not counted 315 } 316 317 private: 318 enum OSTType { kUnkonwnOst, kSymbolOst, kPregOst }; 319 union SymOrPreg { 320 PregIdx pregIdx; 321 MIRSymbol *mirSt; 322 }; OriginalSt(OStIdx index,MapleAllocator & alloc,bool local,bool isFormal,FieldID fieldID,PUIdx pIdx,OSTType ostType,bool ignoreRC,SymOrPreg sysOrPreg)323 OriginalSt(OStIdx index, MapleAllocator &alloc, bool local, bool isFormal, FieldID fieldID, PUIdx pIdx, 324 OSTType ostType, bool ignoreRC, SymOrPreg sysOrPreg) 325 : ostType(ostType), 326 index(index), 327 versionsIndices(alloc.Adapter()), 328 fieldID(fieldID), 329 offset(kOffsetUnknown), 330 isLocal(local), 331 isFormal(isFormal), 332 ignoreRC(ignoreRC), 333 symOrPreg(sysOrPreg), 334 puIdx(pIdx) 335 { 336 } 337 338 OSTType ostType; 339 OStIdx index; // index number in originalStVector 340 MapleVector<size_t> versionsIndices; // the i-th element refers the index of versionst in versionst table 341 size_t zeroVersionIndex = 0; // same as versionsIndices[0] 342 TyIdx tyIdx {0}; // type of this symbol at this level; 0 for unknown 343 FieldID fieldID; // at each level of indirection 344 OffsetType offset; // bit offset 345 int8 indirectLev = 0; // level of indirection; -1 for address, 0 for itself 346 bool isLocal; // get from defined stmt or use expr 347 bool isFormal; // it's from the formal parameters so the type must be kSymbolOst or kPregOst after rename2preg 348 bool addressTaken = false; 349 bool isFinal = false; // if the field has final attribute, only when fieldID != 0 350 bool isPrivate = false; // if the field has private attribute, only when fieldID != 0 351 bool ignoreRC = false; // base on MIRSymbol's IgnoreRC() 352 bool epreLocalRefVar = false; // is a localrefvar temp created by epre phase 353 public: 354 bool isPtrWithIncDec = false; // is a pointer with self-increment/decrement 355 bool storesIVInitValue = false; // temp created to store IV's initial value 356 private: 357 SymOrPreg symOrPreg; 358 PUIdx puIdx; 359 size_t pointerVstIdx = 0; 360 OriginalSt *prevLevOst = nullptr; 361 }; 362 363 class SymbolFieldPair { 364 public: 365 SymbolFieldPair(const StIdx &stIdx, FieldID fld, const TyIdx &tyIdx, 366 const OffsetType &offset = OffsetType(kOffsetUnknown)) stIdx(stIdx)367 : stIdx(stIdx), fldIDAndOffset((static_cast<int64>(offset.val) << 32U) + fld), tyIdx(tyIdx) 368 { 369 } 370 ~SymbolFieldPair() = default; 371 bool operator==(const SymbolFieldPair &pairA) const 372 { 373 return (pairA.stIdx == stIdx) && (pairA.fldIDAndOffset == fldIDAndOffset) && (tyIdx == pairA.tyIdx); 374 } 375 GetStIdx()376 const StIdx &GetStIdx() const 377 { 378 return stIdx; 379 } 380 GetFieldID()381 FieldID GetFieldID() const 382 { 383 return static_cast<FieldID>(fldIDAndOffset); 384 } 385 386 private: 387 StIdx stIdx; 388 int64 fldIDAndOffset; 389 TyIdx tyIdx; 390 }; 391 392 struct HashSymbolFieldPair { operatorHashSymbolFieldPair393 size_t operator()(const SymbolFieldPair &symbolFldID) const 394 { 395 return symbolFldID.GetStIdx().FullIdx(); 396 } 397 }; 398 399 // This Table is for original symobols only. There is no SSA info attached and SSA is built based on this table. 400 class OriginalStTable { 401 public: 402 OriginalStTable(MemPool &memPool, MIRModule &mod); 403 ~OriginalStTable() = default; 404 405 using OriginalStContainer = MapleVector<OriginalSt *>; 406 using VstIdx2NextLevelOsts = MapleVector<OriginalStContainer *>; 407 using OriginalStIterator = OriginalStContainer::iterator; 408 using ConstOriginalStIterator = OriginalStContainer::const_iterator; 409 410 OriginalSt *FindOrCreateSymbolOriginalSt(MIRSymbol &mirSt, PUIdx puIdx, FieldID fld); 411 std::pair<OriginalSt *, bool> FindOrCreateSymbolOriginalSt(MIRSymbol &mirSt, PUIdx puIdx, FieldID fld, 412 const TyIdx &tyIdx, 413 const OffsetType &offset = OffsetType(kOffsetUnknown)); 414 OriginalSt *CreateSymbolOriginalSt(MIRSymbol &mirSt, PUIdx puIdx, FieldID fld, const TyIdx &tyIdx, 415 const OffsetType &offset = OffsetType(kOffsetUnknown)); 416 OriginalSt *FindOrCreatePregOriginalSt(PregIdx pregIdx, PUIdx puIdx); 417 OriginalSt *CreateSymbolOriginalSt(MIRSymbol &mirSt, PUIdx pidx, FieldID fld); 418 OriginalSt *CreatePregOriginalSt(PregIdx pregIdx, PUIdx puIdx); 419 OriginalSt *FindSymbolOriginalSt(const MIRSymbol &mirSt, FieldID fld, const TyIdx &tyIdx, const OffsetType &offset); 420 OriginalSt *FindSymbolOriginalSt(const MIRSymbol &mirSt); 421 const OriginalSt *GetOriginalStFromID(OStIdx id, bool checkFirst = false) const 422 { 423 if (checkFirst && id >= originalStVector.size()) { 424 return nullptr; 425 } 426 DEBUG_ASSERT(id < originalStVector.size(), "symbol table index out of range"); 427 return originalStVector[id]; 428 } 429 OriginalSt *GetOriginalStFromID(OStIdx id, bool checkFirst = false) 430 { 431 return const_cast<OriginalSt *>(const_cast<const OriginalStTable *>(this)->GetOriginalStFromID(id, checkFirst)); 432 } 433 Size()434 size_t Size() const 435 { 436 return originalStVector.size(); 437 } 438 GetMIRSymbolFromOriginalSt(const OriginalSt & ost)439 const MIRSymbol *GetMIRSymbolFromOriginalSt(const OriginalSt &ost) const 440 { 441 DEBUG_ASSERT(ost.IsRealSymbol(), "runtime check error"); 442 return ost.GetMIRSymbol(); 443 } 444 GetMIRSymbolFromID(OStIdx id)445 const MIRSymbol *GetMIRSymbolFromID(OStIdx id) const 446 { 447 return GetOriginalStFromID(id, false)->GetMIRSymbol(); 448 } GetMIRSymbolFromID(OStIdx id)449 MIRSymbol *GetMIRSymbolFromID(OStIdx id) 450 { 451 auto *originalSt = GetOriginalStFromID(id, false); 452 CHECK_FATAL(originalSt, "originalSt is nullptr!"); 453 return originalSt->GetMIRSymbol(); 454 } 455 GetAlloc()456 MapleAllocator &GetAlloc() 457 { 458 return alloc; 459 } 460 GetOriginalStVector()461 MapleVector<OriginalSt *> &GetOriginalStVector() 462 { 463 return originalStVector; 464 } 465 466 void SetEPreLocalRefVar(const OStIdx &id, bool epreLocalrefvarPara = true) 467 { 468 DEBUG_ASSERT(id < originalStVector.size(), "symbol table index out of range"); 469 originalStVector[id]->SetEPreLocalRefVar(epreLocalrefvarPara); 470 } 471 SetZeroVersionIndex(const OStIdx & id,size_t zeroVersionIndexParam)472 void SetZeroVersionIndex(const OStIdx &id, size_t zeroVersionIndexParam) 473 { 474 DEBUG_ASSERT(id < originalStVector.size(), "symbol table index out of range"); 475 originalStVector[id]->SetZeroVersionIndex(zeroVersionIndexParam); 476 } 477 GetVersionsIndicesSize(const OStIdx & id)478 size_t GetVersionsIndicesSize(const OStIdx &id) const 479 { 480 DEBUG_ASSERT(id < originalStVector.size(), "symbol table index out of range"); 481 return originalStVector[id]->GetVersionsIndices().size(); 482 } 483 UpdateVarOstMap(const OStIdx & id,std::map<OStIdx,OriginalSt * > & varOstMap)484 void UpdateVarOstMap(const OStIdx &id, std::map<OStIdx, OriginalSt *> &varOstMap) 485 { 486 DEBUG_ASSERT(id < originalStVector.size(), "symbol table index out of range"); 487 varOstMap[id] = originalStVector[id]; 488 } 489 begin()490 ConstOriginalStIterator begin() const 491 { 492 auto it = originalStVector.begin(); 493 // self-inc resulting from the fact that the 1st element is reserved and set null. 494 ++it; 495 return it; 496 } 497 begin()498 OriginalStIterator begin() 499 { 500 auto it = originalStVector.begin(); 501 // self-inc resulting from the fact that the 1st element is reserved and set null. 502 ++it; 503 return it; 504 } 505 end()506 ConstOriginalStIterator end() const 507 { 508 return originalStVector.end(); 509 } 510 end()511 OriginalStIterator end() 512 { 513 return originalStVector.end(); 514 } 515 516 void Dump(); 517 OriginalSt *FindOrCreateAddrofSymbolOriginalSt(OriginalSt *ost); 518 OriginalSt *FindOrCreateExtraLevOriginalSt(const VersionSt *vst, TyIdx ptyidx, FieldID fld, 519 const OffsetType &offset = OffsetType(kOffsetUnknown)); 520 OriginalSt *FindExtraLevOriginalSt(const MapleVector<OriginalSt *> &nextLevelOsts, const MIRType *type, FieldID fld, 521 const OffsetType &offset = OffsetType(kOffsetUnknown)) const; 522 OriginalSt *FindExtraLevOriginalSt(const VersionSt *vst, const MIRType *type, FieldID fld, 523 const OffsetType &offset = OffsetType(kOffsetUnknown)) const; 524 MapleVector<OriginalSt *> *GetNextLevelOstsOfVst(size_t vstIdx) const; 525 MapleVector<OriginalSt *> *GetNextLevelOstsOfVst(const VersionSt *vst) const; 526 void AddNextLevelOstOfVst(size_t vstIdx, OriginalSt *ost); 527 void AddNextLevelOstOfVst(const VersionSt *vst, OriginalSt *ost); 528 529 private: 530 MapleAllocator alloc; 531 MIRModule &mirModule; 532 MapleVector<OriginalSt *> originalStVector; // the vector that map a OriginalSt's index to its pointer 533 // mir symbol to original table, this only exists for no-original variables. 534 public: 535 MapleUnorderedMap<SymbolFieldPair, OStIdx, HashSymbolFieldPair> mirSt2Ost; 536 MapleUnorderedMap<StIdx, OStIdx> addrofSt2Ost; 537 538 private: 539 MapleUnorderedMap<PregIdx, OStIdx> preg2Ost; 540 // mir type to virtual variables in original table. this only exists for no-original variables. 541 MapleMap<TyIdx, OStIdx> pType2Ost; 542 // malloc info to virtual variables in original table. this only exists for no-original variables. 543 MapleMap<std::pair<BaseNode *, uint32>, OStIdx> malloc2Ost; 544 MapleMap<uint32, OStIdx> thisField2Ost; // field of this_memory to virtual variables in original table. 545 VstIdx2NextLevelOsts nextLevelOstsOfVst; // index is VersionSt index. 546 OStIdx virtuaLostUnkownMem {0}; 547 OStIdx virtuaLostConstMem {0}; 548 }; 549 } // namespace maple 550 551 namespace std { 552 template <> 553 struct hash<maple::OStIdx> { 554 size_t operator()(const maple::OStIdx &x) const 555 { 556 return static_cast<size_t>(x); 557 } 558 }; 559 } // namespace std 560 #endif // MAPLE_ME_INCLUDE_ORIG_SYMBOL_H 561