• 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 "cg.h"
18 namespace maplebe {
IsMachineInstruction() const19 bool Insn::IsMachineInstruction() const
20 {
21     return md && md->IsPhysicalInsn() && Globals::GetInstance()->GetTarget()->IsTargetInsn(mOp);
22 }
23 
IsLoad() const24 bool Insn::IsLoad() const
25 {
26     DEBUG_ASSERT(md, " set insnDescription for insn ");
27     return md->IsLoad();
28 }
IsStore() const29 bool Insn::IsStore() const
30 {
31     DEBUG_ASSERT(md, " set insnDescription for insn ");
32     return md->IsStore();
33 }
IsMove() const34 bool Insn::IsMove() const
35 {
36     DEBUG_ASSERT(md, " set insnDescription for insn ");
37     return md->IsMove();
38 }
IsBranch() const39 bool Insn::IsBranch() const
40 {
41     DEBUG_ASSERT(md, " set insnDescription for insn ");
42     return md->IsBranch();
43 }
IsCondBranch() const44 bool Insn::IsCondBranch() const
45 {
46     DEBUG_ASSERT(md, " set insnDescription for insn ");
47     return md->IsCondBranch();
48 }
IsUnCondBranch() const49 bool Insn::IsUnCondBranch() const
50 {
51     DEBUG_ASSERT(md, " set insnDescription for insn ");
52     return md->IsUnCondBranch();
53 }
IsBasicOp() const54 bool Insn::IsBasicOp() const
55 {
56     DEBUG_ASSERT(md, " set insnDescription for insn ");
57     return md->IsBasicOp();
58 }
IsConversion() const59 bool Insn::IsConversion() const
60 {
61     DEBUG_ASSERT(md, " set insnDescription for insn ");
62     return md->IsConversion();
63 }
IsUnaryOp() const64 bool Insn::IsUnaryOp() const
65 {
66     DEBUG_ASSERT(md, " set insnDescription for insn ");
67     return md->IsUnaryOp();
68 }
IsShift() const69 bool Insn::IsShift() const
70 {
71     DEBUG_ASSERT(md, " set insnDescription for insn ");
72     return md->IsShift();
73 }
IsCall() const74 bool Insn::IsCall() const
75 {
76     DEBUG_ASSERT(md, " set insnDescription for insn ");
77     return md->IsCall();
78 }
IsSpecialCall() const79 bool Insn::IsSpecialCall() const
80 {
81     return md ? md->IsSpecialCall() : false;
82 }
IsTailCall() const83 bool Insn::IsTailCall() const
84 {
85     DEBUG_ASSERT(md, " set insnDescription for insn ");
86     return md->IsTailCall();
87 }
IsAsmInsn() const88 bool Insn::IsAsmInsn() const
89 {
90     DEBUG_ASSERT(md, " set insnDescription for insn ");
91     return md->IsInlineAsm();
92 }
IsAtomic() const93 bool Insn::IsAtomic() const
94 {
95     DEBUG_ASSERT(md, " set insnDescription for insn ");
96     return md->IsAtomic();
97 }
IsMemAccess() const98 bool Insn::IsMemAccess() const
99 {
100     DEBUG_ASSERT(md, " set insnDescription for insn ");
101     return md->IsMemAccess();
102 }
GetAtomicNum() const103 uint32 Insn::GetAtomicNum() const
104 {
105     DEBUG_ASSERT(md, " set insnDescription for insn ");
106     return md->GetAtomicNum();
107 }
IsSpecialIntrinsic() const108 bool Insn::IsSpecialIntrinsic() const
109 {
110     DEBUG_ASSERT(md, " set insnDescription for insn ");
111     return md->IsSpecialIntrinsic();
112 }
IsLoadStorePair() const113 bool Insn::IsLoadStorePair() const
114 {
115     DEBUG_ASSERT(md, " set insnDescription for insn ");
116     return md->IsLoadStorePair();
117 }
IsLoadLabel() const118 bool Insn::IsLoadLabel() const
119 {
120     return md->IsLoad() && GetOperand(kInsnSecondOpnd).GetKind() == Operand::kOpdBBAddress;
121 }
OpndIsDef(uint32 id) const122 bool Insn::OpndIsDef(uint32 id) const
123 {
124     DEBUG_ASSERT(md, " set insnDescription for insn ");
125     return md->GetOpndDes(id)->IsDef();
126 }
IsComment() const127 bool Insn::IsComment() const
128 {
129     return mOp == abstract::MOP_comment && !md->IsPhysicalInsn();
130 }
131 
IsImmaterialInsn() const132 bool Insn::IsImmaterialInsn() const
133 {
134     return IsComment();
135 }
136 
IsPseudo() const137 bool Insn::IsPseudo() const
138 {
139     return md && md->IsPhysicalInsn() && Globals::GetInstance()->GetTarget()->IsPseudoInsn(mOp);
140 }
141 
GetMemOpnd() const142 Operand *Insn::GetMemOpnd() const
143 {
144     for (uint32 i = 0; i < opnds.size(); ++i) {
145         Operand &opnd = GetOperand(i);
146         if (opnd.IsMemoryAccessOperand()) {
147             return &opnd;
148         }
149     }
150     return nullptr;
151 }
152 
IsRegDefined(regno_t regNO) const153 bool Insn::IsRegDefined(regno_t regNO) const
154 {
155     return GetDefRegs().count(regNO);
156 }
157 
GetDefRegs() const158 std::set<uint32> Insn::GetDefRegs() const
159 {
160     std::set<uint32> defRegNOs;
161     size_t opndNum = opnds.size();
162     for (uint32 i = 0; i < opndNum; ++i) {
163         Operand &opnd = GetOperand(i);
164         auto *regProp = md->opndMD[i];
165         bool isDef = regProp->IsDef();
166         if (!isDef && !opnd.IsMemoryAccessOperand()) {
167             continue;
168         }
169         if (opnd.IsList()) {
170             for (auto *op : static_cast<ListOperand &>(opnd).GetOperands()) {
171                 DEBUG_ASSERT(op != nullptr, "invalid operand in list operand");
172                 defRegNOs.emplace(op->GetRegisterNumber());
173             }
174         } else if (opnd.IsMemoryAccessOperand()) {
175             auto &memOpnd = static_cast<MemOperand &>(opnd);
176             RegOperand *base = memOpnd.GetBaseRegister();
177             if (base != nullptr) {
178                 if (memOpnd.GetAddrMode() == MemOperand::kAddrModeBOi &&
179                     (memOpnd.IsPostIndexed() || memOpnd.IsPreIndexed())) {
180                     DEBUG_ASSERT(!defRegNOs.count(base->GetRegisterNumber()), "duplicate def in one insn");
181                     defRegNOs.emplace(base->GetRegisterNumber());
182                 }
183             }
184         } else if (opnd.IsConditionCode() || opnd.IsRegister()) {
185             defRegNOs.emplace(static_cast<RegOperand &>(opnd).GetRegisterNumber());
186         }
187     }
188     return defRegNOs;
189 }
190 
CheckMD() const191 bool Insn::CheckMD() const
192 {
193 #ifdef ARK_LITECG_DEBUG
194     if (!md) {
195         LogInfo::MapleLogger() << " need machine description for target insn\n";
196         return false;
197     }
198     /* check if the number of operand(s) matches */
199     uint32 insnOperandSize = GetOperandSize();
200     if (insnOperandSize != md->GetOpndMDLength()) {
201         LogInfo::MapleLogger() << " need machine description for target insn\n";
202         return false;
203     }
204     /* check if the type of each operand  matches */
205     for (uint32 i = 0; i < insnOperandSize; ++i) {
206         Operand &opnd = GetOperand(i);
207         auto *opndDesc = md->GetOpndDes(i);
208         if (opnd.IsImmediate()) {
209             return opndDesc->IsImm();
210         } else {
211             return (opnd.GetKind() == opndDesc->GetOperandType());
212         }
213     }
214 #endif
215     return true;
216 }
217 
GetCallTargetOperand() const218 Operand *Insn::GetCallTargetOperand() const
219 {
220     DEBUG_ASSERT(IsCall() || IsTailCall(), "should be call");
221     return &GetOperand(kInsnFirstOpnd);
222 }
223 
CommuteOperands(uint32 dIndex,uint32 sIndex)224 void Insn::CommuteOperands(uint32 dIndex, uint32 sIndex)
225 {
226     Operand *tempCopy = opnds[sIndex];
227     opnds[sIndex] = opnds[dIndex];
228     opnds[dIndex] = tempCopy;
229 }
230 
GetMemoryByteSize() const231 uint32 Insn::GetMemoryByteSize() const
232 {
233     DEBUG_ASSERT(IsMemAccess(), "must be memory access insn");
234     uint32 res = 0;
235     for (size_t i = 0; i < opnds.size(); ++i) {
236         if (md->GetOpndDes(i)->GetOperandType() == Operand::kOpdMem) {
237             res = md->GetOpndDes(i)->GetSize();
238         }
239     }
240     DEBUG_ASSERT(res, "cannot access empty memory");
241     if (IsLoadStorePair()) {
242         res = res << 1;
243     }
244     res = res >> k8BitShift;
245     return res;
246 }
247 
ScanReg(regno_t regNO) const248 bool Insn::ScanReg(regno_t regNO) const
249 {
250     uint32 opndNum = GetOperandSize();
251     for (uint32 i = 0; i < opndNum; ++i) {
252         Operand &opnd = GetOperand(i);
253         if (opnd.IsList()) {
254             auto &listOpnd = static_cast<ListOperand &>(opnd);
255             for (auto listElem : listOpnd.GetOperands()) {
256                 auto *regOpnd = static_cast<RegOperand *>(listElem);
257                 DEBUG_ASSERT(regOpnd != nullptr, "parameter operand must be RegOperand");
258                 if (regNO == regOpnd->GetRegisterNumber()) {
259                     return true;
260                 }
261             }
262         } else if (opnd.IsMemoryAccessOperand()) {
263             auto &memOpnd = static_cast<MemOperand &>(opnd);
264             RegOperand *base = memOpnd.GetBaseRegister();
265             RegOperand *index = memOpnd.GetIndexRegister();
266             if ((base != nullptr && base->GetRegisterNumber() == regNO) ||
267                 (index != nullptr && index->GetRegisterNumber() == regNO)) {
268                 return true;
269             }
270         } else if (opnd.IsRegister()) {
271             if (static_cast<RegOperand &>(opnd).GetRegisterNumber() == regNO) {
272                 return true;
273             }
274         }
275     }
276     return false;
277 }
278 
SetMOP(const InsnDesc & idesc)279 void Insn::SetMOP(const InsnDesc &idesc)
280 {
281     mOp = idesc.GetOpc();
282     md = &idesc;
283 }
284 
Dump() const285 void Insn::Dump() const
286 {
287 #ifdef ARK_LITECG_DEBUG
288     DEBUG_ASSERT(md != nullptr, "md should not be nullptr");
289     LogInfo::MapleLogger() << "< " << GetId() << " > ";
290     LogInfo::MapleLogger() << md->name << "(" << mOp << ")";
291 
292     for (uint32 i = 0; i < GetOperandSize(); ++i) {
293         Operand &opnd = GetOperand(i);
294         LogInfo::MapleLogger() << " (opnd" << i << ": ";
295         Globals::GetInstance()->GetTarget()->DumpTargetOperand(opnd, *md->GetOpndDes(i));
296         LogInfo::MapleLogger() << ")";
297     }
298 
299     if (stackMap != nullptr) {
300         const auto &deoptVreg2Opnd = stackMap->GetDeoptInfo().GetDeoptBundleInfo();
301         if (!deoptVreg2Opnd.empty()) {
302             LogInfo::MapleLogger() << "  (deopt: ";
303             bool isFirstElem = true;
304             for (const auto &elem : deoptVreg2Opnd) {
305                 if (!isFirstElem) {
306                     LogInfo::MapleLogger() << ", ";
307                 } else {
308                     isFirstElem = false;
309                 }
310                 LogInfo::MapleLogger() << elem.first << ":";
311                 elem.second->Dump();
312             }
313             LogInfo::MapleLogger() << ")";
314         }
315     }
316     LogInfo::MapleLogger() << "\n";
317 #endif
318 }
319 }  // namespace maplebe
320