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