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