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