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