• 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 "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