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