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 "aarch64_ssa.h"
17 #include "aarch64_cg.h"
18
19 namespace maplebe {
RenameInsn(Insn & insn)20 void AArch64CGSSAInfo::RenameInsn(Insn &insn)
21 {
22 auto opndNum = static_cast<int32>(insn.GetOperandSize());
23 const InsnDesc *md = insn.GetDesc();
24 if (md->IsPhi()) {
25 return;
26 }
27 for (int i = opndNum - 1; i >= 0; --i) {
28 Operand &opnd = insn.GetOperand(static_cast<uint32>(i));
29 auto *opndProp = (md->opndMD[static_cast<uint32>(i)]);
30 A64SSAOperandRenameVisitor renameVisitor(*this, insn, *opndProp, i);
31 opnd.Accept(renameVisitor);
32 }
33 }
34
CreateMemOperand(MemOperand & memOpnd,bool isOnSSA)35 MemOperand *AArch64CGSSAInfo::CreateMemOperand(MemOperand &memOpnd, bool isOnSSA)
36 {
37 return isOnSSA ? memOpnd.Clone(*memPool) : &static_cast<AArch64CGFunc *>(cgFunc)->GetOrCreateMemOpnd(memOpnd);
38 }
39
GetRenamedOperand(RegOperand & vRegOpnd,bool isDef,Insn & curInsn,uint32 idx)40 RegOperand *AArch64CGSSAInfo::GetRenamedOperand(RegOperand &vRegOpnd, bool isDef, Insn &curInsn, uint32 idx)
41 {
42 if (vRegOpnd.IsVirtualRegister()) {
43 DEBUG_ASSERT(!vRegOpnd.IsSSAForm(), "Unexpect ssa operand");
44 if (isDef) {
45 VRegVersion *newVersion = CreateNewVersion(vRegOpnd, curInsn, idx);
46 CHECK_FATAL(newVersion != nullptr, "get ssa version failed");
47 return newVersion->GetSSAvRegOpnd();
48 } else {
49 VRegVersion *curVersion = GetVersion(vRegOpnd);
50 if (curVersion == nullptr) {
51 curVersion = RenamedOperandSpecialCase(vRegOpnd, curInsn, idx);
52 }
53 curVersion->AddUseInsn(*this, curInsn, idx);
54 return curVersion->GetSSAvRegOpnd();
55 }
56 }
57 DEBUG_ASSERT(false, "Get Renamed operand failed");
58 return nullptr;
59 }
60
RenamedOperandSpecialCase(RegOperand & vRegOpnd,Insn & curInsn,uint32 idx)61 VRegVersion *AArch64CGSSAInfo::RenamedOperandSpecialCase(RegOperand &vRegOpnd, Insn &curInsn, uint32 idx)
62 {
63 LogInfo::MapleLogger() << "WARNING: " << vRegOpnd.GetRegisterNumber()
64 << " has no def info in function : " << cgFunc->GetName() << " !\n";
65 /* occupy operand for no def vreg */
66 if (!IncreaseSSAOperand(vRegOpnd.GetRegisterNumber(), nullptr)) {
67 DEBUG_ASSERT(GetAllSSAOperands().find(vRegOpnd.GetRegisterNumber()) != GetAllSSAOperands().end(),
68 "should find");
69 AddNoDefVReg(vRegOpnd.GetRegisterNumber());
70 }
71 VRegVersion *version = CreateNewVersion(vRegOpnd, curInsn, idx);
72 version->SetDefInsn(nullptr, kDefByNo);
73 return version;
74 }
75
CreateSSAOperand(RegOperand & virtualOpnd)76 RegOperand *AArch64CGSSAInfo::CreateSSAOperand(RegOperand &virtualOpnd)
77 {
78 regno_t ssaRegNO = static_cast<regno_t>(GetAllSSAOperands().size()) + SSARegNObase;
79 while (GetAllSSAOperands().count(ssaRegNO)) {
80 ssaRegNO++;
81 SSARegNObase++;
82 }
83 RegOperand *newVreg = memPool->New<RegOperand>(ssaRegNO, virtualOpnd.GetSize(), virtualOpnd.GetRegisterType());
84 newVreg->SetValidBitsNum(virtualOpnd.GetValidBitsNum());
85 newVreg->SetOpndSSAForm();
86 return newVreg;
87 }
88
ReplaceInsn(Insn & oriInsn,Insn & newInsn)89 void AArch64CGSSAInfo::ReplaceInsn(Insn &oriInsn, Insn &newInsn)
90 {
91 A64OpndSSAUpdateVsitor ssaUpdator(*this);
92 auto UpdateInsnSSAInfo = [&ssaUpdator](Insn &curInsn, bool isDelete) {
93 const InsnDesc *md = curInsn.GetDesc();
94 for (uint32 i = 0; i < curInsn.GetOperandSize(); ++i) {
95 Operand &opnd = curInsn.GetOperand(i);
96 auto *opndProp = md->opndMD[i];
97 if (isDelete) {
98 ssaUpdator.MarkDecrease();
99 } else {
100 ssaUpdator.MarkIncrease();
101 }
102 ssaUpdator.SetInsnOpndInfo(curInsn, *opndProp, i);
103 opnd.Accept(ssaUpdator);
104 }
105 };
106 UpdateInsnSSAInfo(oriInsn, true);
107 newInsn.SetId(oriInsn.GetId());
108 UpdateInsnSSAInfo(newInsn, false);
109 CHECK_FATAL(!ssaUpdator.HasDeleteDef(), "delete def point in replace insn, please check");
110 }
111
112 /* do not break binding between input and output operands in asm */
CheckAsmDUbinding(Insn & insn,const VRegVersion * toBeReplaced,VRegVersion * newVersion)113 void AArch64CGSSAInfo::CheckAsmDUbinding(Insn &insn, const VRegVersion *toBeReplaced, VRegVersion *newVersion)
114 {
115 if (insn.GetMachineOpcode() == MOP_asm) {
116 for (auto &opndIt : static_cast<ListOperand &>(insn.GetOperand(kAsmOutputListOpnd)).GetOperands()) {
117 if (opndIt->IsSSAForm()) {
118 VRegVersion *defVersion = FindSSAVersion(opndIt->GetRegisterNumber());
119 if (defVersion && defVersion->GetOriginalRegNO() == toBeReplaced->GetOriginalRegNO()) {
120 insn.AddRegBinding(defVersion->GetOriginalRegNO(),
121 newVersion->GetSSAvRegOpnd()->GetRegisterNumber());
122 }
123 }
124 }
125 }
126 }
127
ReplaceAllUse(VRegVersion * toBeReplaced,VRegVersion * newVersion)128 void AArch64CGSSAInfo::ReplaceAllUse(VRegVersion *toBeReplaced, VRegVersion *newVersion)
129 {
130 MapleUnorderedMap<uint32, DUInsnInfo *> &useList = toBeReplaced->GetAllUseInsns();
131 for (auto it = useList.begin(); it != useList.end();) {
132 Insn *useInsn = it->second->GetInsn();
133 CheckAsmDUbinding(*useInsn, toBeReplaced, newVersion);
134 for (auto &opndIt : it->second->GetOperands()) {
135 Operand &opnd = useInsn->GetOperand(opndIt.first);
136 A64ReplaceRegOpndVisitor replaceRegOpndVisitor(
137 *cgFunc, *useInsn, opndIt.first, *toBeReplaced->GetSSAvRegOpnd(), *newVersion->GetSSAvRegOpnd());
138 opnd.Accept(replaceRegOpndVisitor);
139 newVersion->AddUseInsn(*this, *useInsn, opndIt.first);
140 it->second->ClearDU(opndIt.first);
141 }
142 it = useList.erase(it);
143 }
144 }
145
CreateNewInsnSSAInfo(Insn & newInsn)146 void AArch64CGSSAInfo::CreateNewInsnSSAInfo(Insn &newInsn)
147 {
148 uint32 opndNum = newInsn.GetOperandSize();
149 MarkInsnsInSSA(newInsn);
150 for (uint32 i = 0; i < opndNum; i++) {
151 Operand &opnd = newInsn.GetOperand(i);
152 auto *opndProp = newInsn.GetDesc()->opndMD[i];
153 if (opndProp->IsDef() && opndProp->IsUse()) {
154 CHECK_FATAL(false, "do not support both def and use");
155 }
156 if (opndProp->IsDef()) {
157 CHECK_FATAL(opnd.IsRegister(), "defOpnd must be reg");
158 auto &defRegOpnd = static_cast<RegOperand &>(opnd);
159 regno_t defRegNO = defRegOpnd.GetRegisterNumber();
160 uint32 defVIdx = IncreaseVregCount(defRegNO);
161 RegOperand *defSSAOpnd = CreateSSAOperand(defRegOpnd);
162 newInsn.SetOperand(i, *defSSAOpnd);
163 auto *defVersion = memPool->New<VRegVersion>(ssaAlloc, *defSSAOpnd, defVIdx, defRegNO);
164 auto *defInfo = CreateDUInsnInfo(&newInsn, i);
165 defVersion->SetDefInsn(defInfo, kDefByInsn);
166 if (!IncreaseSSAOperand(defSSAOpnd->GetRegisterNumber(), defVersion)) {
167 CHECK_FATAL(false, "insert ssa operand failed");
168 }
169 } else if (opndProp->IsUse()) {
170 A64OpndSSAUpdateVsitor ssaUpdator(*this);
171 ssaUpdator.MarkIncrease();
172 ssaUpdator.SetInsnOpndInfo(newInsn, *opndProp, i);
173 opnd.Accept(ssaUpdator);
174 }
175 }
176 }
177
DumpInsnInSSAForm(const Insn & insn) const178 void AArch64CGSSAInfo::DumpInsnInSSAForm(const Insn &insn) const
179 {
180 MOperator mOp = insn.GetMachineOpcode();
181 const InsnDesc *md = insn.GetDesc();
182 DEBUG_ASSERT(md != nullptr, "md should not be nullptr");
183
184 LogInfo::MapleLogger() << "< " << insn.GetId() << " > ";
185 LogInfo::MapleLogger() << md->name << "(" << mOp << ")";
186
187 for (uint32 i = 0; i < insn.GetOperandSize(); ++i) {
188 Operand &opnd = insn.GetOperand(i);
189 LogInfo::MapleLogger() << " (opnd" << i << ": ";
190 A64SSAOperandDumpVisitor a64OpVisitor(GetAllSSAOperands());
191 opnd.Accept(a64OpVisitor);
192 if (!a64OpVisitor.HasDumped()) {
193 opnd.Dump();
194 LogInfo::MapleLogger() << ")";
195 }
196 }
197 if (insn.IsVectorOp()) {
198 auto &vInsn = static_cast<const VectorInsn &>(insn);
199 if (vInsn.GetNumOfRegSpec() != 0) {
200 LogInfo::MapleLogger() << " (vecSpec: " << vInsn.GetNumOfRegSpec() << ")";
201 }
202 }
203 LogInfo::MapleLogger() << "\n";
204 }
205
Visit(RegOperand * v)206 void A64SSAOperandRenameVisitor::Visit(RegOperand *v)
207 {
208 if (v->IsVirtualRegister()) {
209 if (opndDes->IsRegDef() && opndDes->IsRegUse()) { /* both def use */
210 insn->SetOperand(idx, *ssaInfo->GetRenamedOperand(*v, false, *insn, idx));
211 (void)ssaInfo->GetRenamedOperand(*v, true, *insn, idx);
212 } else {
213 insn->SetOperand(idx, *ssaInfo->GetRenamedOperand(*v, opndDes->IsRegDef(), *insn, idx));
214 }
215 }
216 }
217
Visit(MemOperand * a64MemOpnd)218 void A64SSAOperandRenameVisitor::Visit(MemOperand *a64MemOpnd)
219 {
220 RegOperand *base = a64MemOpnd->GetBaseRegister();
221 RegOperand *index = a64MemOpnd->GetIndexRegister();
222 bool needCopy = (base != nullptr && base->IsVirtualRegister()) || (index != nullptr && index->IsVirtualRegister());
223 if (needCopy) {
224 MemOperand *cpyMem = ssaInfo->CreateMemOperand(*a64MemOpnd, true);
225 if (base != nullptr && base->IsVirtualRegister()) {
226 bool isDef = !a64MemOpnd->IsIntactIndexed();
227 cpyMem->SetBaseRegister(*ssaInfo->GetRenamedOperand(*base, isDef, *insn, idx));
228 }
229 if (index != nullptr && index->IsVirtualRegister()) {
230 cpyMem->SetIndexRegister(*ssaInfo->GetRenamedOperand(*index, false, *insn, idx));
231 }
232 insn->SetMemOpnd(ssaInfo->CreateMemOperand(*cpyMem, false));
233 }
234 }
235
Visit(ListOperand * v)236 void A64SSAOperandRenameVisitor::Visit(ListOperand *v)
237 {
238 bool isAsm = insn->GetMachineOpcode() == MOP_asm;
239 /* record the orignal list order */
240 std::list<RegOperand *> tempList;
241 auto &opndList = v->GetOperands();
242 while (!opndList.empty()) {
243 auto *op = opndList.front();
244 opndList.pop_front();
245
246 if (op->IsSSAForm() || !op->IsVirtualRegister()) {
247 tempList.push_back(op);
248 continue;
249 }
250
251 bool isDef = isAsm && (idx == kAsmClobberListOpnd || idx == kAsmOutputListOpnd);
252 RegOperand *renameOpnd = ssaInfo->GetRenamedOperand(*op, isDef, *insn, idx);
253 tempList.push_back(renameOpnd);
254 }
255 DEBUG_ASSERT(v->GetOperands().empty(), "need to clean list");
256 v->GetOperands().assign(tempList.begin(), tempList.end());
257 }
258
Visit(RegOperand * regOpnd)259 void A64OpndSSAUpdateVsitor::Visit(RegOperand *regOpnd)
260 {
261 if (regOpnd->IsSSAForm()) {
262 if (opndDes->IsRegDef() && opndDes->IsRegUse()) {
263 UpdateRegUse(regOpnd->GetRegisterNumber());
264 UpdateRegDef(regOpnd->GetRegisterNumber());
265 } else {
266 if (opndDes->IsRegDef()) {
267 UpdateRegDef(regOpnd->GetRegisterNumber());
268 } else if (opndDes->IsRegUse()) {
269 UpdateRegUse(regOpnd->GetRegisterNumber());
270 } else if (IsPhi()) {
271 UpdateRegUse(regOpnd->GetRegisterNumber());
272 } else {
273 DEBUG_ASSERT(false, "invalid opnd");
274 }
275 }
276 }
277 }
278
Visit(maplebe::MemOperand * a64MemOpnd)279 void A64OpndSSAUpdateVsitor::Visit(maplebe::MemOperand *a64MemOpnd)
280 {
281 RegOperand *base = a64MemOpnd->GetBaseRegister();
282 RegOperand *index = a64MemOpnd->GetIndexRegister();
283 if (base != nullptr && base->IsSSAForm()) {
284 if (a64MemOpnd->IsIntactIndexed()) {
285 UpdateRegUse(base->GetRegisterNumber());
286 } else {
287 UpdateRegDef(base->GetRegisterNumber());
288 }
289 }
290 if (index != nullptr && index->IsSSAForm()) {
291 UpdateRegUse(index->GetRegisterNumber());
292 }
293 }
294
Visit(PhiOperand * phiOpnd)295 void A64OpndSSAUpdateVsitor::Visit(PhiOperand *phiOpnd)
296 {
297 SetPhi(true);
298 for (auto phiListIt = phiOpnd->GetOperands().begin(); phiListIt != phiOpnd->GetOperands().end(); ++phiListIt) {
299 Visit(phiListIt->second);
300 }
301 SetPhi(false);
302 }
303
Visit(ListOperand * v)304 void A64OpndSSAUpdateVsitor::Visit(ListOperand *v)
305 {
306 /* do not handle asm here, so there is no list def */
307 if (insn->GetMachineOpcode() == MOP_asm) {
308 DEBUG_ASSERT(false, "do not support asm yet");
309 return;
310 }
311 for (auto *op : v->GetOperands()) {
312 if (op->IsSSAForm()) {
313 UpdateRegUse(op->GetRegisterNumber());
314 }
315 }
316 }
317
UpdateRegUse(uint32 ssaIdx)318 void A64OpndSSAUpdateVsitor::UpdateRegUse(uint32 ssaIdx)
319 {
320 VRegVersion *curVersion = ssaInfo->FindSSAVersion(ssaIdx);
321 DEBUG_ASSERT(curVersion != nullptr, "curVersion should not be nullptr");
322 if (isDecrease) {
323 curVersion->RemoveUseInsn(*insn, idx);
324 } else {
325 curVersion->AddUseInsn(*ssaInfo, *insn, idx);
326 }
327 }
328
UpdateRegDef(uint32 ssaIdx)329 void A64OpndSSAUpdateVsitor::UpdateRegDef(uint32 ssaIdx)
330 {
331 VRegVersion *curVersion = ssaInfo->FindSSAVersion(ssaIdx);
332 if (isDecrease) {
333 deletedDef.emplace(ssaIdx);
334 DEBUG_ASSERT(curVersion != nullptr, "nullptr check");
335 curVersion->MarkDeleted();
336 } else {
337 if (deletedDef.count(ssaIdx)) {
338 deletedDef.erase(ssaIdx);
339 curVersion->MarkRecovery();
340 } else {
341 CHECK_FATAL(false, "do no support new define in ssaUpdating");
342 }
343 DEBUG_ASSERT(!insn->IsPhi(), "do no support yet");
344 curVersion->SetDefInsn(ssaInfo->CreateDUInsnInfo(insn, idx), kDefByInsn);
345 }
346 }
347
Visit(RegOperand * a64RegOpnd)348 void A64SSAOperandDumpVisitor::Visit(RegOperand *a64RegOpnd)
349 {
350 DEBUG_ASSERT(!a64RegOpnd->IsConditionCode(), "both condi and reg");
351 if (a64RegOpnd->IsSSAForm()) {
352 std::array<const std::string, kRegTyLast> prims = {"U", "R", "V", "C", "X", "Vra"};
353 std::array<const std::string, kRegTyLast> classes = {"[U]", "[I]", "[F]", "[CC]", "[X87]", "[Vra]"};
354 CHECK_FATAL(a64RegOpnd->IsVirtualRegister() && a64RegOpnd->IsSSAForm(), "only dump ssa opnd here");
355 RegType regType = a64RegOpnd->GetRegisterType();
356 DEBUG_ASSERT(regType < kRegTyLast, "unexpected regType");
357 auto ssaVit = allSSAOperands.find(a64RegOpnd->GetRegisterNumber());
358 CHECK_FATAL(ssaVit != allSSAOperands.end(), "find ssa version failed");
359 LogInfo::MapleLogger() << "ssa_reg:" << prims[regType] << ssaVit->second->GetOriginalRegNO() << "_"
360 << ssaVit->second->GetVersionIdx() << " class: " << classes[regType] << " validBitNum: ["
361 << static_cast<uint32>(a64RegOpnd->GetValidBitsNum()) << "]";
362 LogInfo::MapleLogger() << ")";
363 SetHasDumped();
364 }
365 }
366
Visit(ListOperand * v)367 void A64SSAOperandDumpVisitor::Visit(ListOperand *v)
368 {
369 for (auto regOpnd : v->GetOperands()) {
370 if (regOpnd->IsSSAForm()) {
371 Visit(regOpnd);
372 continue;
373 }
374 }
375 }
376
Visit(MemOperand * a64MemOpnd)377 void A64SSAOperandDumpVisitor::Visit(MemOperand *a64MemOpnd)
378 {
379 if (a64MemOpnd->GetBaseRegister() != nullptr && a64MemOpnd->GetBaseRegister()->IsSSAForm()) {
380 LogInfo::MapleLogger() << "Mem: ";
381 Visit(a64MemOpnd->GetBaseRegister());
382 if (a64MemOpnd->GetAddrMode() == MemOperand::kAddrModeBOi) {
383 LogInfo::MapleLogger() << "offset:";
384 a64MemOpnd->GetOffsetOperand()->Dump();
385 }
386 }
387 if (a64MemOpnd->GetIndexRegister() != nullptr && a64MemOpnd->GetIndexRegister()->IsSSAForm()) {
388 DEBUG_ASSERT(a64MemOpnd->GetAddrMode() == MemOperand::kAddrModeBOrX, "mem mode false");
389 LogInfo::MapleLogger() << "offset:";
390 Visit(a64MemOpnd->GetIndexRegister());
391 }
392 }
393
Visit(PhiOperand * phi)394 void A64SSAOperandDumpVisitor::Visit(PhiOperand *phi)
395 {
396 for (auto phiListIt = phi->GetOperands().begin(); phiListIt != phi->GetOperands().end();) {
397 Visit(phiListIt->second);
398 LogInfo::MapleLogger() << " fBB<" << phiListIt->first << ">";
399 LogInfo::MapleLogger() << (++phiListIt == phi->GetOperands().end() ? ")" : ", ");
400 }
401 }
402 } // namespace maplebe
403