• 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 #include "live.h"
17 #include <set>
18 #include "cg.h"
19 #include "cg_option.h"
20 #include "cgfunc.h"
21 
22 /*
23  * This phase build two sets: liveOutRegno and liveInRegno of each BB.
24  * This algorithm mainly include 3 parts:
25  * 1. initialize and get def[]/use[] of each BB;
26  * 2. build live_in and live_out based on this algorithm
27  *   Out[B] = U In[S] //S means B's successor;
28  *   In[B] = use[B] U (Out[B]-def[B]);
29  * 3. deal with cleanup BB.
30  */
31 namespace maplebe {
32 #define LIVE_ANALYZE_DUMP_NEWPM CG_DEBUG_FUNC(f)
33 
InitAndGetDefUse()34 void LiveAnalysis::InitAndGetDefUse()
35 {
36     FOR_ALL_BB(bb, cgFunc) {
37         if (!bb->GetEhPreds().empty()) {
38             InitEhDefine(*bb);
39         }
40         InitBB(*bb);
41         GetBBDefUse(*bb);
42         if (bb->GetEhPreds().empty()) {
43             continue;
44         }
45         bb->RemoveInsn(*bb->GetFirstInsn()->GetNext());
46         cgFunc->DecTotalNumberOfInstructions();
47         bb->RemoveInsn(*bb->GetFirstInsn());
48         cgFunc->DecTotalNumberOfInstructions();
49     }
50 }
51 
52 /* Out[BB] = Union all of In[Succs(BB)] */
GenerateLiveOut(BB & bb)53 bool LiveAnalysis::GenerateLiveOut(BB &bb)
54 {
55     const MapleSparseBitVector<> bbLiveOutBak(bb.GetLiveOut()->GetInfo());
56     for (auto succBB : bb.GetSuccs()) {
57         if (succBB->GetLiveInChange() && !succBB->GetLiveIn()->NoneBit()) {
58             bb.LiveOutOrBits(*succBB->GetLiveIn());
59         }
60         if (!succBB->GetEhSuccs().empty()) {
61             for (auto ehSuccBB : succBB->GetEhSuccs()) {
62                 bb.LiveOutOrBits(*ehSuccBB->GetLiveIn());
63             }
64         }
65     }
66     for (auto ehSuccBB : bb.GetEhSuccs()) {
67         if (ehSuccBB->GetLiveInChange() && !ehSuccBB->GetLiveIn()->NoneBit()) {
68             bb.LiveOutOrBits(*ehSuccBB->GetLiveIn());
69         }
70     }
71     return !bb.GetLiveOut()->IsEqual(bbLiveOutBak);
72 }
73 
74 /* In[BB] = use[BB] Union (Out[BB]-def[BB]) */
GenerateLiveIn(BB & bb)75 bool LiveAnalysis::GenerateLiveIn(BB &bb)
76 {
77     LocalMapleAllocator allocator(stackMp);
78     const MapleSparseBitVector<> bbLiveInBak(bb.GetLiveIn()->GetInfo());
79     if (!bb.GetInsertUse()) {
80         bb.SetLiveInInfo(*bb.GetUse());
81         bb.SetInsertUse(true);
82     }
83     SparseDataInfo &bbLiveOut = bb.GetLiveOut()->Clone(allocator);
84     if (!bbLiveOut.NoneBit()) {
85         bbLiveOut.Difference(*bb.GetDef());
86         bb.LiveInOrBits(bbLiveOut);
87     }
88 
89     if (!bb.GetLiveIn()->IsEqual(bbLiveInBak)) {
90         return true;
91     }
92     return false;
93 }
94 
GenerateLiveInByDefUse(SparseDataInfo & liveOut,SparseDataInfo & use,SparseDataInfo & def,const MapleList<BB * > & ehSuccs)95 SparseDataInfo *LiveAnalysis::GenerateLiveInByDefUse(SparseDataInfo &liveOut, SparseDataInfo &use, SparseDataInfo &def,
96                                                      const MapleList<BB *> &ehSuccs)
97 {
98     const uint32 maxRegCount =
99         cgFunc->GetSSAvRegCount() > cgFunc->GetMaxVReg() ? cgFunc->GetSSAvRegCount() : cgFunc->GetMaxVReg();
100     SparseDataInfo *liveIn = memPool->New<SparseDataInfo>(maxRegCount, alloc);
101     liveIn = &use;
102     SparseDataInfo *tmpLiveOut = memPool->New<SparseDataInfo>(liveOut, alloc);
103     if (!liveOut.NoneBit()) {
104         tmpLiveOut->Difference(def);
105         liveIn->OrBits(*tmpLiveOut);
106     }
107     if (!ehSuccs.empty()) {
108         /* if bb has eh successors, check if multi-gen exists. */
109         SparseDataInfo allInOfEhSuccs(maxRegCount, alloc);
110         for (auto ehSucc : ehSuccs) {
111             allInOfEhSuccs.OrBits(*ehSucc->GetLiveIn());
112         }
113         allInOfEhSuccs.AndBits(def);
114         liveIn->OrBits(allInOfEhSuccs);
115     }
116     return liveIn;
117 }
118 
GenerateStackMapLiveIn()119 void LiveAnalysis::GenerateStackMapLiveIn()
120 {
121     const auto &stackMapInsns = cgFunc->GetStackMapInsns();
122     for (auto *insn : stackMapInsns) {
123         BB *curBB = insn->GetBB();
124         SparseDataInfo *liveIn = GenerateLiveInByDefUse(*curBB->GetLiveOut(), *insn->GetStackMapUse(),
125                                                         *insn->GetStackMapDef(), curBB->GetEhSuccs());
126         insn->SetStackMapLiveIn(*liveIn);
127     }
128 }
129 /* building liveIn and liveOut of each BB. */
BuildInOutforFunc()130 void LiveAnalysis::BuildInOutforFunc()
131 {
132     iteration = 0;
133     bool hasChange;
134     do {
135         ++iteration;
136         hasChange = false;
137         FOR_ALL_BB_REV(bb, cgFunc) {
138             if (!GenerateLiveOut(*bb) && bb->GetInsertUse()) {
139                 continue;
140             }
141             if (GenerateLiveIn(*bb)) {
142                 bb->SetLiveInChange(true);
143                 hasChange = true;
144             } else {
145                 bb->SetLiveInChange(false);
146             }
147         }
148     } while (hasChange);
149 }
150 
151 /*  reset to liveout/in_regno */
ResetLiveSet()152 void LiveAnalysis::ResetLiveSet()
153 {
154     FOR_ALL_BB(bb, cgFunc) {
155         bb->GetLiveIn()->GetBitsOfInfo<MapleSet<uint32>>(bb->GetLiveInRegNO());
156         bb->GetLiveOut()->GetBitsOfInfo<MapleSet<uint32>>(bb->GetLiveOutRegNO());
157     }
158 }
159 
160 /* entry function for LiveAnalysis */
AnalysisLive()161 void LiveAnalysis::AnalysisLive()
162 {
163     InitAndGetDefUse();
164     BuildInOutforFunc();
165     InsertInOutOfCleanupBB();
166     GenerateStackMapLiveIn();
167 }
168 
DealWithInOutOfCleanupBB()169 void LiveAnalysis::DealWithInOutOfCleanupBB()
170 {
171     const BB *cleanupBB = cgFunc->GetCleanupEntryBB();
172     if (cleanupBB == nullptr) {
173         return;
174     }
175     for (size_t i = 0; i != cleanupBB->GetLiveIn()->Size(); ++i) {
176         if (!cleanupBB->GetLiveIn()->TestBit(i)) {
177             continue;
178         }
179         if (CleanupBBIgnoreReg(regno_t(i))) {
180             continue;
181         }
182         /*
183          * a param vreg may used in cleanup bb. So this param vreg will live on the whole function
184          * since everywhere in function body may occur exceptions.
185          */
186         FOR_ALL_BB(bb, cgFunc) {
187             if (bb->IsCleanup()) {
188                 continue;
189             }
190             /* If bb is not a cleanup bb, then insert reg to both livein and liveout. */
191             if ((bb != cgFunc->GetFirstBB()) && !bb->GetDef()->TestBit(i)) {
192                 bb->SetLiveInBit(i);
193             }
194             bb->SetLiveOutBit(i);
195         }
196     }
197 }
198 
InsertInOutOfCleanupBB()199 void LiveAnalysis::InsertInOutOfCleanupBB()
200 {
201     const BB *cleanupBB = cgFunc->GetCleanupEntryBB();
202     if (cleanupBB == nullptr) {
203         return;
204     }
205     if (cleanupBB->GetLiveIn() == nullptr || cleanupBB->GetLiveIn()->NoneBit()) {
206         return;
207     }
208     SparseDataInfo cleanupBBLi = *(cleanupBB->GetLiveIn());
209     /* registers need to be ignored: (reg < 8) || (29 <= reg && reg <= 32) */
210     for (uint32 i = 1; i < 8; ++i) { // reset 8 reg for R0-R7
211         cleanupBBLi.ResetBit(i);
212     }
213     for (uint32 j = 29; j <= 32; ++j) { // registers 29 ~ 32 need to be ignored
214         cleanupBBLi.ResetBit(j);
215     }
216 
217     FOR_ALL_BB(bb, cgFunc) {
218         if (bb->IsCleanup()) {
219             continue;
220         }
221         if (bb != cgFunc->GetFirstBB()) {
222             cleanupBBLi.Difference(*bb->GetDef());
223             bb->LiveInOrBits(cleanupBBLi);
224         }
225         bb->LiveOutOrBits(cleanupBBLi);
226     }
227 }
228 
MarkStackMapInsn(Insn & insn,BB & bb)229 void LiveAnalysis::MarkStackMapInsn(Insn &insn, BB &bb)
230 {
231     insn.SetStackMapDef(*NewDef(*bb.GetDef()));
232     insn.SetStackMapUse(*NewUse(*bb.GetUse()));
233 }
234 
235 /*
236  * entry of get def/use of bb.
237  * getting the def or use info of each regopnd as parameters of CollectLiveInfo().
238  */
GetBBDefUse(BB & bb)239 void LiveAnalysis::GetBBDefUse(BB &bb)
240 {
241     if (bb.GetKind() == BB::kBBReturn) {
242         GenerateReturnBBDefUse(bb);
243     }
244     if (bb.IsEmpty()) {
245         return;
246     }
247 
248     FOR_BB_INSNS_REV(insn, &bb)
249     {
250         if (!insn->IsMachineInstruction()) {
251             continue;
252         }
253 
254         if (insn->IsCall()) {
255             MarkStackMapInsn(*insn, bb);
256         }
257 
258         bool isAsm = insn->IsAsmInsn();
259         const InsnDesc *md = insn->GetDesc();
260         if (insn->IsCall() || insn->IsTailCall()) {
261             ProcessCallInsnParam(bb, *insn);
262         }
263         uint32 opndNum = insn->GetOperandSize();
264         for (uint32 i = 0; i < opndNum; ++i) {
265             const OpndDesc *opndDesc = md->GetOpndDes(i);
266             DEBUG_ASSERT(opndDesc != nullptr, "null ptr check");
267             Operand &opnd = insn->GetOperand(i);
268             if (opnd.IsList()) {
269                 if (isAsm) {
270                     ProcessAsmListOpnd(bb, opnd, i);
271                 } else {
272                     ProcessListOpnd(bb, opnd, opndDesc->IsDef());
273                 }
274             } else if (opnd.IsMemoryAccessOperand()) {
275                 ProcessMemOpnd(bb, opnd);
276             } else if (opnd.IsConditionCode()) {
277                 ProcessCondOpnd(bb);
278             } else {
279                 bool isDef = opndDesc->IsRegDef();
280                 bool isUse = opndDesc->IsRegUse();
281                 CollectLiveInfo(bb, opnd, isDef, isUse);
282             }
283         }
284     }
285 }
286 
287 /* build use and def sets of each BB according to the type of regOpnd. */
CollectLiveInfo(BB & bb,const Operand & opnd,bool isDef,bool isUse) const288 void LiveAnalysis::CollectLiveInfo(BB &bb, const Operand &opnd, bool isDef, bool isUse) const
289 {
290     if (!opnd.IsRegister()) {
291         return;
292     }
293     const RegOperand &regOpnd = static_cast<const RegOperand &>(opnd);
294     regno_t regNO = regOpnd.GetRegisterNumber();
295     RegType regType = regOpnd.GetRegisterType();
296     if (regType == kRegTyVary) {
297         return;
298     }
299     if (isDef) {
300         bb.SetDefBit(regNO);
301         if (!isUse) {
302             bb.UseResetBit(regNO);
303         }
304     }
305     if (isUse) {
306         bb.SetUseBit(regNO);
307         bb.DefResetBit(regNO);
308     }
309 }
310 
ProcessAsmListOpnd(BB & bb,Operand & opnd,uint32 idx) const311 void LiveAnalysis::ProcessAsmListOpnd(BB &bb, Operand &opnd, uint32 idx) const
312 {
313     bool isDef = false;
314     bool isUse = false;
315     switch (idx) {
316         case kAsmOutputListOpnd:
317         case kAsmClobberListOpnd: {
318             isDef = true;
319             break;
320         }
321         case kAsmInputListOpnd: {
322             isUse = true;
323             break;
324         }
325         default:
326             return;
327     }
328     ListOperand &listOpnd = static_cast<ListOperand &>(opnd);
329     for (auto op : listOpnd.GetOperands()) {
330         CollectLiveInfo(bb, *op, isDef, isUse);
331     }
332 }
333 
ProcessListOpnd(BB & bb,Operand & opnd,bool isDef) const334 void LiveAnalysis::ProcessListOpnd(BB &bb, Operand &opnd, bool isDef) const
335 {
336     ListOperand &listOpnd = static_cast<ListOperand &>(opnd);
337     for (auto op : listOpnd.GetOperands()) {
338         CollectLiveInfo(bb, *op, isDef, !isDef);
339     }
340 }
341 
ProcessMemOpnd(BB & bb,Operand & opnd) const342 void LiveAnalysis::ProcessMemOpnd(BB &bb, Operand &opnd) const
343 {
344     auto &memOpnd = static_cast<MemOperand &>(opnd);
345     Operand *base = memOpnd.GetBaseRegister();
346     Operand *offset = memOpnd.GetIndexRegister();
347     if (base != nullptr) {
348         CollectLiveInfo(bb, *base, !memOpnd.IsIntactIndexed(), true);
349     }
350     if (offset != nullptr) {
351         CollectLiveInfo(bb, *offset, false, true);
352     }
353 }
354 
ProcessCondOpnd(BB & bb) const355 void LiveAnalysis::ProcessCondOpnd(BB &bb) const
356 {
357     Operand &rflag = cgFunc->GetOrCreateRflag();
358     CollectLiveInfo(bb, rflag, false, true);
359 }
360 
361 /* dump the current info of def/use/livein/liveout */
Dump() const362 void LiveAnalysis::Dump() const
363 {
364     MIRSymbol *funcSt = GlobalTables::GetGsymTable().GetSymbolFromStidx(cgFunc->GetFunction().GetStIdx().Idx());
365     DEBUG_ASSERT(funcSt != nullptr, "null ptr check");
366     LogInfo::MapleLogger() << "\n---------  liveness for " << funcSt->GetName() << "  iteration ";
367     LogInfo::MapleLogger() << iteration << " ---------\n";
368     FOR_ALL_BB(bb, cgFunc) {
369         LogInfo::MapleLogger() << "  === BB_" << bb->GetId() << " (" << std::hex << bb << ") " << std::dec << " <"
370                                << bb->GetKindName();
371         if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
372             LogInfo::MapleLogger() << "[labeled with " << bb->GetLabIdx() << "]";
373         }
374         LogInfo::MapleLogger() << "> idx " << bb->GetId() << " ===\n";
375 
376         if (!bb->GetPreds().empty()) {
377             LogInfo::MapleLogger() << "    pred [ ";
378             for (auto *pred : bb->GetPreds()) {
379                 LogInfo::MapleLogger() << pred->GetId() << " (" << std::hex << pred << ") " << std::dec << " ";
380             }
381             LogInfo::MapleLogger() << "]\n";
382         }
383         if (!bb->GetSuccs().empty()) {
384             LogInfo::MapleLogger() << "    succ [ ";
385             for (auto *succ : bb->GetSuccs()) {
386                 LogInfo::MapleLogger() << succ->GetId() << " (" << std::hex << succ << ") " << std::dec << " ";
387             }
388             LogInfo::MapleLogger() << "]\n";
389         }
390 
391         const SparseDataInfo *infoDef = nullptr;
392         LogInfo::MapleLogger() << "    DEF: ";
393         infoDef = bb->GetDef();
394         DumpInfo(*infoDef);
395 
396         const SparseDataInfo *infoUse = nullptr;
397         LogInfo::MapleLogger() << "\n    USE: ";
398         infoUse = bb->GetUse();
399         DumpInfo(*infoUse);
400 
401         const SparseDataInfo *infoLiveIn = nullptr;
402         LogInfo::MapleLogger() << "\n    Live IN: ";
403         infoLiveIn = bb->GetLiveIn();
404         DumpInfo(*infoLiveIn);
405 
406         const SparseDataInfo *infoLiveOut = nullptr;
407         LogInfo::MapleLogger() << "\n    Live OUT: ";
408         infoLiveOut = bb->GetLiveOut();
409         DumpInfo(*infoLiveOut);
410         LogInfo::MapleLogger() << "\n";
411     }
412     LogInfo::MapleLogger() << "---------------------------\n";
413 }
414 
DumpInfo(const SparseDataInfo & info) const415 void LiveAnalysis::DumpInfo(const SparseDataInfo &info) const
416 {
417     uint32 count = 1;
418     std::set<uint32> res;
419     info.GetInfo().ConvertToSet(res);
420     for (uint32 x : res) {
421         LogInfo::MapleLogger() << x << " ";
422         ++count;
423         /* 20 output one line */
424         if ((count % 20) == 0) {
425             LogInfo::MapleLogger() << "\n";
426         }
427     }
428     LogInfo::MapleLogger() << '\n';
429 }
430 
431 /* initialize dependent info and container of BB. */
InitBB(BB & bb)432 void LiveAnalysis::InitBB(BB &bb)
433 {
434     bb.SetLiveInChange(true);
435     bb.SetInsertUse(false);
436     bb.ClearLiveInRegNO();
437     bb.ClearLiveOutRegNO();
438     const uint32 maxRegCount =
439         cgFunc->GetSSAvRegCount() > cgFunc->GetMaxVReg() ? cgFunc->GetSSAvRegCount() : cgFunc->GetMaxVReg();
440     bb.SetLiveIn(*NewLiveIn(maxRegCount));
441     bb.SetLiveOut(*NewLiveOut(maxRegCount));
442     bb.SetDef(*NewDef(maxRegCount));
443     bb.SetUse(*NewUse(maxRegCount));
444 }
445 
ClearInOutDataInfo()446 void LiveAnalysis::ClearInOutDataInfo()
447 {
448     FOR_ALL_BB(bb, cgFunc) {
449         bb->SetLiveInChange(false);
450         bb->DefClearDataInfo();
451         bb->UseClearDataInfo();
452         bb->LiveInClearDataInfo();
453         bb->LiveOutClearDataInfo();
454     }
455 }
456 
EnlargeSpaceForLiveAnalysis(BB & currBB)457 void LiveAnalysis::EnlargeSpaceForLiveAnalysis(BB &currBB)
458 {
459     regno_t currMaxVRegNO = cgFunc->GetMaxVReg();
460     if (currMaxVRegNO >= currBB.GetLiveIn()->Size()) {
461         FOR_ALL_BB(bb, cgFunc) {
462             bb->LiveInEnlargeCapacity(currMaxVRegNO);
463             bb->LiveOutEnlargeCapacity(currMaxVRegNO);
464         }
465     }
466 }
467 
GetAnalysisDependence(AnalysisDep & aDep) const468 void CgLiveAnalysis::GetAnalysisDependence(AnalysisDep &aDep) const
469 {
470 #if TARGX86_64
471     aDep.AddRequired<CgHandleCFG>();
472 #endif
473     aDep.SetPreservedAll();
474 }
475 
PhaseRun(maplebe::CGFunc & f)476 bool CgLiveAnalysis::PhaseRun(maplebe::CGFunc &f)
477 {
478     MemPool *liveMemPool = GetPhaseMemPool();
479     live = f.GetCG()->CreateLiveAnalysis(*liveMemPool, f);
480     CHECK_FATAL(live != nullptr, "NIY");
481     live->AnalysisLive();
482     if (LIVE_ANALYZE_DUMP_NEWPM) {
483         live->Dump();
484     }
485     live->ResetLiveSet();
486     return false;
487 }
488 MAPLE_ANALYSIS_PHASE_REGISTER(CgLiveAnalysis, liveanalysis)
489 } /* namespace maplebe */
490