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_REGCOALESCE_H
17 #define MAPLEBE_INCLUDE_CG_REGCOALESCE_H
18 #include "live.h"
19
20 namespace maplebe {
21
22 using posPair = std::pair<uint32, uint32>;
23 class LiveInterval {
24 public:
LiveInterval(MapleAllocator & allocator)25 explicit LiveInterval(MapleAllocator &allocator)
26 : ranges(allocator.Adapter()),
27 conflict(allocator.Adapter()),
28 defPoints(allocator.Adapter()),
29 usePoints(allocator.Adapter()),
30 alloc(allocator)
31 {
32 }
33
IncNumCall()34 void IncNumCall()
35 {
36 ++numCall;
37 }
38
GetRanges()39 MapleMap<uint32, MapleVector<posPair>> GetRanges()
40 {
41 return ranges;
42 }
43
AddRange(uint32 bbid,uint32 end,bool alreadLive)44 void AddRange(uint32 bbid, uint32 end, bool alreadLive)
45 {
46 auto it = ranges.find(bbid);
47 if (it == ranges.end()) {
48 MapleVector<posPair> posVec(alloc.Adapter());
49 posVec.emplace_back(std::pair(end, end));
50 ranges.emplace(bbid, posVec);
51 } else {
52 MapleVector<posPair> &posVec = it->second;
53 if (alreadLive) {
54 CHECK_FATAL(posVec.size() > 0, "must not be zero");
55 posPair lastPos = posVec[posVec.size() - 1];
56 posVec[posVec.size() - 1] = std::pair(end, lastPos.second);
57 } else {
58 posVec.emplace_back(std::pair(end, end));
59 }
60 }
61 }
62
MergeRanges(LiveInterval & lr)63 void MergeRanges(LiveInterval &lr)
64 {
65 auto lrDestRanges = lr.GetRanges();
66 for (auto destRange : lrDestRanges) {
67 uint32 bbid = destRange.first;
68 auto &destPosVec = destRange.second;
69 auto it = ranges.find(bbid);
70 if (it == ranges.end()) {
71 /* directly add it */
72 MapleVector<posPair> posVec(alloc.Adapter());
73 for (auto pos : destPosVec) {
74 posVec.emplace_back(std::pair(pos.first, pos.second));
75 }
76 ranges.emplace(bbid, posVec);
77 } else {
78 /* merge it simply, so that subpos may overlap. */
79 auto &srcPosVec = it->second;
80 for (auto pos1 : destPosVec) {
81 bool merged = false;
82 for (auto &pos2 : srcPosVec) {
83 if (!((pos1.first < pos2.first && pos1.second < pos2.first) ||
84 (pos2.first < pos1.second && pos2.second < pos1.first))) {
85 uint32 bgn = pos1.first < pos2.first ? pos1.first : pos2.first;
86 uint32 end = pos1.second > pos2.second ? pos1.second : pos2.second;
87 pos2 = std::pair(bgn, end);
88 merged = true;
89 }
90 }
91 /* add it directly when no overlap*/
92 if (!merged) {
93 srcPosVec.emplace_back(std::pair(pos1.first, pos1.second));
94 }
95 }
96 }
97 }
98 }
99
MergeConflict(LiveInterval & lr)100 void MergeConflict(LiveInterval &lr)
101 {
102 for (auto reg : lr.conflict) {
103 conflict.insert(reg);
104 }
105 }
106
MergeRefPoints(LiveInterval & lr)107 void MergeRefPoints(LiveInterval &lr)
108 {
109 if (lr.GetDefPoint().size() != k1ByteSize) {
110 for (auto insn : lr.defPoints) {
111 defPoints.insert(insn);
112 }
113 }
114 for (auto insn : lr.usePoints) {
115 usePoints.insert(insn);
116 }
117 }
118
AddConflict(regno_t val)119 void AddConflict(regno_t val)
120 {
121 conflict.insert(val);
122 }
123
GetConflict()124 MapleSet<uint32> GetConflict()
125 {
126 return conflict;
127 }
128
AddRefPoint(Insn * val,bool isDef)129 void AddRefPoint(Insn *val, bool isDef)
130 {
131 if (isDef) {
132 defPoints.insert(val);
133 } else {
134 usePoints.insert(val);
135 }
136 }
137
GetDefPoint()138 InsnMapleSet &GetDefPoint()
139 {
140 return defPoints;
141 }
142
GetUsePoint()143 InsnMapleSet &GetUsePoint()
144 {
145 return usePoints;
146 }
147
IsConflictWith(regno_t val)148 bool IsConflictWith(regno_t val)
149 {
150 return conflict.find(val) != conflict.end();
151 }
152
GetRegType()153 RegType GetRegType() const
154 {
155 return regType;
156 }
157
SetRegType(RegType val)158 void SetRegType(RegType val)
159 {
160 this->regType = val;
161 }
162
GetRegNO()163 regno_t GetRegNO() const
164 {
165 return regno;
166 }
167
SetRegNO(regno_t val)168 void SetRegNO(regno_t val)
169 {
170 this->regno = val;
171 }
172
Dump()173 void Dump()
174 {
175 std::cout << "R" << regno << ": ";
176 for (auto range : ranges) {
177 uint32 bbid = range.first;
178 std::cout << "BB" << bbid << ": < ";
179 for (auto pos : range.second) {
180 std::cout << "[" << pos.first << ", " << pos.second << ") ";
181 }
182 std::cout << " > ";
183 }
184 std::cout << "\n";
185 }
DumpDefs()186 void DumpDefs()
187 {
188 std::cout << "R" << regno << ": ";
189 for (auto def : defPoints) {
190 def->Dump();
191 }
192 std::cout << "\n";
193 }
DumpUses()194 void DumpUses()
195 {
196 std::cout << "R" << regno << ": ";
197 for (auto def : usePoints) {
198 def->Dump();
199 }
200 std::cout << "\n";
201 }
202
203 private:
204 MapleMap<uint32, MapleVector<posPair>> ranges;
205 MapleSet<uint32> conflict;
206 InsnMapleSet defPoints;
207 InsnMapleSet usePoints;
208 uint32 numCall = 0;
209 RegType regType = kRegTyUndef;
210 regno_t regno = 0;
211 MapleAllocator &alloc;
212 };
213
214 class LiveIntervalAnalysis {
215 public:
LiveIntervalAnalysis(CGFunc & func,MemPool & memPool)216 LiveIntervalAnalysis(CGFunc &func, MemPool &memPool)
217 : cgFunc(&func), memPool(&memPool), alloc(&memPool), vregIntervals(alloc.Adapter())
218 {
219 }
220
~LiveIntervalAnalysis()221 virtual ~LiveIntervalAnalysis()
222 {
223 cgFunc = nullptr;
224 memPool = nullptr;
225 bfs = nullptr;
226 }
227
228 virtual void CoalesceRegisters() = 0;
229 void Run();
230 void Analysis();
231 void DoAnalysis();
232 void ClearBFS();
233 void Dump();
234 void CoalesceLiveIntervals(LiveInterval &lrDest, LiveInterval &lrSrc);
GetLiveInterval(regno_t regno)235 LiveInterval *GetLiveInterval(regno_t regno)
236 {
237 auto it = vregIntervals.find(regno);
238 if (it == vregIntervals.end()) {
239 return nullptr;
240 } else {
241 return it->second;
242 }
243 }
244
245 protected:
246 CGFunc *cgFunc;
247 MemPool *memPool;
248 MapleAllocator alloc;
249 MapleMap<regno_t, LiveInterval *> vregIntervals;
250 Bfs *bfs = nullptr;
251 bool runAnalysis = false;
252 };
253
MAPLE_FUNC_PHASE_DECLARE(CgRegCoalesce,maplebe::CGFunc)254 MAPLE_FUNC_PHASE_DECLARE(CgRegCoalesce, maplebe::CGFunc)
255 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CGliveIntervalAnalysis, maplebe::CGFunc)
256 LiveIntervalAnalysis *GetResult()
257 {
258 return liveInterval;
259 }
260 LiveIntervalAnalysis *liveInterval = nullptr;
261 OVERRIDE_DEPENDENCE
262 MAPLE_FUNC_PHASE_DECLARE_END
263 } /* namespace maplebe */
264
265 #endif /* MAPLEBE_INCLUDE_CG_REGCOALESCE_H */
266