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_AARCH64_AARCH64_SCHEDULE_H 17 #define MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_SCHEDULE_H 18 19 #include "schedule.h" 20 #include "aarch64_operand.h" 21 22 namespace maplebe { 23 enum RegisterType : uint8 { 24 kRegisterUndef, 25 kRegisterInt, 26 kRegisterFloat, 27 kRegisterCc, 28 kRegisterLast, 29 }; 30 31 class ScheduleProcessInfo { 32 public: ScheduleProcessInfo(uint32 size)33 explicit ScheduleProcessInfo(uint32 size) 34 { 35 availableReadyList.reserve(size); 36 scheduledNodes.reserve(size); 37 } 38 39 virtual ~ScheduleProcessInfo() = default; 40 GetLastUpdateCycle()41 uint32 GetLastUpdateCycle() const 42 { 43 return lastUpdateCycle; 44 } 45 SetLastUpdateCycle(uint32 updateCycle)46 void SetLastUpdateCycle(uint32 updateCycle) 47 { 48 lastUpdateCycle = updateCycle; 49 } 50 GetCurrCycle()51 uint32 GetCurrCycle() const 52 { 53 return currCycle; 54 } 55 IncCurrCycle()56 void IncCurrCycle() 57 { 58 ++currCycle; 59 } 60 DecAdvanceCycle()61 void DecAdvanceCycle() 62 { 63 advanceCycle--; 64 } 65 GetAdvanceCycle()66 uint32 GetAdvanceCycle() const 67 { 68 return advanceCycle; 69 } 70 SetAdvanceCycle(uint32 cycle)71 void SetAdvanceCycle(uint32 cycle) 72 { 73 advanceCycle = cycle; 74 } 75 ClearAvailableReadyList()76 void ClearAvailableReadyList() 77 { 78 availableReadyList.clear(); 79 } 80 PushElemIntoAvailableReadyList(DepNode * node)81 void PushElemIntoAvailableReadyList(DepNode *node) 82 { 83 availableReadyList.emplace_back(node); 84 } 85 SizeOfAvailableReadyList()86 size_t SizeOfAvailableReadyList() const 87 { 88 return availableReadyList.size(); 89 } 90 AvailableReadyListIsEmpty()91 bool AvailableReadyListIsEmpty() const 92 { 93 return availableReadyList.empty(); 94 } 95 SetAvailableReadyList(const std::vector<DepNode * > & tempReadyList)96 void SetAvailableReadyList(const std::vector<DepNode *> &tempReadyList) 97 { 98 availableReadyList = tempReadyList; 99 } 100 GetAvailableReadyList()101 const std::vector<DepNode *> &GetAvailableReadyList() const 102 { 103 return availableReadyList; 104 } 105 GetAvailableReadyList()106 const std::vector<DepNode *> &GetAvailableReadyList() 107 { 108 return availableReadyList; 109 } 110 PushElemIntoScheduledNodes(DepNode * node)111 void PushElemIntoScheduledNodes(DepNode *node) 112 { 113 node->SetState(kScheduled); 114 node->SetSchedCycle(currCycle); 115 node->OccupyUnits(); 116 scheduledNodes.emplace_back(node); 117 } 118 IsFirstSeparator()119 bool IsFirstSeparator() const 120 { 121 return isFirstSeparator; 122 } 123 ResetIsFirstSeparator()124 void ResetIsFirstSeparator() 125 { 126 isFirstSeparator = false; 127 } 128 SizeOfScheduledNodes()129 size_t SizeOfScheduledNodes() const 130 { 131 return scheduledNodes.size(); 132 } 133 GetScheduledNodes()134 const std::vector<DepNode *> &GetScheduledNodes() const 135 { 136 return scheduledNodes; 137 } 138 139 private: 140 std::vector<DepNode *> availableReadyList; 141 std::vector<DepNode *> scheduledNodes; 142 uint32 lastUpdateCycle = 0; 143 uint32 currCycle = 0; 144 uint32 advanceCycle = 0; 145 bool isFirstSeparator = true; 146 }; 147 148 class AArch64ScheduleProcessInfo : public ScheduleProcessInfo { 149 public: AArch64ScheduleProcessInfo(uint32 size)150 explicit AArch64ScheduleProcessInfo(uint32 size) : ScheduleProcessInfo(size) {} 151 ~AArch64ScheduleProcessInfo() override = default; 152 153 /* recover register type which is not recorded in live analysis */ 154 static RegType GetRegisterType(CGFunc &f, regno_t regNO); 155 void VaryLiveRegSet(CGFunc &f, regno_t regNO, bool isInc); 156 void VaryFreeRegSet(CGFunc &f, std::set<regno_t> regNOs, DepNode &node); 157 GetFreeIntRegs(DepNode & node)158 uint32 GetFreeIntRegs(DepNode &node) 159 { 160 return freeIntRegNodeSet.count(&node) ? freeIntRegNodeSet.find(&node)->second : 0; 161 } IncFreeIntRegNode(DepNode & node)162 void IncFreeIntRegNode(DepNode &node) 163 { 164 if (!freeIntRegNodeSet.count(&node)) { 165 freeIntRegNodeSet.emplace(std::pair<DepNode *, uint32>(&node, 1)); 166 } else { 167 freeIntRegNodeSet.find(&node)->second++; 168 } 169 } GetFreeIntRegNodeSet()170 const std::map<DepNode *, uint32> &GetFreeIntRegNodeSet() const 171 { 172 return freeIntRegNodeSet; 173 } IncFreeFpRegNode(DepNode & node)174 void IncFreeFpRegNode(DepNode &node) 175 { 176 if (!freeFpRegNodeSet.count(&node)) { 177 freeFpRegNodeSet.emplace(std::pair<DepNode *, uint32>(&node, 1)); 178 } else { 179 freeFpRegNodeSet.find(&node)->second++; 180 } 181 } GetFreeFpRegs(DepNode & node)182 uint32 GetFreeFpRegs(DepNode &node) 183 { 184 return freeFpRegNodeSet.count(&node) ? freeFpRegNodeSet.find(&node)->second : 0; 185 } GetFreeFpRegNodeSet()186 const std::map<DepNode *, uint32> &GetFreeFpRegNodeSet() const 187 { 188 return freeFpRegNodeSet; 189 } 190 ClearALLFreeRegNodeSet()191 void ClearALLFreeRegNodeSet() 192 { 193 freeIntRegNodeSet.clear(); 194 freeFpRegNodeSet.clear(); 195 } 196 FindIntLiveReg(regno_t reg)197 size_t FindIntLiveReg(regno_t reg) const 198 { 199 return intLiveRegSet.count(reg); 200 } IncIntLiveRegSet(regno_t reg)201 void IncIntLiveRegSet(regno_t reg) 202 { 203 intLiveRegSet.emplace(reg); 204 } DecIntLiveRegSet(regno_t reg)205 void DecIntLiveRegSet(regno_t reg) 206 { 207 intLiveRegSet.erase(reg); 208 } FindFpLiveReg(regno_t reg)209 size_t FindFpLiveReg(regno_t reg) const 210 { 211 return fpLiveRegSet.count(reg); 212 } IncFpLiveRegSet(regno_t reg)213 void IncFpLiveRegSet(regno_t reg) 214 { 215 fpLiveRegSet.emplace(reg); 216 } DecFpLiveRegSet(regno_t reg)217 void DecFpLiveRegSet(regno_t reg) 218 { 219 fpLiveRegSet.erase(reg); 220 } 221 SizeOfIntLiveRegSet()222 size_t SizeOfIntLiveRegSet() const 223 { 224 return intLiveRegSet.size(); 225 } 226 SizeOfCalleeSaveLiveRegister(bool isInt)227 size_t SizeOfCalleeSaveLiveRegister(bool isInt) 228 { 229 size_t num = 0; 230 if (isInt) { 231 for (auto regNO : intLiveRegSet) { 232 if (regNO > static_cast<regno_t>(R19)) { 233 num++; 234 } 235 } 236 } else { 237 for (auto regNO : fpLiveRegSet) { 238 if (regNO > static_cast<regno_t>(V16)) { 239 num++; 240 } 241 } 242 } 243 return num; 244 } 245 SizeOfFpLiveRegSet()246 size_t SizeOfFpLiveRegSet() const 247 { 248 return fpLiveRegSet.size(); 249 } 250 251 private: 252 std::set<regno_t> intLiveRegSet; 253 std::set<regno_t> fpLiveRegSet; 254 std::map<DepNode *, uint32> freeIntRegNodeSet; 255 std::map<DepNode *, uint32> freeFpRegNodeSet; 256 }; 257 258 class AArch64Schedule : public Schedule { 259 public: AArch64Schedule(CGFunc & func,MemPool & memPool,LiveAnalysis & live,const std::string & phaseName)260 AArch64Schedule(CGFunc &func, MemPool &memPool, LiveAnalysis &live, const std::string &phaseName) 261 : Schedule(func, memPool, live, phaseName) 262 { 263 intCalleeSaveThreshold = func.UseFP() ? intCalleeSaveThresholdBase : intCalleeSaveThresholdEnhance; 264 } 265 ~AArch64Schedule() override = default; 266 267 protected: 268 void DumpDepGraph(const MapleVector<DepNode *> &nodes) const; 269 void DumpScheduleResult(const MapleVector<DepNode *> &nodes, SimulateType type) const; 270 void GenerateDot(const BB &bb, const MapleVector<DepNode *> &nodes) const; 271 void EraseNodeFromNodeList(const DepNode &target, MapleVector<DepNode *> &nodeList) override; 272 void FindAndCombineMemoryAccessPair(const std::vector<DepNode *> &memList) override; 273 void RegPressureScheduling(BB &bb, MapleVector<DepNode *> &nodes) override; 274 275 private: 276 enum CSRResult : uint8 { 277 kNode1, 278 kNode2, 279 kDoCSP /* can do csp further */ 280 }; 281 void Init() override; 282 void MemoryAccessPairOpt() override; 283 void ClinitPairOpt() override; 284 uint32 DoSchedule() override; 285 uint32 DoBruteForceSchedule() override; 286 uint32 SimulateOnly() override; 287 void UpdateBruteForceSchedCycle() override; 288 void IterateBruteForce(DepNode &targetNode, MapleVector<DepNode *> &readyList, uint32 currCycle, 289 MapleVector<DepNode *> &scheduledNodes, uint32 &maxCycleCount, 290 MapleVector<DepNode *> &optimizedScheduledNodes) override; 291 bool CanCombine(const Insn &insn) const override; 292 void ListScheduling(bool beforeRA) override; 293 void BruteForceScheduling(const BB &bb); 294 void SimulateScheduling(const BB &bb); 295 void FinalizeScheduling(BB &bb, const DepAnalysis &depAnalysis) override; 296 uint32 ComputeEstart(uint32 cycle) override; 297 void ComputeLstart(uint32 maxEstart) override; 298 void UpdateELStartsOnCycle(uint32 cycle) override; 299 void RandomTest() override; 300 void EraseNodeFromReadyList(const DepNode &target) override; 301 uint32 GetNextSepIndex() const override; 302 void CountUnitKind(const DepNode &depNode, uint32 array[], const uint32 arraySize) const override; 303 static bool IfUseUnitKind(const DepNode &depNode, uint32 index); 304 void UpdateReadyList(DepNode &targetNode, MapleVector<DepNode *> &readyList, bool updateEStart) override; 305 void UpdateScheduleProcessInfo(AArch64ScheduleProcessInfo &info); 306 void UpdateAdvanceCycle(AArch64ScheduleProcessInfo &scheduleInfo, const DepNode &targetNode); 307 bool CheckSchedulable(AArch64ScheduleProcessInfo &info) const; 308 void SelectNode(AArch64ScheduleProcessInfo &scheduleInfo); 309 static void DumpDebugInfo(const ScheduleProcessInfo &scheduleInfo); 310 bool CompareDepNode(DepNode &node1, DepNode &node2, AArch64ScheduleProcessInfo &scheduleInfo) const; 311 void CalculateMaxUnitKindCount(ScheduleProcessInfo &scheduleInfo); 312 void UpdateReleaseRegInfo(AArch64ScheduleProcessInfo &scheduleInfo); 313 std::set<regno_t> CanFreeRegister(const DepNode &node) const; 314 void UpdateLiveRegSet(AArch64ScheduleProcessInfo &scheduleInfo, const DepNode &node); 315 void InitLiveRegSet(AArch64ScheduleProcessInfo &scheduleInfo); 316 int CalSeriesCycles(const MapleVector<DepNode *> &nodes); 317 CSRResult DoCSR(DepNode &node1, DepNode &node2, AArch64ScheduleProcessInfo &scheduleInfo) const; 318 AArch64Schedule::CSRResult ScheduleCrossCall(const DepNode &node1, const DepNode &node2) const; 319 int intCalleeSaveThreshold = 0; 320 321 static uint32 maxUnitIndex; 322 static int intRegPressureThreshold; 323 static int fpRegPressureThreshold; 324 static int intCalleeSaveThresholdBase; 325 static int intCalleeSaveThresholdEnhance; 326 static int fpCalleeSaveThreshold; 327 }; 328 } /* namespace maplebe */ 329 330 #endif /* MAPLEBE_INCLUDE_CG_AARCH64_AARCH64_SCHEDULE_H */ 331