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