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