1 //===--------------------- Instruction.h ------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file defines abstractions used by the Pipeline to model register reads, 11 /// register writes and instructions. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_MCA_INSTRUCTION_H 16 #define LLVM_MCA_INSTRUCTION_H 17 18 #include "llvm/ADT/ArrayRef.h" 19 #include "llvm/ADT/STLExtras.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/MC/MCRegister.h" // definition of MCPhysReg. 22 #include "llvm/Support/MathExtras.h" 23 24 #ifndef NDEBUG 25 #include "llvm/Support/raw_ostream.h" 26 #endif 27 28 #include <memory> 29 30 namespace llvm { 31 32 namespace mca { 33 34 constexpr int UNKNOWN_CYCLES = -512; 35 36 /// A register write descriptor. 37 struct WriteDescriptor { 38 // Operand index. The index is negative for implicit writes only. 39 // For implicit writes, the actual operand index is computed performing 40 // a bitwise not of the OpIndex. 41 int OpIndex; 42 // Write latency. Number of cycles before write-back stage. 43 unsigned Latency; 44 // This field is set to a value different than zero only if this 45 // is an implicit definition. 46 MCPhysReg RegisterID; 47 // Instruction itineraries would set this field to the SchedClass ID. 48 // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry 49 // element associated to this write. 50 // When computing read latencies, this value is matched against the 51 // "ReadAdvance" information. The hardware backend may implement 52 // dedicated forwarding paths to quickly propagate write results to dependent 53 // instructions waiting in the reservation station (effectively bypassing the 54 // write-back stage). 55 unsigned SClassOrWriteResourceID; 56 // True only if this is a write obtained from an optional definition. 57 // Optional definitions are allowed to reference regID zero (i.e. "no 58 // register"). 59 bool IsOptionalDef; 60 isImplicitWriteWriteDescriptor61 bool isImplicitWrite() const { return OpIndex < 0; }; 62 }; 63 64 /// A register read descriptor. 65 struct ReadDescriptor { 66 // A MCOperand index. This is used by the Dispatch logic to identify register 67 // reads. Implicit reads have negative indices. The actual operand index of an 68 // implicit read is the bitwise not of field OpIndex. 69 int OpIndex; 70 // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit 71 // uses always come first in the sequence of uses. 72 unsigned UseIndex; 73 // This field is only set if this is an implicit read. 74 MCPhysReg RegisterID; 75 // Scheduling Class Index. It is used to query the scheduling model for the 76 // MCSchedClassDesc object. 77 unsigned SchedClassID; 78 isImplicitReadReadDescriptor79 bool isImplicitRead() const { return OpIndex < 0; }; 80 }; 81 82 class ReadState; 83 84 /// A critical data dependency descriptor. 85 /// 86 /// Field RegID is set to the invalid register for memory dependencies. 87 struct CriticalDependency { 88 unsigned IID; 89 MCPhysReg RegID; 90 unsigned Cycles; 91 }; 92 93 /// Tracks uses of a register definition (e.g. register write). 94 /// 95 /// Each implicit/explicit register write is associated with an instance of 96 /// this class. A WriteState object tracks the dependent users of a 97 /// register write. It also tracks how many cycles are left before the write 98 /// back stage. 99 class WriteState { 100 const WriteDescriptor *WD; 101 // On instruction issue, this field is set equal to the write latency. 102 // Before instruction issue, this field defaults to -512, a special 103 // value that represents an "unknown" number of cycles. 104 int CyclesLeft; 105 106 // Actual register defined by this write. This field is only used 107 // to speedup queries on the register file. 108 // For implicit writes, this field always matches the value of 109 // field RegisterID from WD. 110 MCPhysReg RegisterID; 111 112 // Physical register file that serves register RegisterID. 113 unsigned PRFID; 114 115 // True if this write implicitly clears the upper portion of RegisterID's 116 // super-registers. 117 bool ClearsSuperRegs; 118 119 // True if this write is from a dependency breaking zero-idiom instruction. 120 bool WritesZero; 121 122 // True if this write has been eliminated at register renaming stage. 123 // Example: a register move doesn't consume scheduler/pipleline resources if 124 // it is eliminated at register renaming stage. It still consumes 125 // decode bandwidth, and ROB entries. 126 bool IsEliminated; 127 128 // This field is set if this is a partial register write, and it has a false 129 // dependency on any previous write of the same register (or a portion of it). 130 // DependentWrite must be able to complete before this write completes, so 131 // that we don't break the WAW, and the two writes can be merged together. 132 const WriteState *DependentWrite; 133 134 // A partial write that is in a false dependency with this write. 135 WriteState *PartialWrite; 136 unsigned DependentWriteCyclesLeft; 137 138 // Critical register dependency for this write. 139 CriticalDependency CRD; 140 141 // A list of dependent reads. Users is a set of dependent 142 // reads. A dependent read is added to the set only if CyclesLeft 143 // is "unknown". As soon as CyclesLeft is 'known', each user in the set 144 // gets notified with the actual CyclesLeft. 145 146 // The 'second' element of a pair is a "ReadAdvance" number of cycles. 147 SmallVector<std::pair<ReadState *, int>, 4> Users; 148 149 public: 150 WriteState(const WriteDescriptor &Desc, MCPhysReg RegID, 151 bool clearsSuperRegs = false, bool writesZero = false) 152 : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0), 153 ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero), 154 IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr), 155 DependentWriteCyclesLeft(0), CRD() {} 156 157 WriteState(const WriteState &Other) = default; 158 WriteState &operator=(const WriteState &Other) = default; 159 getCyclesLeft()160 int getCyclesLeft() const { return CyclesLeft; } getWriteResourceID()161 unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; } getRegisterID()162 MCPhysReg getRegisterID() const { return RegisterID; } getRegisterFileID()163 unsigned getRegisterFileID() const { return PRFID; } getLatency()164 unsigned getLatency() const { return WD->Latency; } getDependentWriteCyclesLeft()165 unsigned getDependentWriteCyclesLeft() const { 166 return DependentWriteCyclesLeft; 167 } getDependentWrite()168 const WriteState *getDependentWrite() const { return DependentWrite; } getCriticalRegDep()169 const CriticalDependency &getCriticalRegDep() const { return CRD; } 170 171 // This method adds Use to the set of data dependent reads. IID is the 172 // instruction identifier associated with this write. ReadAdvance is the 173 // number of cycles to subtract from the latency of this data dependency. 174 // Use is in a RAW dependency with this write. 175 void addUser(unsigned IID, ReadState *Use, int ReadAdvance); 176 177 // Use is a younger register write that is in a false dependency with this 178 // write. IID is the instruction identifier associated with this write. 179 void addUser(unsigned IID, WriteState *Use); 180 getNumUsers()181 unsigned getNumUsers() const { 182 unsigned NumUsers = Users.size(); 183 if (PartialWrite) 184 ++NumUsers; 185 return NumUsers; 186 } 187 clearsSuperRegisters()188 bool clearsSuperRegisters() const { return ClearsSuperRegs; } isWriteZero()189 bool isWriteZero() const { return WritesZero; } isEliminated()190 bool isEliminated() const { return IsEliminated; } 191 isReady()192 bool isReady() const { 193 if (DependentWrite) 194 return false; 195 unsigned CyclesLeft = getDependentWriteCyclesLeft(); 196 return !CyclesLeft || CyclesLeft < getLatency(); 197 } 198 isExecuted()199 bool isExecuted() const { 200 return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0; 201 } 202 setDependentWrite(const WriteState * Other)203 void setDependentWrite(const WriteState *Other) { DependentWrite = Other; } 204 void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles); setWriteZero()205 void setWriteZero() { WritesZero = true; } setEliminated()206 void setEliminated() { 207 assert(Users.empty() && "Write is in an inconsistent state."); 208 CyclesLeft = 0; 209 IsEliminated = true; 210 } 211 setPRF(unsigned PRF)212 void setPRF(unsigned PRF) { PRFID = PRF; } 213 214 // On every cycle, update CyclesLeft and notify dependent users. 215 void cycleEvent(); 216 void onInstructionIssued(unsigned IID); 217 218 #ifndef NDEBUG 219 void dump() const; 220 #endif 221 }; 222 223 /// Tracks register operand latency in cycles. 224 /// 225 /// A read may be dependent on more than one write. This occurs when some 226 /// writes only partially update the register associated to this read. 227 class ReadState { 228 const ReadDescriptor *RD; 229 // Physical register identified associated to this read. 230 MCPhysReg RegisterID; 231 // Physical register file that serves register RegisterID. 232 unsigned PRFID; 233 // Number of writes that contribute to the definition of RegisterID. 234 // In the absence of partial register updates, the number of DependentWrites 235 // cannot be more than one. 236 unsigned DependentWrites; 237 // Number of cycles left before RegisterID can be read. This value depends on 238 // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES. 239 // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of 240 // every dependent write is known. 241 int CyclesLeft; 242 // This field is updated on every writeStartEvent(). When the number of 243 // dependent writes (i.e. field DependentWrite) is zero, this value is 244 // propagated to field CyclesLeft. 245 unsigned TotalCycles; 246 // Longest register dependency. 247 CriticalDependency CRD; 248 // This field is set to true only if there are no dependent writes, and 249 // there are no `CyclesLeft' to wait. 250 bool IsReady; 251 // True if this is a read from a known zero register. 252 bool IsZero; 253 // True if this register read is from a dependency-breaking instruction. 254 bool IndependentFromDef; 255 256 public: ReadState(const ReadDescriptor & Desc,MCPhysReg RegID)257 ReadState(const ReadDescriptor &Desc, MCPhysReg RegID) 258 : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0), 259 CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true), 260 IsZero(false), IndependentFromDef(false) {} 261 getDescriptor()262 const ReadDescriptor &getDescriptor() const { return *RD; } getSchedClass()263 unsigned getSchedClass() const { return RD->SchedClassID; } getRegisterID()264 MCPhysReg getRegisterID() const { return RegisterID; } getRegisterFileID()265 unsigned getRegisterFileID() const { return PRFID; } getCriticalRegDep()266 const CriticalDependency &getCriticalRegDep() const { return CRD; } 267 isPending()268 bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; } isReady()269 bool isReady() const { return IsReady; } isImplicitRead()270 bool isImplicitRead() const { return RD->isImplicitRead(); } 271 isIndependentFromDef()272 bool isIndependentFromDef() const { return IndependentFromDef; } setIndependentFromDef()273 void setIndependentFromDef() { IndependentFromDef = true; } 274 275 void cycleEvent(); 276 void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles); setDependentWrites(unsigned Writes)277 void setDependentWrites(unsigned Writes) { 278 DependentWrites = Writes; 279 IsReady = !Writes; 280 } 281 isReadZero()282 bool isReadZero() const { return IsZero; } setReadZero()283 void setReadZero() { IsZero = true; } setPRF(unsigned ID)284 void setPRF(unsigned ID) { PRFID = ID; } 285 }; 286 287 /// A sequence of cycles. 288 /// 289 /// This class can be used as a building block to construct ranges of cycles. 290 class CycleSegment { 291 unsigned Begin; // Inclusive. 292 unsigned End; // Exclusive. 293 bool Reserved; // Resources associated to this segment must be reserved. 294 295 public: 296 CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false) Begin(StartCycle)297 : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {} 298 contains(unsigned Cycle)299 bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; } startsAfter(const CycleSegment & CS)300 bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; } endsBefore(const CycleSegment & CS)301 bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; } overlaps(const CycleSegment & CS)302 bool overlaps(const CycleSegment &CS) const { 303 return !startsAfter(CS) && !endsBefore(CS); 304 } isExecuting()305 bool isExecuting() const { return Begin == 0 && End != 0; } isExecuted()306 bool isExecuted() const { return End == 0; } 307 bool operator<(const CycleSegment &Other) const { 308 return Begin < Other.Begin; 309 } 310 CycleSegment &operator--(void) { 311 if (Begin) 312 Begin--; 313 if (End) 314 End--; 315 return *this; 316 } 317 isValid()318 bool isValid() const { return Begin <= End; } size()319 unsigned size() const { return End - Begin; }; subtract(unsigned Cycles)320 void subtract(unsigned Cycles) { 321 assert(End >= Cycles); 322 End -= Cycles; 323 } 324 begin()325 unsigned begin() const { return Begin; } end()326 unsigned end() const { return End; } setEnd(unsigned NewEnd)327 void setEnd(unsigned NewEnd) { End = NewEnd; } isReserved()328 bool isReserved() const { return Reserved; } setReserved()329 void setReserved() { Reserved = true; } 330 }; 331 332 /// Helper used by class InstrDesc to describe how hardware resources 333 /// are used. 334 /// 335 /// This class describes how many resource units of a specific resource kind 336 /// (and how many cycles) are "used" by an instruction. 337 struct ResourceUsage { 338 CycleSegment CS; 339 unsigned NumUnits; 340 ResourceUsage(CycleSegment Cycles, unsigned Units = 1) CSResourceUsage341 : CS(Cycles), NumUnits(Units) {} sizeResourceUsage342 unsigned size() const { return CS.size(); } isReservedResourceUsage343 bool isReserved() const { return CS.isReserved(); } setReservedResourceUsage344 void setReserved() { CS.setReserved(); } 345 }; 346 347 /// An instruction descriptor 348 struct InstrDesc { 349 SmallVector<WriteDescriptor, 4> Writes; // Implicit writes are at the end. 350 SmallVector<ReadDescriptor, 4> Reads; // Implicit reads are at the end. 351 352 // For every resource used by an instruction of this kind, this vector 353 // reports the number of "consumed cycles". 354 SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Resources; 355 356 // A bitmask of used hardware buffers. 357 uint64_t UsedBuffers; 358 359 // A bitmask of used processor resource units. 360 uint64_t UsedProcResUnits; 361 362 // A bitmask of used processor resource groups. 363 uint64_t UsedProcResGroups; 364 365 unsigned MaxLatency; 366 // Number of MicroOps for this instruction. 367 unsigned NumMicroOps; 368 // SchedClassID used to construct this InstrDesc. 369 // This information is currently used by views to do fast queries on the 370 // subtarget when computing the reciprocal throughput. 371 unsigned SchedClassID; 372 373 bool MayLoad; 374 bool MayStore; 375 bool HasSideEffects; 376 bool BeginGroup; 377 bool EndGroup; 378 379 // True if all buffered resources are in-order, and there is at least one 380 // buffer which is a dispatch hazard (BufferSize = 0). 381 bool MustIssueImmediately; 382 383 // A zero latency instruction doesn't consume any scheduler resources. isZeroLatencyInstrDesc384 bool isZeroLatency() const { return !MaxLatency && Resources.empty(); } 385 386 InstrDesc() = default; 387 InstrDesc(const InstrDesc &Other) = delete; 388 InstrDesc &operator=(const InstrDesc &Other) = delete; 389 }; 390 391 /// Base class for instructions consumed by the simulation pipeline. 392 /// 393 /// This class tracks data dependencies as well as generic properties 394 /// of the instruction. 395 class InstructionBase { 396 const InstrDesc &Desc; 397 398 // This field is set for instructions that are candidates for move 399 // elimination. For more information about move elimination, see the 400 // definition of RegisterMappingTracker in RegisterFile.h 401 bool IsOptimizableMove; 402 403 // Output dependencies. 404 // One entry per each implicit and explicit register definition. 405 SmallVector<WriteState, 4> Defs; 406 407 // Input dependencies. 408 // One entry per each implicit and explicit register use. 409 SmallVector<ReadState, 4> Uses; 410 411 public: InstructionBase(const InstrDesc & D)412 InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {} 413 getDefs()414 SmallVectorImpl<WriteState> &getDefs() { return Defs; } getDefs()415 const ArrayRef<WriteState> getDefs() const { return Defs; } getUses()416 SmallVectorImpl<ReadState> &getUses() { return Uses; } getUses()417 const ArrayRef<ReadState> getUses() const { return Uses; } getDesc()418 const InstrDesc &getDesc() const { return Desc; } 419 getLatency()420 unsigned getLatency() const { return Desc.MaxLatency; } getNumMicroOps()421 unsigned getNumMicroOps() const { return Desc.NumMicroOps; } 422 hasDependentUsers()423 bool hasDependentUsers() const { 424 return any_of(Defs, 425 [](const WriteState &Def) { return Def.getNumUsers() > 0; }); 426 } 427 getNumUsers()428 unsigned getNumUsers() const { 429 unsigned NumUsers = 0; 430 for (const WriteState &Def : Defs) 431 NumUsers += Def.getNumUsers(); 432 return NumUsers; 433 } 434 435 // Returns true if this instruction is a candidate for move elimination. isOptimizableMove()436 bool isOptimizableMove() const { return IsOptimizableMove; } setOptimizableMove()437 void setOptimizableMove() { IsOptimizableMove = true; } isMemOp()438 bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; } 439 }; 440 441 /// An instruction propagated through the simulated instruction pipeline. 442 /// 443 /// This class is used to monitor changes to the internal state of instructions 444 /// that are sent to the various components of the simulated hardware pipeline. 445 class Instruction : public InstructionBase { 446 enum InstrStage { 447 IS_INVALID, // Instruction in an invalid state. 448 IS_DISPATCHED, // Instruction dispatched but operands are not ready. 449 IS_PENDING, // Instruction is not ready, but operand latency is known. 450 IS_READY, // Instruction dispatched and operands ready. 451 IS_EXECUTING, // Instruction issued. 452 IS_EXECUTED, // Instruction executed. Values are written back. 453 IS_RETIRED // Instruction retired. 454 }; 455 456 // The current instruction stage. 457 enum InstrStage Stage; 458 459 // This value defaults to the instruction latency. This instruction is 460 // considered executed when field CyclesLeft goes to zero. 461 int CyclesLeft; 462 463 // Retire Unit token ID for this instruction. 464 unsigned RCUTokenID; 465 466 // LS token ID for this instruction. 467 // This field is set to the invalid null token if this is not a memory 468 // operation. 469 unsigned LSUTokenID; 470 471 // A resource mask which identifies buffered resources consumed by this 472 // instruction at dispatch stage. In the absence of macro-fusion, this value 473 // should always match the value of field `UsedBuffers` from the instruction 474 // descriptor (see field InstrBase::Desc). 475 uint64_t UsedBuffers; 476 477 // Critical register dependency. 478 CriticalDependency CriticalRegDep; 479 480 // Critical memory dependency. 481 CriticalDependency CriticalMemDep; 482 483 // A bitmask of busy processor resource units. 484 // This field is set to zero only if execution is not delayed during this 485 // cycle because of unavailable pipeline resources. 486 uint64_t CriticalResourceMask; 487 488 // True if this instruction has been optimized at register renaming stage. 489 bool IsEliminated; 490 491 public: Instruction(const InstrDesc & D)492 Instruction(const InstrDesc &D) 493 : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES), 494 RCUTokenID(0), LSUTokenID(0), UsedBuffers(D.UsedBuffers), 495 CriticalRegDep(), CriticalMemDep(), CriticalResourceMask(0), 496 IsEliminated(false) {} 497 getRCUTokenID()498 unsigned getRCUTokenID() const { return RCUTokenID; } getLSUTokenID()499 unsigned getLSUTokenID() const { return LSUTokenID; } setLSUTokenID(unsigned LSUTok)500 void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; } 501 getUsedBuffers()502 uint64_t getUsedBuffers() const { return UsedBuffers; } setUsedBuffers(uint64_t Mask)503 void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; } clearUsedBuffers()504 void clearUsedBuffers() { UsedBuffers = 0ULL; } 505 getCyclesLeft()506 int getCyclesLeft() const { return CyclesLeft; } 507 508 // Transition to the dispatch stage, and assign a RCUToken to this 509 // instruction. The RCUToken is used to track the completion of every 510 // register write performed by this instruction. 511 void dispatch(unsigned RCUTokenID); 512 513 // Instruction issued. Transition to the IS_EXECUTING state, and update 514 // all the register definitions. 515 void execute(unsigned IID); 516 517 // Force a transition from the IS_DISPATCHED state to the IS_READY or 518 // IS_PENDING state. State transitions normally occur either at the beginning 519 // of a new cycle (see method cycleEvent()), or as a result of another issue 520 // event. This method is called every time the instruction might have changed 521 // in state. It internally delegates to method updateDispatched() and 522 // updateWaiting(). 523 void update(); 524 bool updateDispatched(); 525 bool updatePending(); 526 isDispatched()527 bool isDispatched() const { return Stage == IS_DISPATCHED; } isPending()528 bool isPending() const { return Stage == IS_PENDING; } isReady()529 bool isReady() const { return Stage == IS_READY; } isExecuting()530 bool isExecuting() const { return Stage == IS_EXECUTING; } isExecuted()531 bool isExecuted() const { return Stage == IS_EXECUTED; } isRetired()532 bool isRetired() const { return Stage == IS_RETIRED; } isEliminated()533 bool isEliminated() const { return IsEliminated; } 534 535 // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED. 536 void forceExecuted(); setEliminated()537 void setEliminated() { IsEliminated = true; } 538 retire()539 void retire() { 540 assert(isExecuted() && "Instruction is in an invalid state!"); 541 Stage = IS_RETIRED; 542 } 543 getCriticalRegDep()544 const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; } getCriticalMemDep()545 const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; } 546 const CriticalDependency &computeCriticalRegDep(); setCriticalMemDep(const CriticalDependency & MemDep)547 void setCriticalMemDep(const CriticalDependency &MemDep) { 548 CriticalMemDep = MemDep; 549 } 550 getCriticalResourceMask()551 uint64_t getCriticalResourceMask() const { return CriticalResourceMask; } setCriticalResourceMask(uint64_t ResourceMask)552 void setCriticalResourceMask(uint64_t ResourceMask) { 553 CriticalResourceMask = ResourceMask; 554 } 555 556 void cycleEvent(); 557 }; 558 559 /// An InstRef contains both a SourceMgr index and Instruction pair. The index 560 /// is used as a unique identifier for the instruction. MCA will make use of 561 /// this index as a key throughout MCA. 562 class InstRef { 563 std::pair<unsigned, Instruction *> Data; 564 565 public: InstRef()566 InstRef() : Data(std::make_pair(0, nullptr)) {} InstRef(unsigned Index,Instruction * I)567 InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {} 568 569 bool operator==(const InstRef &Other) const { return Data == Other.Data; } 570 bool operator!=(const InstRef &Other) const { return Data != Other.Data; } 571 bool operator<(const InstRef &Other) const { 572 return Data.first < Other.Data.first; 573 } 574 getSourceIndex()575 unsigned getSourceIndex() const { return Data.first; } getInstruction()576 Instruction *getInstruction() { return Data.second; } getInstruction()577 const Instruction *getInstruction() const { return Data.second; } 578 579 /// Returns true if this references a valid instruction. 580 explicit operator bool() const { return Data.second != nullptr; } 581 582 /// Invalidate this reference. invalidate()583 void invalidate() { Data.second = nullptr; } 584 585 #ifndef NDEBUG print(raw_ostream & OS)586 void print(raw_ostream &OS) const { OS << getSourceIndex(); } 587 #endif 588 }; 589 590 #ifndef NDEBUG 591 inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) { 592 IR.print(OS); 593 return OS; 594 } 595 #endif 596 597 /// A reference to a register write. 598 /// 599 /// This class is mainly used by the register file to describe register 600 /// mappings. It correlates a register write to the source index of the 601 /// defining instruction. 602 class WriteRef { 603 std::pair<unsigned, WriteState *> Data; 604 static const unsigned INVALID_IID; 605 606 public: WriteRef()607 WriteRef() : Data(INVALID_IID, nullptr) {} WriteRef(unsigned SourceIndex,WriteState * WS)608 WriteRef(unsigned SourceIndex, WriteState *WS) : Data(SourceIndex, WS) {} 609 getSourceIndex()610 unsigned getSourceIndex() const { return Data.first; } getWriteState()611 const WriteState *getWriteState() const { return Data.second; } getWriteState()612 WriteState *getWriteState() { return Data.second; } invalidate()613 void invalidate() { Data.second = nullptr; } isWriteZero()614 bool isWriteZero() const { 615 assert(isValid() && "Invalid null WriteState found!"); 616 return getWriteState()->isWriteZero(); 617 } 618 619 /// Returns true if this register write has been executed, and the new 620 /// register value is therefore available to users. isAvailable()621 bool isAvailable() const { 622 if (getSourceIndex() == INVALID_IID) 623 return false; 624 const WriteState *WS = getWriteState(); 625 return !WS || WS->isExecuted(); 626 } 627 isValid()628 bool isValid() const { return Data.second && Data.first != INVALID_IID; } 629 bool operator==(const WriteRef &Other) const { return Data == Other.Data; } 630 631 #ifndef NDEBUG 632 void dump() const; 633 #endif 634 }; 635 636 } // namespace mca 637 } // namespace llvm 638 639 #endif // LLVM_MCA_INSTRUCTION_H 640