• 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 #ifndef MAPLEBE_INCLUDE_CG_INSN_H
17 #define MAPLEBE_INCLUDE_CG_INSN_H
18 /* C++ headers */
19 #include <cstddef> /* for nullptr */
20 #include <string>
21 #include <vector>
22 #include <list>
23 /* Maple CG headers */
24 #include "operand.h"
25 #include "isa.h"
26 #include "common_utils.h"
27 /* Maple IR header */
28 #include "types_def.h" /* for uint32 */
29 /* Maple Util headers */
30 #include "mpl_logging.h"
31 
32 #include "stackmap.h"
33 #include "sparse_datainfo.h"
34 
35 /* Maple Util headers */
36 #include "mem_reference_table.h" /* for alias */
37 namespace maplebe {
38 /* forward declaration */
39 class BB;
40 class CG;
41 class Emitter;
42 class DepNode;
43 struct InsnDesc;
44 class InsnBuilder;
45 class OperandBuilder;
46 
47 class Insn {
48 public:
49     /* MCC_DecRefResetPair clear 2 stack position, MCC_ClearLocalStackRef clear 1 stack position */
50     static constexpr uint8 kMaxStackOffsetSize = 2;
51 
Insn(MemPool & memPool,MOperator opc)52     Insn(MemPool &memPool, MOperator opc)
53         : mOp(opc),
54           localAlloc(&memPool),
55           opnds(localAlloc.Adapter()),
56           registerBinding(localAlloc.Adapter()),
57           comment(&memPool),
58           stackMapLiveIn(localAlloc.Adapter())
59     {
60     }
Insn(MemPool & memPool,MOperator opc,Operand & opnd0)61     Insn(MemPool &memPool, MOperator opc, Operand &opnd0) : Insn(memPool, opc)
62     {
63         opnds.emplace_back(&opnd0);
64     }
Insn(MemPool & memPool,MOperator opc,Operand & opnd0,Operand & opnd1)65     Insn(MemPool &memPool, MOperator opc, Operand &opnd0, Operand &opnd1) : Insn(memPool, opc)
66     {
67         opnds.emplace_back(&opnd0);
68         opnds.emplace_back(&opnd1);
69     }
Insn(MemPool & memPool,MOperator opc,Operand & opnd0,Operand & opnd1,Operand & opnd2)70     Insn(MemPool &memPool, MOperator opc, Operand &opnd0, Operand &opnd1, Operand &opnd2) : Insn(memPool, opc)
71     {
72         opnds.emplace_back(&opnd0);
73         opnds.emplace_back(&opnd1);
74         opnds.emplace_back(&opnd2);
75     }
Insn(MemPool & memPool,MOperator opc,Operand & opnd0,Operand & opnd1,Operand & opnd2,Operand & opnd3)76     Insn(MemPool &memPool, MOperator opc, Operand &opnd0, Operand &opnd1, Operand &opnd2, Operand &opnd3)
77         : Insn(memPool, opc)
78     {
79         opnds.emplace_back(&opnd0);
80         opnds.emplace_back(&opnd1);
81         opnds.emplace_back(&opnd2);
82         opnds.emplace_back(&opnd3);
83     }
Insn(MemPool & memPool,MOperator opc,Operand & opnd0,Operand & opnd1,Operand & opnd2,Operand & opnd3,Operand & opnd4)84     Insn(MemPool &memPool, MOperator opc, Operand &opnd0, Operand &opnd1, Operand &opnd2, Operand &opnd3,
85          Operand &opnd4)
86         : Insn(memPool, opc)
87     {
88         opnds.emplace_back(&opnd0);
89         opnds.emplace_back(&opnd1);
90         opnds.emplace_back(&opnd2);
91         opnds.emplace_back(&opnd3);
92         opnds.emplace_back(&opnd4);
93     }
94     virtual ~Insn() = default;
95 
DeepClone(const Insn & insn,MapleAllocator & allocator)96     void DeepClone(const Insn &insn, MapleAllocator &allocator)
97     {
98         opnds.clear();
99         for (auto opnd : insn.opnds) {
100             opnds.emplace_back(opnd->CloneTree(allocator));
101         }
102     }
103 
104     // Custom deep copy
CloneTree(MapleAllocator & allocator)105     virtual Insn *CloneTree(MapleAllocator &allocator) const
106     {
107         auto *insn = allocator.GetMemPool()->New<Insn>(*this);
108         insn->DeepClone(*this, allocator);
109         return insn;
110     }
111 
GetMachineOpcode()112     MOperator GetMachineOpcode() const
113     {
114         return mOp;
115     }
116 
117     void SetMOP(const InsnDesc &idesc);
118 
AddOperand(Operand & opnd)119     void AddOperand(Operand &opnd)
120     {
121         opnds.emplace_back(&opnd);
122     }
123 
AddOpndChain(Operand & opnd)124     Insn &AddOpndChain(Operand &opnd)
125     {
126         AddOperand(opnd);
127         return *this;
128     }
129     /* use carefully which might cause insn to illegal */
130     void CommuteOperands(uint32 dIndex, uint32 sIndex);
CleanAllOperand()131     void CleanAllOperand()
132     {
133         opnds.clear();
134     }
135 
PopBackOperand()136     void PopBackOperand()
137     {
138         opnds.pop_back();
139     }
140 
GetOperand(uint32 index)141     Operand &GetOperand(uint32 index) const
142     {
143         DEBUG_ASSERT(index < opnds.size(), "index out of range");
144         return *opnds[index];
145     }
146 
ResizeOpnds(uint32 newSize)147     void ResizeOpnds(uint32 newSize)
148     {
149         opnds.resize(static_cast<std::size_t>(newSize));
150     }
151 
GetOperandSize()152     uint32 GetOperandSize() const
153     {
154         return static_cast<uint32>(opnds.size());
155     }
156 
SetOperand(uint32 index,Operand & opnd)157     void SetOperand(uint32 index, Operand &opnd)
158     {
159         DEBUG_ASSERT(index <= opnds.size(), "index out of range");
160         opnds[index] = &opnd;
161     }
162 
163     /* Get size info from machine description */
GetOperandSize(uint32 index)164     uint32 GetOperandSize(uint32 index) const
165     {
166         CHECK_FATAL(index < opnds.size(), "index out of range!");
167         const OpndDesc *opndMD = md->GetOpndDes(index);
168         return opndMD->GetSize();
169     }
170 
SetRetSize(uint32 size)171     void SetRetSize(uint32 size)
172     {
173         DEBUG_ASSERT(IsCall(), "Insn should be a call.");
174         retSize = size;
175     }
176 
GetRetSize()177     uint32 GetRetSize() const
178     {
179         DEBUG_ASSERT(IsCall(), "Insn should be a call.");
180         return retSize;
181     }
182 
183     // Insn Function: check legitimacy of opnds.
VerifySelf()184     bool VerifySelf() const
185     {
186         if (this->IsCfiInsn() || this->IsDbgInsn()) {
187             return true;
188         }
189         return md->Verify(opnds);
190     }
191 
SplitSelf(bool isAfterRegAlloc,InsnBuilder * insnBuilder,OperandBuilder * opndBuilder)192     void SplitSelf(bool isAfterRegAlloc, InsnBuilder *insnBuilder, OperandBuilder *opndBuilder)
193     {
194         md->Split(this, isAfterRegAlloc, insnBuilder, opndBuilder);
195     }
196 
197     virtual bool IsMachineInstruction() const;
198 
IsIntrinsic()199     virtual bool IsIntrinsic() const
200     {
201         return false;
202     }
203 
204     bool OpndIsDef(uint32 id) const;
205 
206     bool OpndIsUse(uint32 id) const;
207 
IsPCLoad()208     virtual bool IsPCLoad() const
209     {
210         return false;
211     }
212 
213     Operand *GetMemOpnd() const;
214 
215     uint32 GetMemOpndIdx() const;
216 
217     void SetMemOpnd(MemOperand *memOpnd);
218 
219     bool IsCall() const;
220     bool IsSpecialCall() const;
221     bool IsTailCall() const;
222     bool IsAsmInsn() const;
223     bool IsClinit() const;
224     bool CanThrow() const;
225     bool MayThrow() const;
226     bool IsBranch() const;
227     bool IsCondBranch() const;
228     bool IsUnCondBranch() const;
229     bool IsMove() const;
230     bool IsBasicOp() const;
231     bool IsUnaryOp() const;
232     bool IsShift() const;
233     bool IsPhi() const;
234     bool IsLoad() const;
235     bool IsStore() const;
236     bool IsConversion() const;
237     bool IsAtomic() const;
238 
239     bool IsLoadPair() const;
240     bool IsStorePair() const;
241     bool IsLoadStorePair() const;
242     bool IsLoadLabel() const;
243 
NoAlias()244     virtual bool NoAlias() const
245     {
246         return false;
247     }
248 
249     bool IsVolatile() const;
250 
251     bool IsMemAccessBar() const;
252 
253     bool IsMemAccess() const;
254 
HasSideEffects()255     virtual bool HasSideEffects() const
256     {
257         return false;
258     }
259 
260     bool HasLoop() const;
261 
262     virtual bool IsSpecialIntrinsic() const;
263 
264     bool IsComment() const;
265     bool IsImmaterialInsn() const;
266 
267     bool IsPseudo() const;
268 
IsTargetInsn()269     virtual bool IsTargetInsn() const
270     {
271         return true;
272     }
273 
IsCfiInsn()274     virtual bool IsCfiInsn() const
275     {
276         return false;
277     }
278 
IsDbgInsn()279     virtual bool IsDbgInsn() const
280     {
281         return false;
282     }
283 
IsDbgLine()284     virtual bool IsDbgLine() const
285     {
286         return false;
287     }
288 
289     bool IsDMBInsn() const;
290 
291     bool IsVectorOp() const;
292 
293     virtual Operand *GetCallTargetOperand() const;
294 
295     uint32 GetAtomicNum() const;
296     /*
297      * returns a ListOperand
298      * Note that we don't really need this for Emit
299      * Rather, we need it for register allocation, to
300      * correctly state the live ranges for operands
301      * use for passing call arguments
302      */
303     virtual ListOperand *GetCallArgumentOperand();
IsAtomicStore()304     bool IsAtomicStore() const
305     {
306         return IsStore() && IsAtomic();
307     }
308 
SetCondDef()309     void SetCondDef()
310     {
311         flags |= kOpCondDef;
312     }
313 
IsCondDef()314     bool IsCondDef() const
315     {
316         return flags & kOpCondDef;
317     }
318 
AccessMem()319     bool AccessMem() const
320     {
321         return IsLoad() || IsStore();
322     }
323 
IsFrameDef()324     bool IsFrameDef() const
325     {
326         return isFrameDef;
327     }
328 
SetFrameDef(bool b)329     void SetFrameDef(bool b)
330     {
331         isFrameDef = b;
332     }
333 
IsStackDef()334     bool IsStackDef() const
335     {
336         return isStackDef;
337     }
338 
SetStackDef(bool flag)339     void SetStackDef(bool flag)
340     {
341         isStackDef = flag;
342     }
343 
IsStackRevert()344     bool IsStackRevert() const
345     {
346         return isStackRevert;
347     }
348 
SetStackRevert(bool flag)349     void SetStackRevert(bool flag)
350     {
351         isStackRevert = flag;
352     }
353 
IsAsmDefCondCode()354     bool IsAsmDefCondCode() const
355     {
356         return asmDefCondCode;
357     }
358 
SetAsmDefCondCode()359     void SetAsmDefCondCode()
360     {
361         asmDefCondCode = true;
362     }
363 
IsAsmModMem()364     bool IsAsmModMem() const
365     {
366         return asmModMem;
367     }
368 
SetAsmModMem()369     void SetAsmModMem()
370     {
371         asmModMem = true;
372     }
373 
GetUnitType()374     virtual uint32 GetUnitType()
375     {
376         return 0;
377     }
378 
379     virtual void Dump() const;
380 
381     virtual bool CheckMD() const;
382 
SetComment(const std::string & str)383     void SetComment(const std::string &str)
384     {
385         comment = str;
386     }
387 
SetComment(const MapleString & str)388     void SetComment(const MapleString &str)
389     {
390         comment = str;
391     }
392 
GetComment()393     const MapleString &GetComment() const
394     {
395         return comment;
396     }
397 
AppendComment(const std::string & str)398     void AppendComment(const std::string &str)
399     {
400         comment += str;
401     }
402 
SetDebugComment(const MapleString * str)403     void SetDebugComment(const MapleString *str)
404     {
405         debugComment = str;
406     }
407 
GetDebugComment()408     const MapleString *GetDebugComment() const
409     {
410         return debugComment;
411     }
412 
MarkAsSaveRetValToLocal()413     void MarkAsSaveRetValToLocal()
414     {
415         flags |= kOpDassignToSaveRetValToLocal;
416     }
417 
IsSaveRetValToLocal()418     bool IsSaveRetValToLocal() const
419     {
420         return ((flags & kOpDassignToSaveRetValToLocal) != 0);
421     }
422 
MarkAsAccessRefField(bool cond)423     void MarkAsAccessRefField(bool cond)
424     {
425         if (cond) {
426             flags |= kOpAccessRefField;
427         }
428     }
429 
IsAccessRefField()430     bool IsAccessRefField() const
431     {
432         return ((flags & kOpAccessRefField) != 0);
433     }
434 
GetPreviousMachineInsn()435     Insn *GetPreviousMachineInsn() const
436     {
437         for (Insn *returnInsn = prev; returnInsn != nullptr; returnInsn = returnInsn->prev) {
438             DEBUG_ASSERT(returnInsn->bb == bb, "insn and it's prev insn must have same bb");
439             if (returnInsn->IsMachineInstruction()) {
440                 return returnInsn;
441             }
442         }
443         return nullptr;
444     }
445 
GetNextMachineInsn()446     Insn *GetNextMachineInsn() const
447     {
448         for (Insn *returnInsn = next; returnInsn != nullptr; returnInsn = returnInsn->next) {
449             CHECK_FATAL(returnInsn->bb == bb, "insn and it's next insn must have same bb");
450             if (returnInsn->IsMachineInstruction()) {
451                 return returnInsn;
452             }
453         }
454         return nullptr;
455     }
456 
457     uint32 GetLatencyType() const;
458 
SetPrev(Insn * prev)459     void SetPrev(Insn *prev)
460     {
461         this->prev = prev;
462     }
463 
GetPrev()464     Insn *GetPrev()
465     {
466         return prev;
467     }
468 
GetPrev()469     const Insn *GetPrev() const
470     {
471         return prev;
472     }
473 
SetNext(Insn * next)474     void SetNext(Insn *next)
475     {
476         this->next = next;
477     }
478 
GetNext()479     Insn *GetNext() const
480     {
481         return next;
482     }
483 
SetBB(BB * bb)484     void SetBB(BB *bb)
485     {
486         this->bb = bb;
487     }
488 
GetBB()489     BB *GetBB()
490     {
491         return bb;
492     }
493 
GetBB()494     const BB *GetBB() const
495     {
496         return bb;
497     }
498 
SetId(uint32 id)499     void SetId(uint32 id)
500     {
501         this->id = id;
502     }
503 
GetId()504     uint32 GetId() const
505     {
506         return id;
507     }
508 
SetAddress(uint32 addr)509     void SetAddress(uint32 addr)
510     {
511         address = addr;
512     }
513 
GetAddress()514     uint32 GetAddress() const
515     {
516         return address;
517     }
518 
SetNopNum(uint32 num)519     void SetNopNum(uint32 num)
520     {
521         nopNum = num;
522     }
523 
GetNopNum()524     uint32 GetNopNum() const
525     {
526         return nopNum;
527     }
528 
SetNeedSplit(bool flag)529     void SetNeedSplit(bool flag)
530     {
531         needSplit = flag;
532     }
533 
IsNeedSplit()534     bool IsNeedSplit() const
535     {
536         return needSplit;
537     }
538 
SetIsThrow(bool isThrow)539     void SetIsThrow(bool isThrow)
540     {
541         this->isThrow = isThrow;
542     }
543 
GetIsThrow()544     bool GetIsThrow() const
545     {
546         return isThrow;
547     }
548 
SetDoNotRemove(bool doNotRemove)549     void SetDoNotRemove(bool doNotRemove)
550     {
551         this->doNotRemove = doNotRemove;
552     }
553 
GetDoNotRemove()554     bool GetDoNotRemove() const
555     {
556         return doNotRemove;
557     }
558 
SetIsSpill()559     void SetIsSpill()
560     {
561         this->isSpill = true;
562     }
563 
GetIsSpill()564     bool GetIsSpill() const
565     {
566         return isSpill;
567     }
568 
SetIsReload()569     void SetIsReload()
570     {
571         this->isReload = true;
572     }
573 
GetIsReload()574     bool GetIsReload() const
575     {
576         return isReload;
577     }
578 
IsSpillInsn()579     bool IsSpillInsn() const
580     {
581         return (isSpill || isReload);
582     }
583 
SetIsCallReturnUnsigned(bool unSigned)584     void SetIsCallReturnUnsigned(bool unSigned)
585     {
586         DEBUG_ASSERT(IsCall(), "Insn should be a call.");
587         this->isCallReturnUnsigned = unSigned;
588     }
589 
GetIsCallReturnUnsigned()590     bool GetIsCallReturnUnsigned() const
591     {
592         DEBUG_ASSERT(IsCall(), "Insn should be a call.");
593         return isCallReturnUnsigned;
594     }
595 
GetIsCallReturnSigned()596     bool GetIsCallReturnSigned() const
597     {
598         DEBUG_ASSERT(IsCall(), "Insn should be a call.");
599         return !isCallReturnUnsigned;
600     }
601 
SetClearStackOffset(short index,int64 offset)602     void SetClearStackOffset(short index, int64 offset)
603     {
604         CHECK_FATAL(index < kMaxStackOffsetSize, "out of clearStackOffset's range");
605         clearStackOffset[index] = offset;
606     }
607 
GetClearStackOffset(short index)608     int64 GetClearStackOffset(short index) const
609     {
610         CHECK_FATAL(index < kMaxStackOffsetSize, "out of clearStackOffset's range");
611         return clearStackOffset[index];
612     }
613 
614     /* if function name is MCC_ClearLocalStackRef or MCC_DecRefResetPair, will clear designate stack slot */
IsClearDesignateStackCall()615     bool IsClearDesignateStackCall() const
616     {
617         return clearStackOffset[0] != -1 || clearStackOffset[1] != -1;
618     }
619 
SetDepNode(DepNode & depNode)620     void SetDepNode(DepNode &depNode)
621     {
622         this->depNode = &depNode;
623     }
624 
GetDepNode()625     DepNode *GetDepNode()
626     {
627         return depNode;
628     }
629 
GetDepNode()630     const DepNode *GetDepNode() const
631     {
632         return depNode;
633     }
634 
SetIsPhiMovInsn(bool val)635     void SetIsPhiMovInsn(bool val)
636     {
637         isPhiMovInsn = val;
638     }
639 
IsPhiMovInsn()640     bool IsPhiMovInsn() const
641     {
642         return isPhiMovInsn;
643     }
644 
645     Insn *Clone(MemPool &memPool) const;
646 
SetInsnDescrption(const InsnDesc & newMD)647     void SetInsnDescrption(const InsnDesc &newMD)
648     {
649         md = &newMD;
650     }
651 
GetDesc()652     const InsnDesc *GetDesc() const
653     {
654         return md;
655     }
656 
AddRegBinding(uint32 regA,uint32 regB)657     void AddRegBinding(uint32 regA, uint32 regB)
658     {
659         (void)registerBinding.emplace(regA, regB);
660     }
661 
GetRegBinding()662     const MapleMap<uint32, uint32> &GetRegBinding() const
663     {
664         return registerBinding;
665     }
666 
SetReferenceOsts(MemDefUse * memDefUse)667     void SetReferenceOsts(MemDefUse *memDefUse)
668     {
669         referenceOsts = memDefUse;
670     }
671 
GetReferenceOsts()672     const MemDefUse *GetReferenceOsts() const
673     {
674         return referenceOsts;
675     }
676 
MergeReferenceOsts(Insn & rhs)677     void MergeReferenceOsts(Insn &rhs)
678     {
679         if (referenceOsts == nullptr) {
680             SetReferenceOsts(rhs.referenceOsts);
681         } else if (rhs.referenceOsts != nullptr) {
682             referenceOsts->MergeOthers(*rhs.referenceOsts);
683         }
684     }
685 
Equals(const Insn & rhs)686     bool Equals(const Insn &rhs) const
687     {
688         if (&rhs == this) {
689             return true;
690         }
691         if (mOp != rhs.mOp || opnds.size() != rhs.opnds.size()) {
692             return false;
693         }
694         for (uint32 i = 0; i < opnds.size(); ++i) {
695             if (!opnds[i]->Equals(*rhs.opnds[i])) {
696                 return false;
697             }
698         }
699         return true;
700     }
701 
AddDeoptBundleInfo(int32 deoptVreg,Operand & opnd)702     void AddDeoptBundleInfo(int32 deoptVreg, Operand &opnd)
703     {
704         if (stackMap == nullptr) {
705             stackMap = localAlloc.New<StackMap>(localAlloc);
706         }
707         stackMap->GetDeoptInfo().AddDeoptBundleInfo(deoptVreg, opnd);
708     }
709 
GetStackMap()710     StackMap *GetStackMap()
711     {
712         return stackMap;
713     }
714 
GetStackMap()715     const StackMap *GetStackMap() const
716     {
717         return stackMap;
718     }
719 
InitStackMapInfo()720     void InitStackMapInfo()
721     {
722         if (stackMap != nullptr) {
723             return;
724         }
725         stackMap = localAlloc.New<StackMap>(localAlloc);
726     }
727 
SetRefSkipIdx(int32 index)728     void SetRefSkipIdx(int32 index)
729     {
730         refSkipIdx = index;
731     }
732 
733     /* Get Size of memory write/read by insn */
734     uint32 GetMemoryByteSize() const;
735 
736     /* return ture if register appears */
737     virtual bool ScanReg(regno_t regNO) const;
738 
739     virtual bool IsRegDefined(regno_t regNO) const;
740 
741     virtual std::set<uint32> GetDefRegs() const;
742 
743     virtual uint32 GetBothDefUseOpnd() const;
744 
SetStackMapDef(SparseDataInfo & def)745     void SetStackMapDef(SparseDataInfo &def)
746     {
747         stackMapDef = &def;
748     }
749 
GetStackMapDef()750     SparseDataInfo *GetStackMapDef()
751     {
752         return stackMapDef;
753     }
754 
SetStackMapUse(SparseDataInfo & use)755     void SetStackMapUse(SparseDataInfo &use)
756     {
757         stackMapUse = &use;
758     }
759 
GetStackMapUse()760     SparseDataInfo *GetStackMapUse()
761     {
762         return stackMapUse;
763     }
764 
SetStackMapLiveIn(SparseDataInfo & liveIn)765     void SetStackMapLiveIn(SparseDataInfo &liveIn)
766     {
767         liveIn.GetInfo().ConvertToSet(stackMapLiveIn);
768     }
769 
GetStackMapLiveIn()770     const MapleSet<regno_t> &GetStackMapLiveIn() const
771     {
772         return stackMapLiveIn;
773     }
774 
ClearStackMapDefUse()775     void ClearStackMapDefUse()
776     {
777         stackMapDef = nullptr;
778         stackMapUse = nullptr;
779     }
780 
781 protected:
782     MOperator mOp;
783     MapleAllocator localAlloc;
784     MapleVector<Operand *> opnds;
785     Insn *prev = nullptr;
786     Insn *next = nullptr;
787     BB *bb = nullptr; /* BB to which this insn belongs */
788     uint32 flags = 0;
789     bool isPhiMovInsn = false;
790 
791 private:
792     MapleMap<uint32, uint32> registerBinding; /* used for inline asm only */
793     StackMap *stackMap = nullptr;
794     enum OpKind : uint32 {
795         kOpUnknown = 0,
796         kOpCondDef = 0x1,
797         kOpAccessRefField = (1ULL << 30),            /* load-from/store-into a ref flag-fieldGetMachineOpcode() */
798         kOpDassignToSaveRetValToLocal = (1ULL << 31) /* save return value to local flag */
799     };
800 
801     uint32 id = 0;
802     uint32 address = 0;
803     uint32 nopNum = 0;
804     uint32 retSize = 0; /* Byte size of the return value if insn is a call. */
805     /* record the stack cleared by MCC_ClearLocalStackRef or MCC_DecRefResetPair */
806     int64 clearStackOffset[kMaxStackOffsetSize] = {-1, -1};
807     DepNode *depNode = nullptr; /* For dependence analysis, pointing to a dependence node. */
808     const MapleString *debugComment = nullptr;
809     MapleString comment;
810     bool isThrow = false;
811     bool doNotRemove = false;          /* caller reg cross call */
812     bool isCallReturnUnsigned = false; /* for call insn only. false: signed, true: unsigned */
813     bool isSpill = false;              /* used as hint for optimization */
814     bool isReload = false;             /* used as hint for optimization */
815     bool isFrameDef = false;
816     bool isStackDef = false;     // def sp in prolog
817     bool isStackRevert = false;  // revert sp in epilog
818     bool asmDefCondCode = false;
819     bool asmModMem = false;
820     bool needSplit = false;
821 
822     /* for dynamic language to mark reference counting */
823     int32 refSkipIdx = -1;
824 
825     /* for multiple architecture */
826     const InsnDesc *md = nullptr;
827     MemDefUse *referenceOsts = nullptr;
828     SparseDataInfo *stackMapDef = nullptr;
829     SparseDataInfo *stackMapUse = nullptr;
830     MapleSet<regno_t> stackMapLiveIn;
831 };
832 
833 struct VectorRegSpec {
VectorRegSpecVectorRegSpec834     VectorRegSpec() : vecLane(-1), vecLaneMax(0), vecElementSize(0), compositeOpnds(0) {}
835 
836     VectorRegSpec(PrimType type, int16 lane = -1, uint16 compositeOpnds = 0)
vecLaneVectorRegSpec837         : vecLane(lane),
838           vecLaneMax(GetVecLanes(type)),
839           vecElementSize(GetVecEleSize(type)),
840           compositeOpnds(compositeOpnds)
841     {
842     }
843 
844     VectorRegSpec(uint16 laneNum, uint16 eleSize, int16 lane = -1, uint16 compositeOpnds = 0)
vecLaneVectorRegSpec845         : vecLane(lane), vecLaneMax(laneNum), vecElementSize(eleSize), compositeOpnds(compositeOpnds)
846     {
847     }
848 
849     int16 vecLane;         /* -1 for whole reg, 0 to 15 to specify individual lane */
850     uint16 vecLaneMax;     /* Maximum number of lanes for this vregister */
851     uint16 vecElementSize; /* element size in each Lane */
852     uint16 compositeOpnds; /* Number of enclosed operands within this composite operand */
853 };
854 
855 class VectorInsn : public Insn {
856 public:
VectorInsn(MemPool & memPool,MOperator opc)857     VectorInsn(MemPool &memPool, MOperator opc) : Insn(memPool, opc), regSpecList(localAlloc.Adapter())
858     {
859         regSpecList.clear();
860     }
861 
862     ~VectorInsn() override = default;
863 
ClearRegSpecList()864     void ClearRegSpecList()
865     {
866         regSpecList.clear();
867     }
868 
869     VectorRegSpec *GetAndRemoveRegSpecFromList();
870 
GetNumOfRegSpec()871     size_t GetNumOfRegSpec() const
872     {
873         if (IsVectorOp() && !regSpecList.empty()) {
874             return regSpecList.size();
875         }
876         return 0;
877     }
878 
GetRegSpecList()879     MapleVector<VectorRegSpec *> &GetRegSpecList()
880     {
881         return regSpecList;
882     }
883 
SetRegSpecList(const MapleVector<VectorRegSpec * > & vec)884     void SetRegSpecList(const MapleVector<VectorRegSpec *> &vec)
885     {
886         regSpecList = vec;
887     }
888 
PushRegSpecEntry(VectorRegSpec * v)889     VectorInsn &PushRegSpecEntry(VectorRegSpec *v)
890     {
891         regSpecList.emplace(regSpecList.begin(), v);
892         return *this;
893     }
894 
895 private:
896     MapleVector<VectorRegSpec *> regSpecList;
897 };
898 
899 struct InsnIdCmp {
operatorInsnIdCmp900     bool operator()(const Insn *lhs, const Insn *rhs) const
901     {
902         CHECK_FATAL(lhs != nullptr, "lhs is nullptr in InsnIdCmp");
903         CHECK_FATAL(rhs != nullptr, "rhs is nullptr in InsnIdCmp");
904         return lhs->GetId() < rhs->GetId();
905     }
906 };
907 using InsnSet = std::set<Insn *, InsnIdCmp>;
908 using InsnMapleSet = MapleSet<Insn *, InsnIdCmp>;
909 } /* namespace maplebe */
910 
911 #endif /* MAPLEBE_INCLUDE_CG_INSN_H */
912