• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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