• 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                 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