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