• 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 "insn.h"
17 #include "isa.h"
18 #include "cg.h"
19 namespace maplebe {
IsMachineInstruction() const20 bool Insn::IsMachineInstruction() const
21 {
22     return md && md->IsPhysicalInsn() && Globals::GetInstance()->GetTarget()->IsTargetInsn(mOp);
23 }
24 /* phi is not physical insn */
IsPhi() const25 bool Insn::IsPhi() const
26 {
27     return md ? md->IsPhi() : false;
28 }
IsLoad() const29 bool Insn::IsLoad() const
30 {
31     DEBUG_ASSERT(md, " set insnDescription for insn ");
32     return md->IsLoad();
33 }
IsStore() const34 bool Insn::IsStore() const
35 {
36     DEBUG_ASSERT(md, " set insnDescription for insn ");
37     return md->IsStore();
38 }
IsMove() const39 bool Insn::IsMove() const
40 {
41     DEBUG_ASSERT(md, " set insnDescription for insn ");
42     return md->IsMove();
43 }
IsBranch() const44 bool Insn::IsBranch() const
45 {
46     DEBUG_ASSERT(md, " set insnDescription for insn ");
47     return md->IsBranch();
48 }
IsCondBranch() const49 bool Insn::IsCondBranch() const
50 {
51     DEBUG_ASSERT(md, " set insnDescription for insn ");
52     return md->IsCondBranch();
53 }
IsUnCondBranch() const54 bool Insn::IsUnCondBranch() const
55 {
56     DEBUG_ASSERT(md, " set insnDescription for insn ");
57     return md->IsUnCondBranch();
58 }
IsBasicOp() const59 bool Insn::IsBasicOp() const
60 {
61     DEBUG_ASSERT(md, " set insnDescription for insn ");
62     return md->IsBasicOp();
63 }
IsConversion() const64 bool Insn::IsConversion() const
65 {
66     DEBUG_ASSERT(md, " set insnDescription for insn ");
67     return md->IsConversion();
68 }
IsUnaryOp() const69 bool Insn::IsUnaryOp() const
70 {
71     DEBUG_ASSERT(md, " set insnDescription for insn ");
72     return md->IsUnaryOp();
73 }
IsShift() const74 bool Insn::IsShift() const
75 {
76     DEBUG_ASSERT(md, " set insnDescription for insn ");
77     return md->IsShift();
78 }
IsCall() const79 bool Insn::IsCall() const
80 {
81     DEBUG_ASSERT(md, " set insnDescription for insn ");
82     return md->IsCall();
83 }
IsSpecialCall() const84 bool Insn::IsSpecialCall() const
85 {
86     return md ? md->IsSpecialCall() : false;
87 }
IsTailCall() const88 bool Insn::IsTailCall() const
89 {
90     DEBUG_ASSERT(md, " set insnDescription for insn ");
91     return md->IsTailCall();
92 }
IsAsmInsn() const93 bool Insn::IsAsmInsn() const
94 {
95     DEBUG_ASSERT(md, " set insnDescription for insn ");
96     return md->IsInlineAsm();
97 }
IsDMBInsn() const98 bool Insn::IsDMBInsn() const
99 {
100     DEBUG_ASSERT(md, " set insnDescription for insn ");
101     return md->IsDMB();
102 }
IsAtomic() const103 bool Insn::IsAtomic() const
104 {
105     DEBUG_ASSERT(md, " set insnDescription for insn ");
106     return md->IsAtomic();
107 }
IsVolatile() const108 bool Insn::IsVolatile() const
109 {
110     DEBUG_ASSERT(md, " set insnDescription for insn ");
111     return md->IsVolatile();
112 }
IsMemAccessBar() const113 bool Insn::IsMemAccessBar() const
114 {
115     DEBUG_ASSERT(md, " set insnDescription for insn ");
116     return md->IsMemAccessBar();
117 }
IsMemAccess() const118 bool Insn::IsMemAccess() const
119 {
120     DEBUG_ASSERT(md, " set insnDescription for insn ");
121     return md->IsMemAccess();
122 }
CanThrow() const123 bool Insn::CanThrow() const
124 {
125     DEBUG_ASSERT(md, " set insnDescription for insn ");
126     return md->CanThrow();
127 }
IsVectorOp() const128 bool Insn::IsVectorOp() const
129 {
130     DEBUG_ASSERT(md, " set insnDescription for insn ");
131     return md->IsVectorOp();
132 }
HasLoop() const133 bool Insn::HasLoop() const
134 {
135     DEBUG_ASSERT(md, " set insnDescription for insn ");
136     return md->HasLoop();
137 }
GetLatencyType() const138 uint32 Insn::GetLatencyType() const
139 {
140     DEBUG_ASSERT(md, " set insnDescription for insn ");
141     return md->GetLatencyType();
142 }
GetAtomicNum() const143 uint32 Insn::GetAtomicNum() const
144 {
145     DEBUG_ASSERT(md, " set insnDescription for insn ");
146     return md->GetAtomicNum();
147 }
IsSpecialIntrinsic() const148 bool Insn::IsSpecialIntrinsic() const
149 {
150     DEBUG_ASSERT(md, " set insnDescription for insn ");
151     return md->IsSpecialIntrinsic();
152 }
IsLoadPair() const153 bool Insn::IsLoadPair() const
154 {
155     DEBUG_ASSERT(md, " set insnDescription for insn ");
156     return md->IsLoadPair();
157 }
IsStorePair() const158 bool Insn::IsStorePair() const
159 {
160     DEBUG_ASSERT(md, " set insnDescription for insn ");
161     return md->IsStorePair();
162 }
IsLoadStorePair() const163 bool Insn::IsLoadStorePair() const
164 {
165     DEBUG_ASSERT(md, " set insnDescription for insn ");
166     return md->IsLoadStorePair();
167 }
IsLoadLabel() const168 bool Insn::IsLoadLabel() const
169 {
170     return md->IsLoad() && GetOperand(kInsnSecondOpnd).GetKind() == Operand::kOpdBBAddress;
171 }
OpndIsDef(uint32 id) const172 bool Insn::OpndIsDef(uint32 id) const
173 {
174     DEBUG_ASSERT(md, " set insnDescription for insn ");
175     return md->GetOpndDes(id)->IsDef();
176 }
OpndIsUse(uint32 id) const177 bool Insn::OpndIsUse(uint32 id) const
178 {
179     DEBUG_ASSERT(md, " set insnDescription for insn ");
180     return md->GetOpndDes(id)->IsUse();
181 }
IsClinit() const182 bool Insn::IsClinit() const
183 {
184     return Globals::GetInstance()->GetTarget()->IsClinitInsn(mOp);
185 }
IsComment() const186 bool Insn::IsComment() const
187 {
188     return mOp == abstract::MOP_comment && !md->IsPhysicalInsn();
189 }
190 
IsImmaterialInsn() const191 bool Insn::IsImmaterialInsn() const
192 {
193     return IsComment();
194 }
195 
IsPseudo() const196 bool Insn::IsPseudo() const
197 {
198     return md && md->IsPhysicalInsn() && Globals::GetInstance()->GetTarget()->IsPseudoInsn(mOp);
199 }
200 
GetMemOpnd() const201 Operand *Insn::GetMemOpnd() const
202 {
203     for (uint32 i = 0; i < opnds.size(); ++i) {
204         Operand &opnd = GetOperand(i);
205         if (opnd.IsMemoryAccessOperand()) {
206             return &opnd;
207         }
208     }
209     return nullptr;
210 }
211 
GetMemOpndIdx() const212 uint32 Insn::GetMemOpndIdx() const
213 {
214     uint32 opndIdx = kInsnMaxOpnd;
215     for (uint32 i = 0; i < static_cast<uint32>(opnds.size()); ++i) {
216         Operand &opnd = GetOperand(i);
217         if (opnd.IsMemoryAccessOperand()) {
218             return i;
219         }
220     }
221     return opndIdx;
222 }
SetMemOpnd(MemOperand * memOpnd)223 void Insn::SetMemOpnd(MemOperand *memOpnd)
224 {
225     for (uint32 i = 0; i < static_cast<uint32>(opnds.size()); ++i) {
226         Operand &opnd = GetOperand(i);
227         if (opnd.IsMemoryAccessOperand()) {
228             SetOperand(i, *memOpnd);
229             return;
230         }
231     }
232 }
233 
IsRegDefined(regno_t regNO) const234 bool Insn::IsRegDefined(regno_t regNO) const
235 {
236     return GetDefRegs().count(regNO);
237 }
238 
GetDefRegs() const239 std::set<uint32> Insn::GetDefRegs() const
240 {
241     std::set<uint32> defRegNOs;
242     size_t opndNum = opnds.size();
243     for (uint32 i = 0; i < opndNum; ++i) {
244         Operand &opnd = GetOperand(i);
245         auto *regProp = md->opndMD[i];
246         bool isDef = regProp->IsDef();
247         if (!isDef && !opnd.IsMemoryAccessOperand()) {
248             continue;
249         }
250         if (opnd.IsList()) {
251             for (auto *op : static_cast<ListOperand &>(opnd).GetOperands()) {
252                 DEBUG_ASSERT(op != nullptr, "invalid operand in list operand");
253                 defRegNOs.emplace(op->GetRegisterNumber());
254             }
255         } else if (opnd.IsMemoryAccessOperand()) {
256             auto &memOpnd = static_cast<MemOperand &>(opnd);
257             RegOperand *base = memOpnd.GetBaseRegister();
258             if (base != nullptr) {
259                 if (memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi &&
260                     (memOpnd.IsPostIndexed() || memOpnd.IsPreIndexed())) {
261                     DEBUG_ASSERT(!defRegNOs.count(base->GetRegisterNumber()), "duplicate def in one insn");
262                     defRegNOs.emplace(base->GetRegisterNumber());
263                 }
264             }
265         } else if (opnd.IsConditionCode() || opnd.IsRegister()) {
266             defRegNOs.emplace(static_cast<RegOperand &>(opnd).GetRegisterNumber());
267         }
268     }
269     return defRegNOs;
270 }
271 
CheckMD() const272 bool Insn::CheckMD() const
273 {
274     if (!md) {
275         LogInfo::MapleLogger() << " need machine description for target insn\n";
276         return false;
277     }
278     /* check if the number of operand(s) matches */
279     uint32 insnOperandSize = GetOperandSize();
280     if (insnOperandSize != md->GetOpndMDLength()) {
281         LogInfo::MapleLogger() << " need machine description for target insn\n";
282         return false;
283     }
284     /* check if the type of each operand  matches */
285     for (uint32 i = 0; i < insnOperandSize; ++i) {
286         Operand &opnd = GetOperand(i);
287         auto *opndDesc = md->GetOpndDes(i);
288         if (opnd.IsImmediate()) {
289             return opndDesc->IsImm();
290         } else {
291             return (opnd.GetKind() == opndDesc->GetOperandType());
292         }
293     }
294     return true;
295 }
296 
Clone(MemPool & memPool) const297 Insn *Insn::Clone(MemPool &memPool) const
298 {
299     CHECK_FATAL(false, "NIY");
300     return nullptr;
301 }
GetCallTargetOperand() const302 Operand *Insn::GetCallTargetOperand() const
303 {
304     DEBUG_ASSERT(IsCall() || IsTailCall(), "should be call");
305     return &GetOperand(kInsnFirstOpnd);
306 }
307 
GetCallArgumentOperand()308 ListOperand *Insn::GetCallArgumentOperand()
309 {
310     DEBUG_ASSERT(IsCall(), "should be call");
311     DEBUG_ASSERT(GetOperand(1).IsList(), "should be list");
312     return &static_cast<ListOperand &>(GetOperand(kInsnSecondOpnd));
313 }
314 
CommuteOperands(uint32 dIndex,uint32 sIndex)315 void Insn::CommuteOperands(uint32 dIndex, uint32 sIndex)
316 {
317     Operand *tempCopy = opnds[sIndex];
318     opnds[sIndex] = opnds[dIndex];
319     opnds[dIndex] = tempCopy;
320 }
321 
GetBothDefUseOpnd() const322 uint32 Insn::GetBothDefUseOpnd() const
323 {
324     size_t opndNum = opnds.size();
325     uint32 opndIdx = kInsnMaxOpnd;
326     if (md->GetAtomicNum() > 1) {
327         return opndIdx;
328     }
329     for (uint32 i = 0; i < opndNum; ++i) {
330         auto *opndProp = md->GetOpndDes(i);
331         if (opndProp->IsRegUse() && opndProp->IsDef()) {
332             DEBUG_ASSERT(opndIdx == kInsnMaxOpnd, "Do not support yet");
333             opndIdx = i;
334         }
335         if (opnds[i]->IsMemoryAccessOperand()) {
336             auto *MemOpnd = static_cast<MemOperand *>(opnds[i]);
337             if (!MemOpnd->IsIntactIndexed()) {
338                 DEBUG_ASSERT(opndIdx == kInsnMaxOpnd, "Do not support yet");
339                 opndIdx = i;
340             }
341         }
342     }
343     return opndIdx;
344 }
345 
GetMemoryByteSize() const346 uint32 Insn::GetMemoryByteSize() const
347 {
348     DEBUG_ASSERT(IsMemAccess(), "must be memory access insn");
349     uint32 res = 0;
350     for (size_t i = 0; i < opnds.size(); ++i) {
351         if (md->GetOpndDes(i)->GetOperandType() == Operand::kOpdMem) {
352             res = md->GetOpndDes(i)->GetSize();
353         }
354     }
355     DEBUG_ASSERT(res, "cannot access empty memory");
356     if (IsLoadStorePair()) {
357         res = res << 1;
358     }
359     res = res >> k8BitShift;
360     return res;
361 }
362 
ScanReg(regno_t regNO) const363 bool Insn::ScanReg(regno_t regNO) const
364 {
365     uint32 opndNum = GetOperandSize();
366     for (uint32 i = 0; i < opndNum; ++i) {
367         Operand &opnd = GetOperand(i);
368         if (opnd.IsList()) {
369             auto &listOpnd = static_cast<ListOperand &>(opnd);
370             for (auto listElem : listOpnd.GetOperands()) {
371                 auto *regOpnd = static_cast<RegOperand *>(listElem);
372                 DEBUG_ASSERT(regOpnd != nullptr, "parameter operand must be RegOperand");
373                 if (regNO == regOpnd->GetRegisterNumber()) {
374                     return true;
375                 }
376             }
377         } else if (opnd.IsMemoryAccessOperand()) {
378             auto &memOpnd = static_cast<MemOperand &>(opnd);
379             RegOperand *base = memOpnd.GetBaseRegister();
380             RegOperand *index = memOpnd.GetIndexRegister();
381             if ((base != nullptr && base->GetRegisterNumber() == regNO) ||
382                 (index != nullptr && index->GetRegisterNumber() == regNO)) {
383                 return true;
384             }
385         } else if (opnd.IsRegister()) {
386             if (static_cast<RegOperand &>(opnd).GetRegisterNumber() == regNO) {
387                 return true;
388             }
389         }
390     }
391     return false;
392 }
393 
MayThrow() const394 bool Insn::MayThrow() const
395 {
396     if (md->IsMemAccess() && !IsLoadLabel()) {
397         auto *memOpnd = static_cast<MemOperand *>(GetMemOpnd());
398         DEBUG_ASSERT(memOpnd != nullptr, "CG invalid memory operand.");
399         if (memOpnd->IsStackMem()) {
400             return false;
401         }
402     }
403     return md->CanThrow();
404 }
405 
SetMOP(const InsnDesc & idesc)406 void Insn::SetMOP(const InsnDesc &idesc)
407 {
408     mOp = idesc.GetOpc();
409     md = &idesc;
410 }
411 
Dump() const412 void Insn::Dump() const
413 {
414     DEBUG_ASSERT(md != nullptr, "md should not be nullptr");
415     LogInfo::MapleLogger() << "< " << GetId() << " > ";
416     LogInfo::MapleLogger() << md->name << "(" << mOp << ")";
417 
418     for (uint32 i = 0; i < GetOperandSize(); ++i) {
419         Operand &opnd = GetOperand(i);
420         LogInfo::MapleLogger() << " (opnd" << i << ": ";
421         Globals::GetInstance()->GetTarget()->DumpTargetOperand(opnd, *md->GetOpndDes(i));
422         LogInfo::MapleLogger() << ")";
423     }
424 
425     if (IsVectorOp()) {
426         auto *vInsn = static_cast<const VectorInsn *>(this);
427         if (vInsn->GetNumOfRegSpec() != 0) {
428             LogInfo::MapleLogger() << " (vecSpec: " << vInsn->GetNumOfRegSpec() << ")";
429         }
430     }
431     if (stackMap != nullptr) {
432         const auto &deoptVreg2Opnd = stackMap->GetDeoptInfo().GetDeoptBundleInfo();
433         if (!deoptVreg2Opnd.empty()) {
434             LogInfo::MapleLogger() << "  (deopt: ";
435             bool isFirstElem = true;
436             for (const auto &elem : deoptVreg2Opnd) {
437                 if (!isFirstElem) {
438                     LogInfo::MapleLogger() << ", ";
439                 } else {
440                     isFirstElem = false;
441                 }
442                 LogInfo::MapleLogger() << elem.first << ":";
443                 elem.second->Dump();
444             }
445             LogInfo::MapleLogger() << ")";
446         }
447     }
448     LogInfo::MapleLogger() << "\n";
449 }
450 
GetAndRemoveRegSpecFromList()451 VectorRegSpec *VectorInsn::GetAndRemoveRegSpecFromList()
452 {
453     if (regSpecList.size() == 0) {
454         VectorRegSpec *vecSpec = CG::GetCurCGFuncNoConst()->GetMemoryPool()->New<VectorRegSpec>();
455         return vecSpec;
456     }
457     VectorRegSpec *ret = regSpecList.back();
458     regSpecList.pop_back();
459     return ret;
460 }
461 }  // namespace maplebe
462