• 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 MAPLEBE_INCLUDE_CG_AARCH64REGSAVESOPT_H
17 #define MAPLEBE_INCLUDE_CG_AARCH64REGSAVESOPT_H
18 
19 #include "cg.h"
20 #include "regsaves.h"
21 #include "aarch64_cg.h"
22 #include "aarch64_insn.h"
23 #include "aarch64_operand.h"
24 
25 namespace maplebe {
26 
27 /* Saved reg info.  This class is created to avoid the complexity of
28    nested Maple Containers */
29 class SavedRegInfo {
30 public:
31     bool insertAtLastMinusOne = false;
SavedRegInfo(MapleAllocator & alloc)32     explicit SavedRegInfo(MapleAllocator &alloc)
33         : saveSet(alloc.Adapter()), restoreEntrySet(alloc.Adapter()), restoreExitSet(alloc.Adapter())
34     {
35     }
36 
ContainSaveReg(regno_t r)37     bool ContainSaveReg(regno_t r)
38     {
39         if (saveSet.find(r) != saveSet.end()) {
40             return true;
41         }
42         return false;
43     }
44 
ContainEntryReg(regno_t r)45     bool ContainEntryReg(regno_t r)
46     {
47         if (restoreEntrySet.find(r) != restoreEntrySet.end()) {
48             return true;
49         }
50         return false;
51     }
52 
ContainExitReg(regno_t r)53     bool ContainExitReg(regno_t r)
54     {
55         if (restoreExitSet.find(r) != restoreExitSet.end()) {
56             return true;
57         }
58         return false;
59     }
60 
InsertSaveReg(regno_t r)61     void InsertSaveReg(regno_t r)
62     {
63         (void)saveSet.insert(r);
64     }
65 
InsertEntryReg(regno_t r)66     void InsertEntryReg(regno_t r)
67     {
68         (void)restoreEntrySet.insert(r);
69     }
70 
InsertExitReg(regno_t r)71     void InsertExitReg(regno_t r)
72     {
73         (void)restoreExitSet.insert(r);
74     }
75 
GetSaveSet()76     MapleSet<regno_t> &GetSaveSet()
77     {
78         return saveSet;
79     }
80 
GetEntrySet()81     MapleSet<regno_t> &GetEntrySet()
82     {
83         return restoreEntrySet;
84     }
85 
GetExitSet()86     MapleSet<regno_t> &GetExitSet()
87     {
88         return restoreExitSet;
89     }
90 
RemoveSaveReg(regno_t r)91     void RemoveSaveReg(regno_t r)
92     {
93         (void)saveSet.erase(r);
94     }
95 
96 private:
97     MapleSet<regno_t> saveSet;
98     MapleSet<regno_t> restoreEntrySet;
99     MapleSet<regno_t> restoreExitSet;
100 };
101 
102 class SavedBBInfo {
103 public:
SavedBBInfo(MapleAllocator & alloc)104     explicit SavedBBInfo(MapleAllocator &alloc) : bbList(alloc.Adapter()) {}
105 
GetBBList()106     MapleSet<BB *> &GetBBList()
107     {
108         return bbList;
109     }
110 
InsertBB(BB * bb)111     void InsertBB(BB *bb)
112     {
113         (void)bbList.insert(bb);
114     }
115 
RemoveBB(BB * bb)116     void RemoveBB(BB *bb)
117     {
118         (void)bbList.erase(bb);
119     }
120 
121 private:
122     MapleSet<BB *> bbList;
123 };
124 
125 class AArch64RegSavesOpt : public RegSavesOpt {
126 public:
AArch64RegSavesOpt(CGFunc & func,MemPool & pool,DomAnalysis & dom,PostDomAnalysis & pdom)127     AArch64RegSavesOpt(CGFunc &func, MemPool &pool, DomAnalysis &dom, PostDomAnalysis &pdom)
128         : RegSavesOpt(func, pool),
129           domInfo(&dom),
130           pDomInfo(&pdom),
131           bbSavedRegs(alloc.Adapter()),
132           regSavedBBs(alloc.Adapter()),
133           regOffset(alloc.Adapter()),
134           id2bb(alloc.Adapter())
135     {
136         bbSavedRegs.resize(func.NumBBs());
137         regSavedBBs.resize(sizeof(CalleeBitsType) << k8BitShift);
138         for (size_t i = 0; i < bbSavedRegs.size(); ++i) {
139             bbSavedRegs[i] = nullptr;
140         }
141         for (size_t i = 0; i < regSavedBBs.size(); ++i) {
142             regSavedBBs[i] = nullptr;
143         }
144     }
145     ~AArch64RegSavesOpt() override = default;
146 
147     using CalleeBitsType = uint64;
148 
149     void InitData();
150     void CollectLiveInfo(const BB &bb, const Operand &opnd, bool isDef, bool isUse);
151     void GenerateReturnBBDefUse(const BB &bb);
152     void ProcessCallInsnParam(BB &bb);
153     void ProcessAsmListOpnd(const BB &bb, Operand &opnd, uint32 idx);
154     void ProcessListOpnd(const BB &bb, Operand &opnd);
155     void ProcessMemOpnd(const BB &bb, Operand &opnd);
156     void ProcessCondOpnd(const BB &bb);
157     void GetLocalDefUse();
158     void PrintBBs() const;
159     int CheckCriteria(BB *bb, regno_t reg) const;
160     bool AlreadySavedInDominatorList(const BB *bb, regno_t reg) const;
161     void DetermineCalleeSaveLocationsDoms();
162     void DetermineCalleeSaveLocationsPre();
163     bool DetermineCalleeRestoreLocations();
164     int32 FindNextOffsetForCalleeSave() const;
165     void InsertCalleeSaveCode();
166     void InsertCalleeRestoreCode();
167     void Verify(regno_t reg, BB *bb, std::set<BB *, BBIdCmp> *visited, uint32 *s, uint32 *r);
168     void Run() override;
169 
GetDomInfo()170     DomAnalysis *GetDomInfo() const
171     {
172         return domInfo;
173     }
174 
GetPostDomInfo()175     PostDomAnalysis *GetPostDomInfo() const
176     {
177         return pDomInfo;
178     }
179 
GetBfs()180     Bfs *GetBfs() const
181     {
182         return bfs;
183     }
184 
GetCalleeBitsDef()185     CalleeBitsType *GetCalleeBitsDef()
186     {
187         return calleeBitsDef;
188     }
189 
GetCalleeBitsUse()190     CalleeBitsType *GetCalleeBitsUse()
191     {
192         return calleeBitsUse;
193     }
194 
GetBBCalleeBits(CalleeBitsType * data,uint32 bid)195     CalleeBitsType GetBBCalleeBits(CalleeBitsType *data, uint32 bid) const
196     {
197         return data[bid];
198     }
199 
SetCalleeBit(CalleeBitsType * data,uint32 bid,regno_t reg)200     void SetCalleeBit(CalleeBitsType *data, uint32 bid, regno_t reg) const
201     {
202         CalleeBitsType mask = 1ULL << RegBitMap(reg);
203         if ((GetBBCalleeBits(data, bid) & mask) == 0) {
204             data[bid] = GetBBCalleeBits(data, bid) | mask;
205         }
206     }
207 
ResetCalleeBit(CalleeBitsType * data,uint32 bid,regno_t reg)208     void ResetCalleeBit(CalleeBitsType *data, uint32 bid, regno_t reg) const
209     {
210         CalleeBitsType mask = 1ULL << RegBitMap(reg);
211         data[bid] = GetBBCalleeBits(data, bid) & ~mask;
212     }
213 
IsCalleeBitSet(CalleeBitsType * data,uint32 bid,regno_t reg)214     bool IsCalleeBitSet(CalleeBitsType *data, uint32 bid, regno_t reg) const
215     {
216         CalleeBitsType mask = 1ULL << RegBitMap(reg);
217         return GetBBCalleeBits(data, bid) & mask;
218     }
219 
220     /* AArch64 specific callee-save registers bit positions
221         0       9  10                33   -- position
222        R19 ..  R28 V8 .. V15 V16 .. V31   -- regs */
RegBitMap(regno_t reg)223     uint32 RegBitMap(regno_t reg) const
224     {
225         uint32 r;
226         if (reg <= R28) {
227             r = (reg - R19);
228         } else {
229             r = ((R28 - R19) + 1) + (reg - V8);
230         }
231         return r;
232     }
233 
ReverseRegBitMap(uint32 reg)234     regno_t ReverseRegBitMap(uint32 reg) const
235     {
236         constexpr uint32 floatRegisterBitOffset = 10;
237         if (reg < floatRegisterBitOffset) {
238             return static_cast<AArch64reg>(R19 + reg);
239         } else {
240             return static_cast<AArch64reg>((V8 + reg) - (R28 - R19 + 1));
241         }
242     }
243 
GetbbSavedRegsEntry(uint32 bid)244     SavedRegInfo *GetbbSavedRegsEntry(uint32 bid)
245     {
246         if (bbSavedRegs[bid] == nullptr) {
247             bbSavedRegs[bid] = memPool->New<SavedRegInfo>(alloc);
248         }
249         return bbSavedRegs[bid];
250     }
251 
SetId2bb(BB * bb)252     void SetId2bb(BB *bb)
253     {
254         id2bb[bb->GetId()] = bb;
255     }
256 
GetId2bb(uint32 bid)257     BB *GetId2bb(uint32 bid)
258     {
259         return id2bb[bid];
260     }
261 
262 private:
263     DomAnalysis *domInfo;
264     PostDomAnalysis *pDomInfo;
265     Bfs *bfs = nullptr;
266     CalleeBitsType *calleeBitsDef = nullptr;
267     CalleeBitsType *calleeBitsUse = nullptr;
268     MapleVector<SavedRegInfo *> bbSavedRegs; /* set of regs to be saved in a BB */
269     MapleVector<SavedBBInfo *> regSavedBBs;  /* set of BBs to be saved for a reg */
270     MapleMap<regno_t, uint32> regOffset;     /* save offset of each register */
271     MapleMap<uint32, BB *> id2bb;            /* bbid to bb* mapping */
272     bool oneAtaTime = false;
273     regno_t oneAtaTimeReg = 0;
274 };
275 } /* namespace maplebe */
276 
277 #endif /* MAPLEBE_INCLUDE_CG_AARCH64REGSAVESOPT_H */
278