• 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 "cg_ssa.h"
17 #include "cg.h"
18 
19 #include "optimize_common.h"
20 
21 namespace maplebe {
22 uint32 CGSSAInfo::SSARegNObase = 100;
ConstructSSA()23 void CGSSAInfo::ConstructSSA()
24 {
25     InsertPhiInsn();
26     /* Rename variables */
27     RenameVariablesForBB(domInfo->GetCommonEntryBB().GetId());
28 #if DEBUG
29     /* Check phiListOpnd, must be ssaForm */
30     FOR_ALL_BB(bb, cgFunc)
31     {
32         FOR_BB_INSNS(insn, bb)
33         {
34             if (!insn->IsPhi()) {
35                 continue;
36             }
37             Operand &phiListOpnd = insn->GetOperand(kInsnSecondOpnd);
38             CHECK_FATAL(phiListOpnd.IsPhi(), "unexpect phi operand");
39             MapleMap<uint32, RegOperand *> &phiList = static_cast<PhiOperand &>(phiListOpnd).GetOperands();
40             for (auto &phiOpndIt : phiList) {
41                 if (!phiOpndIt.second->IsSSAForm()) {
42                     CHECK_FATAL(false, "phiOperand is not ssaForm!");
43                 }
44             }
45         }
46     }
47 #endif
48     cgFunc->SetSSAvRegCount(static_cast<uint32>(GetAllSSAOperands().size()) + SSARegNObase + 1);
49     /* save reversePostOrder of bbs for rectify validbit */
50     SetReversePostOrder();
51 }
52 
MarkInsnsInSSA(Insn & insn)53 void CGSSAInfo::MarkInsnsInSSA(Insn &insn)
54 {
55     CHECK_FATAL(insn.GetId() == 0, "insn is not clean !!"); /* change to assert*/
56     insnCount += kInsnNum2;
57     insn.SetId(static_cast<uint32>(insnCount));
58 }
59 
InsertPhiInsn()60 void CGSSAInfo::InsertPhiInsn()
61 {
62     FOR_ALL_BB(bb, cgFunc)
63     {
64         FOR_BB_INSNS(insn, bb)
65         {
66             if (!insn->IsMachineInstruction()) {
67                 continue;
68             }
69             std::set<uint32> defRegNOs = insn->GetDefRegs();
70             for (auto vRegNO : defRegNOs) {
71                 RegOperand *virtualOpnd = cgFunc->GetVirtualRegisterOperand(vRegNO);
72                 if (virtualOpnd != nullptr) {
73                     PrunedPhiInsertion(*bb, *virtualOpnd);
74                 }
75             }
76         }
77     }
78 }
79 
PrunedPhiInsertion(const BB & bb,RegOperand & virtualOpnd)80 void CGSSAInfo::PrunedPhiInsertion(const BB &bb, RegOperand &virtualOpnd)
81 {
82     regno_t vRegNO = virtualOpnd.GetRegisterNumber();
83     MapleVector<uint32> frontiers = domInfo->GetDomFrontier(bb.GetId());
84     for (auto i : frontiers) {
85         BB *phiBB = cgFunc->GetBBFromID(i);
86         CHECK_FATAL(phiBB != nullptr, "get phiBB failed change to DEBUG_ASSERT");
87         if (phiBB->HasPhiInsn(vRegNO)) {
88             continue;
89         }
90         if (phiBB->GetLiveIn()->TestBit(vRegNO)) {
91             CG *codeGen = cgFunc->GetCG();
92             PhiOperand &phiList = codeGen->CreatePhiOperand(*memPool, ssaAlloc);
93             /* do not insert phi opnd when insert phi insn? */
94             for (auto prevBB : phiBB->GetPreds()) {
95                 if (prevBB->GetLiveOut()->TestBit(vRegNO)) {
96                     auto *paraOpnd = static_cast<RegOperand *>(virtualOpnd.Clone(*tempMp));
97                     phiList.InsertOpnd(prevBB->GetId(), *paraOpnd);
98                 } else {
99                     CHECK_FATAL(false, "multipule BB in");
100                 }
101             }
102             Insn &phiInsn = codeGen->BuildPhiInsn(virtualOpnd, phiList);
103             MarkInsnsInSSA(phiInsn);
104             bool insertSuccess = false;
105             FOR_BB_INSNS(insn, phiBB)
106             {
107                 if (insn->IsMachineInstruction()) {
108                     (void)phiBB->InsertInsnBefore(*insn, phiInsn);
109                     insertSuccess = true;
110                     break;
111                 }
112             }
113             if (!insertSuccess) {
114                 phiBB->InsertInsnBegin(phiInsn);
115             }
116             phiBB->AddPhiInsn(vRegNO, phiInsn);
117             PrunedPhiInsertion(*phiBB, virtualOpnd);
118         }
119     }
120 }
121 
RenameVariablesForBB(uint32 bbID)122 void CGSSAInfo::RenameVariablesForBB(uint32 bbID)
123 {
124     RenameBB(*cgFunc->GetBBFromID(bbID)); /* rename first BB */
125     const auto &domChildren = domInfo->GetDomChildren(bbID);
126     for (const auto &child : domChildren) {
127         RenameBB(*cgFunc->GetBBFromID(child));
128     }
129 }
130 
RenameBB(BB & bb)131 void CGSSAInfo::RenameBB(BB &bb)
132 {
133     if (IsBBRenamed(bb.GetId())) {
134         return;
135     }
136     AddRenamedBB(bb.GetId());
137     /* record version stack size */
138     size_t tempSize =
139         vRegStk.empty() ? allSSAOperands.size() + cgFunc->GetFirstMapleIrVRegNO() + 1 : vRegStk.rbegin()->first + 1;
140     std::vector<int32> oriStackSize(tempSize, -1);
141     for (auto it : vRegStk) {
142         DEBUG_ASSERT(it.first < oriStackSize.size(), "out of range");
143         oriStackSize[it.first] = static_cast<int32>(it.second.size());
144     }
145     RenamePhi(bb);
146     FOR_BB_INSNS(insn, &bb)
147     {
148         if (!insn->IsMachineInstruction()) {
149             continue;
150         }
151         MarkInsnsInSSA(*insn);
152         RenameInsn(*insn);
153     }
154     RenameSuccPhiUse(bb);
155     RenameVariablesForBB(bb.GetId());
156     /* stack pop up */
157     for (auto &it : vRegStk) {
158         if (it.first < oriStackSize.size() && oriStackSize[it.first] >= 0) {
159             while (static_cast<int32>(it.second.size()) > oriStackSize[static_cast<uint64>(it.first)]) {
160                 DEBUG_ASSERT(!it.second.empty(), "empty stack");
161                 it.second.pop();
162             }
163         }
164     }
165 }
166 
RenamePhi(BB & bb)167 void CGSSAInfo::RenamePhi(BB &bb)
168 {
169     for (auto phiInsnIt : bb.GetPhiInsns()) {
170         Insn *phiInsn = phiInsnIt.second;
171         CHECK_FATAL(phiInsn != nullptr, "get phi insn failed");
172         auto *phiDefOpnd = static_cast<RegOperand *>(&phiInsn->GetOperand(kInsnFirstOpnd));
173         VRegVersion *newVst = CreateNewVersion(*phiDefOpnd, *phiInsn, kInsnFirstOpnd, true);
174         phiInsn->SetOperand(kInsnFirstOpnd, *newVst->GetSSAvRegOpnd());
175     }
176 }
177 
RenameSuccPhiUse(const BB & bb)178 void CGSSAInfo::RenameSuccPhiUse(const BB &bb)
179 {
180     for (auto *sucBB : bb.GetSuccs()) {
181         for (auto phiInsnIt : sucBB->GetPhiInsns()) {
182             Insn *phiInsn = phiInsnIt.second;
183             CHECK_FATAL(phiInsn != nullptr, "get phi insn failed");
184             Operand *phiListOpnd = &phiInsn->GetOperand(kInsnSecondOpnd);
185             CHECK_FATAL(phiListOpnd->IsPhi(), "unexpect phi operand");
186             MapleMap<uint32, RegOperand *> &phiList = static_cast<PhiOperand *>(phiListOpnd)->GetOperands();
187             DEBUG_ASSERT(phiList.size() <= sucBB->GetPreds().size(), "unexpect phiList size need check");
188             for (auto phiOpndIt = phiList.begin(); phiOpndIt != phiList.end(); ++phiOpndIt) {
189                 if (phiOpndIt->first == bb.GetId()) {
190                     RegOperand *renamedOpnd = GetRenamedOperand(*(phiOpndIt->second), false, *phiInsn, kInsnSecondOpnd);
191                     phiList[phiOpndIt->first] = renamedOpnd;
192                 }
193             }
194         }
195     }
196 }
197 
IncreaseVregCount(regno_t vRegNO)198 uint32 CGSSAInfo::IncreaseVregCount(regno_t vRegNO)
199 {
200     if (!vRegDefCount.count(vRegNO)) {
201         vRegDefCount.emplace(vRegNO, 0);
202     } else {
203         vRegDefCount[vRegNO]++;
204     }
205     return vRegDefCount[vRegNO];
206 }
207 
IncreaseSSAOperand(regno_t vRegNO,VRegVersion * vst)208 bool CGSSAInfo::IncreaseSSAOperand(regno_t vRegNO, VRegVersion *vst)
209 {
210     if (allSSAOperands.count(vRegNO)) {
211         return false;
212     }
213     allSSAOperands.emplace(vRegNO, vst);
214     return true;
215 }
216 
CreateNewVersion(RegOperand & virtualOpnd,Insn & defInsn,uint32 idx,bool isDefByPhi)217 VRegVersion *CGSSAInfo::CreateNewVersion(RegOperand &virtualOpnd, Insn &defInsn, uint32 idx, bool isDefByPhi)
218 {
219     regno_t vRegNO = virtualOpnd.GetRegisterNumber();
220     uint32 verionIdx = IncreaseVregCount(vRegNO);
221     RegOperand *ssaOpnd = CreateSSAOperand(virtualOpnd);
222     auto *newVst = memPool->New<VRegVersion>(ssaAlloc, *ssaOpnd, verionIdx, vRegNO);
223     auto *defInfo = CreateDUInsnInfo(&defInsn, idx);
224     newVst->SetDefInsn(defInfo, isDefByPhi ? kDefByPhi : kDefByInsn);
225     if (!IncreaseSSAOperand(ssaOpnd->GetRegisterNumber(), newVst)) {
226         CHECK_FATAL(false, "insert ssa operand failed");
227     }
228     auto it = vRegStk.find(vRegNO);
229     if (it == vRegStk.end()) {
230         MapleStack<VRegVersion *> vRegVersionStack(ssaAlloc.Adapter());
231         auto ret = vRegStk.emplace(std::pair<regno_t, MapleStack<VRegVersion *>>(vRegNO, vRegVersionStack));
232         CHECK_FATAL(ret.second, "insert failed");
233         it = ret.first;
234     }
235     it->second.push(newVst);
236     return newVst;
237 }
238 
GetVersion(const RegOperand & virtualOpnd)239 VRegVersion *CGSSAInfo::GetVersion(const RegOperand &virtualOpnd)
240 {
241     regno_t vRegNO = virtualOpnd.GetRegisterNumber();
242     auto vRegIt = vRegStk.find(vRegNO);
243     return vRegIt != vRegStk.end() ? vRegIt->second.top() : nullptr;
244 }
245 
FindSSAVersion(regno_t ssaRegNO)246 VRegVersion *CGSSAInfo::FindSSAVersion(regno_t ssaRegNO)
247 {
248     auto it = allSSAOperands.find(ssaRegNO);
249     return it != allSSAOperands.end() ? it->second : nullptr;
250 }
251 
CreatePhiOperand()252 PhiOperand &CGSSAInfo::CreatePhiOperand()
253 {
254     return cgFunc->GetCG()->CreatePhiOperand(*memPool, ssaAlloc);
255 }
256 
SetReversePostOrder()257 void CGSSAInfo::SetReversePostOrder()
258 {
259     MapleVector<BB *> &reverse = domInfo->GetReversePostOrder();
260     for (auto *bb : reverse) {
261         if (bb != nullptr) {
262             reversePostOrder.emplace_back(bb->GetId());
263         }
264     }
265 }
266 
GetDefInsn(const RegOperand & useReg)267 Insn *CGSSAInfo::GetDefInsn(const RegOperand &useReg)
268 {
269     if (!useReg.IsSSAForm()) {
270         return nullptr;
271     }
272     regno_t useRegNO = useReg.GetRegisterNumber();
273     VRegVersion *useVersion = FindSSAVersion(useRegNO);
274     CHECK_FATAL(useVersion != nullptr, "useVRegVersion must not be null based on ssa");
275     CHECK_FATAL(!useVersion->IsDeleted(), "deleted version");
276     DUInsnInfo *defInfo = useVersion->GetDefInsnInfo();
277     return defInfo == nullptr ? nullptr : defInfo->GetInsn();
278 }
279 
DumpFuncCGIRinSSAForm() const280 void CGSSAInfo::DumpFuncCGIRinSSAForm() const
281 {
282     LogInfo::MapleLogger() << "\n******  SSA CGIR for " << cgFunc->GetName() << " *******\n";
283     FOR_ALL_BB_CONST(bb, cgFunc)
284     {
285         LogInfo::MapleLogger() << "=== BB "
286                                << " <" << bb->GetKindName();
287         if (bb->GetLabIdx() != MIRLabelTable::GetDummyLabel()) {
288             LogInfo::MapleLogger() << "[labeled with " << bb->GetLabIdx();
289             LogInfo::MapleLogger() << " ==> @" << cgFunc->GetFunction().GetLabelName(bb->GetLabIdx()) << "]";
290         }
291 
292         LogInfo::MapleLogger() << "> <" << bb->GetId() << "> ";
293         if (bb->IsCleanup()) {
294             LogInfo::MapleLogger() << "[is_cleanup] ";
295         }
296         if (bb->IsUnreachable()) {
297             LogInfo::MapleLogger() << "[unreachable] ";
298         }
299         if (bb->GetFirstStmt() == cgFunc->GetCleanupLabel()) {
300             LogInfo::MapleLogger() << "cleanup ";
301         }
302         if (!bb->GetSuccs().empty()) {
303             LogInfo::MapleLogger() << "succs: ";
304             for (auto *succBB : bb->GetSuccs()) {
305                 LogInfo::MapleLogger() << succBB->GetId() << " ";
306             }
307         }
308         LogInfo::MapleLogger() << "===\n";
309         LogInfo::MapleLogger() << "frequency:" << bb->GetFrequency() << "\n";
310 
311         FOR_BB_INSNS_CONST(insn, bb)
312         {
313             if (insn->IsCfiInsn() && insn->IsDbgInsn()) {
314                 insn->Dump();
315             } else {
316                 DumpInsnInSSAForm(*insn);
317             }
318         }
319     }
320 }
321 
AddUseInsn(CGSSAInfo & ssaInfo,Insn & useInsn,uint32 idx)322 void VRegVersion::AddUseInsn(CGSSAInfo &ssaInfo, Insn &useInsn, uint32 idx)
323 {
324     DEBUG_ASSERT(useInsn.GetId() > 0, "insn should be marked during ssa");
325     auto useInsnIt = useInsnInfos.find(useInsn.GetId());
326     if (useInsnIt != useInsnInfos.end()) {
327         useInsnIt->second->IncreaseDU(idx);
328     } else {
329         useInsnInfos.insert(std::make_pair(useInsn.GetId(), ssaInfo.CreateDUInsnInfo(&useInsn, idx)));
330     }
331 }
332 
RemoveUseInsn(const Insn & useInsn,uint32 idx)333 void VRegVersion::RemoveUseInsn(const Insn &useInsn, uint32 idx)
334 {
335     auto useInsnIt = useInsnInfos.find(useInsn.GetId());
336     DEBUG_ASSERT(useInsnIt != useInsnInfos.end(), "use Insn not found");
337     useInsnIt->second->DecreaseDU(idx);
338     if (useInsnIt->second->HasNoDU()) {
339         useInsnInfos.erase(useInsnIt);
340     }
341 }
342 
CheckDeadUse(const Insn & useInsn)343 void VRegVersion::CheckDeadUse(const Insn &useInsn)
344 {
345     auto useInsnIt = useInsnInfos.find(useInsn.GetId());
346     DEBUG_ASSERT(useInsnIt != useInsnInfos.end(), "use Insn not found");
347     if (useInsnIt->second->HasNoDU()) {
348         useInsnInfos.erase(useInsnIt);
349     }
350 }
351 
GetAnalysisDependence(maple::AnalysisDep & aDep) const352 void CgSSAConstruct::GetAnalysisDependence(maple::AnalysisDep &aDep) const
353 {
354     aDep.AddRequired<CgDomAnalysis>();
355     aDep.AddRequired<CgLiveAnalysis>();
356     aDep.PreservedAllExcept<CgLiveAnalysis>();
357 }
358 
PhaseRun(maplebe::CGFunc & f)359 bool CgSSAConstruct::PhaseRun(maplebe::CGFunc &f)
360 {
361     if (CG_DEBUG_FUNC(f)) {
362         DotGenerator::GenerateDot("beforessa", f, f.GetMirModule());
363     }
364     MemPool *ssaMemPool = GetPhaseMemPool();
365     MemPool *ssaTempMp = ApplyTempMemPool();
366     DomAnalysis *domInfo = nullptr;
367     domInfo = GET_ANALYSIS(CgDomAnalysis, f);
368     LiveAnalysis *liveInfo = nullptr;
369     liveInfo = GET_ANALYSIS(CgLiveAnalysis, f);
370     ssaInfo = f.GetCG()->CreateCGSSAInfo(*ssaMemPool, f, *domInfo, *ssaTempMp);
371     ssaInfo->ConstructSSA();
372 
373     if (CG_DEBUG_FUNC(f)) {
374         LogInfo::MapleLogger() << "******** CG IR After ssaconstruct in ssaForm: *********"
375                                << "\n";
376         ssaInfo->DumpFuncCGIRinSSAForm();
377     }
378     if (liveInfo != nullptr) {
379         liveInfo->ClearInOutDataInfo();
380     }
381     /* due to change of register number */
382     GetAnalysisInfoHook()->ForceEraseAnalysisPhase(f.GetUniqueID(), &CgLiveAnalysis::id);
383     return true;
384 }
385 MAPLE_ANALYSIS_PHASE_REGISTER(CgSSAConstruct, cgssaconstruct) /* both transform & analysis */
386 }  // namespace maplebe
387