• 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,LoopAnalysis & loop)127     AArch64RegSavesOpt(CGFunc &func, MemPool &pool, DomAnalysis &dom, PostDomAnalysis &pdom, LoopAnalysis &loop)
128         : RegSavesOpt(func, pool),
129           domInfo(&dom),
130           pDomInfo(&pdom),
131           loopInfo(loop),
132           bbSavedRegs(alloc.Adapter()),
133           regSavedBBs(alloc.Adapter()),
134           regOffset(alloc.Adapter()),
135           id2bb(alloc.Adapter())
136     {
137         bbSavedRegs.resize(func.NumBBs());
138         regSavedBBs.resize(sizeof(CalleeBitsType) << k8BitShift);
139         for (size_t i = 0; i < bbSavedRegs.size(); ++i) {
140             bbSavedRegs[i] = nullptr;
141         }
142         for (size_t i = 0; i < regSavedBBs.size(); ++i) {
143             regSavedBBs[i] = nullptr;
144         }
145     }
146     ~AArch64RegSavesOpt() override = default;
147 
148     using CalleeBitsType = uint64;
149 
150     void InitData();
151     void CollectLiveInfo(const BB &bb, const Operand &opnd, bool isDef, bool isUse);
152     void GenerateReturnBBDefUse(const BB &bb);
153     void ProcessCallInsnParam(BB &bb);
154     void ProcessAsmListOpnd(const BB &bb, Operand &opnd, uint32 idx);
155     void ProcessListOpnd(const BB &bb, Operand &opnd);
156     void ProcessMemOpnd(const BB &bb, Operand &opnd);
157     void ProcessCondOpnd(const BB &bb);
158     void GetLocalDefUse();
159     void PrintBBs() const;
160     int CheckCriteria(BB *bb, regno_t reg) const;
161     bool AlreadySavedInDominatorList(const BB *bb, regno_t reg) const;
162     void DetermineCalleeSaveLocationsDoms();
163     void DetermineCalleeSaveLocationsPre();
164     bool DetermineCalleeRestoreLocations();
165     int32 FindNextOffsetForCalleeSave() const;
166     void InsertCalleeSaveCode();
167     void InsertCalleeRestoreCode();
168     void Verify(regno_t reg, BB *bb, std::set<BB *, BBIdCmp> *visited, uint32 *s, uint32 *r);
169     void Run() override;
170 
GetDomInfo()171     DomAnalysis *GetDomInfo() const
172     {
173         return domInfo;
174     }
175 
GetPostDomInfo()176     PostDomAnalysis *GetPostDomInfo() const
177     {
178         return pDomInfo;
179     }
180 
GetBfs()181     Bfs *GetBfs() const
182     {
183         return bfs;
184     }
185 
GetCalleeBitsDef()186     CalleeBitsType *GetCalleeBitsDef()
187     {
188         return calleeBitsDef;
189     }
190 
GetCalleeBitsUse()191     CalleeBitsType *GetCalleeBitsUse()
192     {
193         return calleeBitsUse;
194     }
195 
GetBBCalleeBits(CalleeBitsType * data,uint32 bid)196     CalleeBitsType GetBBCalleeBits(CalleeBitsType *data, uint32 bid) const
197     {
198         return data[bid];
199     }
200 
SetCalleeBit(CalleeBitsType * data,uint32 bid,regno_t reg)201     void SetCalleeBit(CalleeBitsType *data, uint32 bid, regno_t reg) const
202     {
203         CalleeBitsType mask = 1ULL << RegBitMap(reg);
204         if ((GetBBCalleeBits(data, bid) & mask) == 0) {
205             data[bid] = GetBBCalleeBits(data, bid) | mask;
206         }
207     }
208 
ResetCalleeBit(CalleeBitsType * data,uint32 bid,regno_t reg)209     void ResetCalleeBit(CalleeBitsType *data, uint32 bid, regno_t reg) const
210     {
211         CalleeBitsType mask = 1ULL << RegBitMap(reg);
212         data[bid] = GetBBCalleeBits(data, bid) & ~mask;
213     }
214 
IsCalleeBitSet(CalleeBitsType * data,uint32 bid,regno_t reg)215     bool IsCalleeBitSet(CalleeBitsType *data, uint32 bid, regno_t reg) const
216     {
217         CalleeBitsType mask = 1ULL << RegBitMap(reg);
218         return GetBBCalleeBits(data, bid) & mask;
219     }
220 
221     /* AArch64 specific callee-save registers bit positions
222         0       9  10                33   -- position
223        R19 ..  R28 V8 .. V15 V16 .. V31   -- regs */
RegBitMap(regno_t reg)224     uint32 RegBitMap(regno_t reg) const
225     {
226         uint32 r;
227         if (reg <= R28) {
228             r = (reg - R19);
229         } else {
230             r = ((R28 - R19) + 1) + (reg - V8);
231         }
232         return r;
233     }
234 
ReverseRegBitMap(uint32 reg)235     regno_t ReverseRegBitMap(uint32 reg) const
236     {
237         constexpr uint32 floatRegisterBitOffset = 10;
238         if (reg < floatRegisterBitOffset) {
239             return static_cast<AArch64reg>(R19 + reg);
240         } else {
241             return static_cast<AArch64reg>((V8 + reg) - (R28 - R19 + 1));
242         }
243     }
244 
GetbbSavedRegsEntry(uint32 bid)245     SavedRegInfo *GetbbSavedRegsEntry(uint32 bid)
246     {
247         if (bbSavedRegs[bid] == nullptr) {
248             bbSavedRegs[bid] = memPool->New<SavedRegInfo>(alloc);
249         }
250         return bbSavedRegs[bid];
251     }
252 
SetId2bb(BB * bb)253     void SetId2bb(BB *bb)
254     {
255         id2bb[bb->GetId()] = bb;
256     }
257 
GetId2bb(uint32 bid)258     BB *GetId2bb(uint32 bid)
259     {
260         return id2bb[bid];
261     }
262 
263 private:
264     DomAnalysis *domInfo;
265     PostDomAnalysis *pDomInfo;
266     LoopAnalysis &loopInfo;
267     Bfs *bfs = nullptr;
268     CalleeBitsType *calleeBitsDef = nullptr;
269     CalleeBitsType *calleeBitsUse = nullptr;
270     MapleVector<SavedRegInfo *> bbSavedRegs; /* set of regs to be saved in a BB */
271     MapleVector<SavedBBInfo *> regSavedBBs;  /* set of BBs to be saved for a reg */
272     MapleMap<regno_t, uint32> regOffset;     /* save offset of each register */
273     MapleMap<uint32, BB *> id2bb;            /* bbid to bb* mapping */
274     bool oneAtaTime = false;
275     regno_t oneAtaTimeReg = 0;
276 };
277 } /* namespace maplebe */
278 
279 #endif /* MAPLEBE_INCLUDE_CG_AARCH64REGSAVESOPT_H */
280