Instruction.h revision 360784
1652Sjkh//===--------------------- Instruction.h ------------------------*- C++ -*-===// 233473Sscrappy// 3139825Simp// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4139825Simp// See https://llvm.org/LICENSE.txt for license information. 5139825Simp// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6652Sjkh// 733473Sscrappy//===----------------------------------------------------------------------===// 8652Sjkh/// \file 9652Sjkh/// 10652Sjkh/// This file defines abstractions used by the Pipeline to model register reads, 11652Sjkh/// register writes and instructions. 12652Sjkh/// 13652Sjkh//===----------------------------------------------------------------------===// 1433473Sscrappy 1533473Sscrappy#ifndef LLVM_MCA_INSTRUCTION_H 1633473Sscrappy#define LLVM_MCA_INSTRUCTION_H 1733473Sscrappy 18652Sjkh#include "llvm/ADT/ArrayRef.h" 1933473Sscrappy#include "llvm/ADT/STLExtras.h" 2033473Sscrappy#include "llvm/ADT/SmallVector.h" 2133473Sscrappy#include "llvm/MC/MCRegister.h" // definition of MCPhysReg. 2233473Sscrappy#include "llvm/Support/MathExtras.h" 2333473Sscrappy 2433473Sscrappy#ifndef NDEBUG 2533473Sscrappy#include "llvm/Support/raw_ostream.h" 2633473Sscrappy#endif 2733473Sscrappy 2833473Sscrappy#include <memory> 2933473Sscrappy 3033473Sscrappynamespace llvm { 3150734Speter 3250734Speternamespace mca { 33652Sjkh 34652Sjkhconstexpr int UNKNOWN_CYCLES = -512; 3550906Sdfr 3650906Sdfr/// A register write descriptor. 3765335Scgstruct WriteDescriptor { 38652Sjkh // Operand index. The index is negative for implicit writes only. 3965335Scg // For implicit writes, the actual operand index is computed performing 4013765Smpp // a bitwise not of the OpIndex. 41652Sjkh int OpIndex; 42652Sjkh // Write latency. Number of cycles before write-back stage. 43652Sjkh unsigned Latency; 443256Sswallace // This field is set to a value different than zero only if this 4530866Smarkm // is an implicit definition. 4630866Smarkm MCPhysReg RegisterID; 4765335Scg // Instruction itineraries would set this field to the SchedClass ID. 4882033Sgreid // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry 4930866Smarkm // element associated to this write. 5030866Smarkm // When computing read latencies, this value is matched against the 5182033Sgreid // "ReadAdvance" information. The hardware backend may implement 5230866Smarkm // dedicated forwarding paths to quickly propagate write results to dependent 5330866Smarkm // instructions waiting in the reservation station (effectively bypassing the 54652Sjkh // write-back stage). 55652Sjkh unsigned SClassOrWriteResourceID; 5633530Sscrappy // True only if this is a write obtained from an optional definition. 5733530Sscrappy // Optional definitions are allowed to reference regID zero (i.e. "no 5833530Sscrappy // register"). 5933530Sscrappy bool IsOptionalDef; 6033530Sscrappy 6133530Sscrappy bool isImplicitWrite() const { return OpIndex < 0; }; 6233530Sscrappy}; 6333530Sscrappy 6433530Sscrappy/// A register read descriptor. 6533530Sscrappystruct ReadDescriptor { 6633530Sscrappy // A MCOperand index. This is used by the Dispatch logic to identify register 6733530Sscrappy // reads. Implicit reads have negative indices. The actual operand index of an 6833530Sscrappy // implicit read is the bitwise not of field OpIndex. 6933530Sscrappy int OpIndex; 7033530Sscrappy // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit 7133530Sscrappy // uses always come first in the sequence of uses. 7233530Sscrappy unsigned UseIndex; 7333530Sscrappy // This field is only set if this is an implicit read. 7433530Sscrappy MCPhysReg RegisterID; 7533530Sscrappy // Scheduling Class Index. It is used to query the scheduling model for the 7633530Sscrappy // MCSchedClassDesc object. 7733530Sscrappy unsigned SchedClassID; 7833530Sscrappy 7933530Sscrappy bool isImplicitRead() const { return OpIndex < 0; }; 8033530Sscrappy}; 8133530Sscrappy 8233530Sscrappyclass ReadState; 8333530Sscrappy 8433530Sscrappy/// A critical data dependency descriptor. 8533530Sscrappy/// 8633530Sscrappy/// Field RegID is set to the invalid register for memory dependencies. 8733530Sscrappystruct CriticalDependency { 8833530Sscrappy unsigned IID; 8933530Sscrappy MCPhysReg RegID; 9033530Sscrappy unsigned Cycles; 9133530Sscrappy}; 9233530Sscrappy 9333530Sscrappy/// Tracks uses of a register definition (e.g. register write). 9482033Sgreid/// 9545240Skato/// Each implicit/explicit register write is associated with an instance of 9662947Stanimura/// this class. A WriteState object tracks the dependent users of a 9762947Stanimura/// register write. It also tracks how many cycles are left before the write 9833530Sscrappy/// back stage. 9933473Sscrappyclass WriteState { 100114181Smbr const WriteDescriptor *WD; 10133473Sscrappy // On instruction issue, this field is set equal to the write latency. 10233473Sscrappy // Before instruction issue, this field defaults to -512, a special 10333473Sscrappy // value that represents an "unknown" number of cycles. 104652Sjkh int CyclesLeft; 105652Sjkh 10633473Sscrappy // Actual register defined by this write. This field is only used 10733473Sscrappy // to speedup queries on the register file. 10833473Sscrappy // For implicit writes, this field always matches the value of 10933473Sscrappy // field RegisterID from WD. 11033473Sscrappy MCPhysReg RegisterID; 111652Sjkh 112652Sjkh // Physical register file that serves register RegisterID. 11333473Sscrappy unsigned PRFID; 11433473Sscrappy 11533473Sscrappy // True if this write implicitly clears the upper portion of RegisterID's 11633473Sscrappy // super-registers. 11733473Sscrappy bool ClearsSuperRegs; 11833473Sscrappy 11933473Sscrappy // True if this write is from a dependency breaking zero-idiom instruction. 12033473Sscrappy bool WritesZero; 12133473Sscrappy 12233473Sscrappy // True if this write has been eliminated at register renaming stage. 12333473Sscrappy // Example: a register move doesn't consume scheduler/pipleline resources if 12433473Sscrappy // it is eliminated at register renaming stage. It still consumes 12533473Sscrappy // decode bandwidth, and ROB entries. 12665335Scg bool IsEliminated; 12733473Sscrappy 12833473Sscrappy // This field is set if this is a partial register write, and it has a false 12933473Sscrappy // dependency on any previous write of the same register (or a portion of it). 13033473Sscrappy // DependentWrite must be able to complete before this write completes, so 13133473Sscrappy // that we don't break the WAW, and the two writes can be merged together. 13233473Sscrappy const WriteState *DependentWrite; 13333473Sscrappy 13433473Sscrappy // A partial write that is in a false dependency with this write. 13533473Sscrappy WriteState *PartialWrite; 136652Sjkh unsigned DependentWriteCyclesLeft; 13730866Smarkm 13833473Sscrappy // Critical register dependency for this write. 13933473Sscrappy CriticalDependency CRD; 14033473Sscrappy 14133473Sscrappy // A list of dependent reads. Users is a set of dependent 14233473Sscrappy // reads. A dependent read is added to the set only if CyclesLeft 14333473Sscrappy // is "unknown". As soon as CyclesLeft is 'known', each user in the set 14481891Ssobomax // gets notified with the actual CyclesLeft. 14581891Ssobomax 14681891Ssobomax // The 'second' element of a pair is a "ReadAdvance" number of cycles. 14781891Ssobomax SmallVector<std::pair<ReadState *, int>, 4> Users; 14881891Ssobomax 14981891Ssobomaxpublic: 15081891Ssobomax WriteState(const WriteDescriptor &Desc, MCPhysReg RegID, 15133473Sscrappy bool clearsSuperRegs = false, bool writesZero = false) 15233473Sscrappy : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0), 15381891Ssobomax ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero), 15481891Ssobomax IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr), 15581891Ssobomax DependentWriteCyclesLeft(0), CRD() {} 15681891Ssobomax 15781891Ssobomax WriteState(const WriteState &Other) = default; 15881891Ssobomax WriteState &operator=(const WriteState &Other) = default; 15981891Ssobomax 16081891Ssobomax int getCyclesLeft() const { return CyclesLeft; } 16181891Ssobomax unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; } 16281891Ssobomax MCPhysReg getRegisterID() const { return RegisterID; } 16381891Ssobomax unsigned getRegisterFileID() const { return PRFID; } 16481891Ssobomax unsigned getLatency() const { return WD->Latency; } 16581891Ssobomax unsigned getDependentWriteCyclesLeft() const { 16681891Ssobomax return DependentWriteCyclesLeft; 167114181Smbr } 168114642Smbr const WriteState *getDependentWrite() const { return DependentWrite; } 169114181Smbr const CriticalDependency &getCriticalRegDep() const { return CRD; } 170114181Smbr 171114181Smbr // This method adds Use to the set of data dependent reads. IID is the 172114181Smbr // instruction identifier associated with this write. ReadAdvance is the 173114181Smbr // number of cycles to subtract from the latency of this data dependency. 17465335Scg // Use is in a RAW dependency with this write. 17581891Ssobomax void addUser(unsigned IID, ReadState *Use, int ReadAdvance); 17681891Ssobomax 17781891Ssobomax // Use is a younger register write that is in a false dependency with this 17865335Scg // write. IID is the instruction identifier associated with this write. 17981891Ssobomax void addUser(unsigned IID, WriteState *Use); 18081891Ssobomax 18181891Ssobomax unsigned getNumUsers() const { 18281891Ssobomax unsigned NumUsers = Users.size(); 183148605Snetchild if (PartialWrite) 184148605Snetchild ++NumUsers; 185148605Snetchild return NumUsers; 186148605Snetchild } 18733473Sscrappy 18881891Ssobomax bool clearsSuperRegisters() const { return ClearsSuperRegs; } 18933473Sscrappy bool isWriteZero() const { return WritesZero; } 19033473Sscrappy bool isEliminated() const { return IsEliminated; } 19133473Sscrappy 19233473Sscrappy bool isReady() const { 19381891Ssobomax if (DependentWrite) 19433473Sscrappy return false; 19533473Sscrappy unsigned CyclesLeft = getDependentWriteCyclesLeft(); 19633473Sscrappy return !CyclesLeft || CyclesLeft < getLatency(); 19733473Sscrappy } 19833473Sscrappy 19933473Sscrappy bool isExecuted() const { 20033473Sscrappy return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0; 20133473Sscrappy } 20281891Ssobomax 20333473Sscrappy void setDependentWrite(const WriteState *Other) { DependentWrite = Other; } 20433473Sscrappy void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles); 20533473Sscrappy void setWriteZero() { WritesZero = true; } 20633473Sscrappy void setEliminated() { 20733473Sscrappy assert(Users.empty() && "Write is in an inconsistent state."); 20833473Sscrappy CyclesLeft = 0; 20933473Sscrappy IsEliminated = true; 21033473Sscrappy } 21133473Sscrappy 21233473Sscrappy void setPRF(unsigned PRF) { PRFID = PRF; } 21333473Sscrappy 21433473Sscrappy // On every cycle, update CyclesLeft and notify dependent users. 21533473Sscrappy void cycleEvent(); 21633473Sscrappy void onInstructionIssued(unsigned IID); 21733473Sscrappy 21833473Sscrappy#ifndef NDEBUG 21933473Sscrappy void dump() const; 22033473Sscrappy#endif 22133473Sscrappy}; 22233473Sscrappy 22333473Sscrappy/// Tracks register operand latency in cycles. 22433473Sscrappy/// 22533473Sscrappy/// A read may be dependent on more than one write. This occurs when some 22633473Sscrappy/// writes only partially update the register associated to this read. 22733473Sscrappyclass ReadState { 22833473Sscrappy const ReadDescriptor *RD; 22933473Sscrappy // Physical register identified associated to this read. 23033473Sscrappy MCPhysReg RegisterID; 23133473Sscrappy // Physical register file that serves register RegisterID. 23233473Sscrappy unsigned PRFID; 23333473Sscrappy // Number of writes that contribute to the definition of RegisterID. 23433473Sscrappy // In the absence of partial register updates, the number of DependentWrites 23533473Sscrappy // cannot be more than one. 23633473Sscrappy unsigned DependentWrites; 23733473Sscrappy // Number of cycles left before RegisterID can be read. This value depends on 23833473Sscrappy // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES. 23933473Sscrappy // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of 24033473Sscrappy // every dependent write is known. 24133473Sscrappy int CyclesLeft; 24233473Sscrappy // This field is updated on every writeStartEvent(). When the number of 24333473Sscrappy // dependent writes (i.e. field DependentWrite) is zero, this value is 24433473Sscrappy // propagated to field CyclesLeft. 24533473Sscrappy unsigned TotalCycles; 24633473Sscrappy // Longest register dependency. 24733473Sscrappy CriticalDependency CRD; 24833473Sscrappy // This field is set to true only if there are no dependent writes, and 24933473Sscrappy // there are no `CyclesLeft' to wait. 25033473Sscrappy bool IsReady; 25133473Sscrappy // True if this is a read from a known zero register. 25233473Sscrappy bool IsZero; 25333473Sscrappy // True if this register read is from a dependency-breaking instruction. 25433473Sscrappy bool IndependentFromDef; 25533473Sscrappy 25633473Sscrappypublic: 25733473Sscrappy ReadState(const ReadDescriptor &Desc, MCPhysReg RegID) 25833473Sscrappy : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0), 25933473Sscrappy CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true), 26033473Sscrappy IsZero(false), IndependentFromDef(false) {} 26133473Sscrappy 26233473Sscrappy const ReadDescriptor &getDescriptor() const { return *RD; } 26333473Sscrappy unsigned getSchedClass() const { return RD->SchedClassID; } 26433473Sscrappy MCPhysReg getRegisterID() const { return RegisterID; } 26533473Sscrappy unsigned getRegisterFileID() const { return PRFID; } 26633473Sscrappy const CriticalDependency &getCriticalRegDep() const { return CRD; } 26733473Sscrappy 26833473Sscrappy bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; } 26933473Sscrappy bool isReady() const { return IsReady; } 27033473Sscrappy bool isImplicitRead() const { return RD->isImplicitRead(); } 27133473Sscrappy 27233473Sscrappy bool isIndependentFromDef() const { return IndependentFromDef; } 27333473Sscrappy void setIndependentFromDef() { IndependentFromDef = true; } 27433473Sscrappy 27533473Sscrappy void cycleEvent(); 27633473Sscrappy void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles); 27733473Sscrappy void setDependentWrites(unsigned Writes) { 27833473Sscrappy DependentWrites = Writes; 27933473Sscrappy IsReady = !Writes; 28033473Sscrappy } 28133473Sscrappy 282652Sjkh bool isReadZero() const { return IsZero; } 283652Sjkh void setReadZero() { IsZero = true; } 284652Sjkh void setPRF(unsigned ID) { PRFID = ID; } 28533473Sscrappy}; 28633473Sscrappy 28733473Sscrappy/// A sequence of cycles. 28833473Sscrappy/// 28933473Sscrappy/// This class can be used as a building block to construct ranges of cycles. 29033473Sscrappyclass CycleSegment { 29133473Sscrappy unsigned Begin; // Inclusive. 29233473Sscrappy unsigned End; // Exclusive. 29333473Sscrappy bool Reserved; // Resources associated to this segment must be reserved. 29433473Sscrappy 29533473Sscrappypublic: 29633473Sscrappy CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false) 29733473Sscrappy : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {} 29833473Sscrappy 29933473Sscrappy bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; } 30033473Sscrappy bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; } 30133473Sscrappy bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; } 30233473Sscrappy bool overlaps(const CycleSegment &CS) const { 30333473Sscrappy return !startsAfter(CS) && !endsBefore(CS); 30433473Sscrappy } 305122954Smatk bool isExecuting() const { return Begin == 0 && End != 0; } 3069750Sjkh bool isExecuted() const { return End == 0; } 30730866Smarkm bool operator<(const CycleSegment &Other) const { 30830866Smarkm return Begin < Other.Begin; 30930866Smarkm } 3109750Sjkh CycleSegment &operator--(void) { 31133473Sscrappy if (Begin) 31233473Sscrappy Begin--; 31333473Sscrappy if (End) 31433473Sscrappy End--; 31533473Sscrappy return *this; 31633473Sscrappy } 31733473Sscrappy 31833473Sscrappy bool isValid() const { return Begin <= End; } 31933473Sscrappy unsigned size() const { return End - Begin; }; 32033473Sscrappy void subtract(unsigned Cycles) { 32133473Sscrappy assert(End >= Cycles); 32233473Sscrappy End -= Cycles; 32333473Sscrappy } 32433473Sscrappy 3253256Sswallace unsigned begin() const { return Begin; } 326652Sjkh unsigned end() const { return End; } 32730866Smarkm void setEnd(unsigned NewEnd) { End = NewEnd; } 32830866Smarkm bool isReserved() const { return Reserved; } 32930866Smarkm void setReserved() { Reserved = true; } 33030866Smarkm}; 33130866Smarkm 33230866Smarkm/// Helper used by class InstrDesc to describe how hardware resources 33330866Smarkm/// are used. 33430866Smarkm/// 33530866Smarkm/// This class describes how many resource units of a specific resource kind 33630866Smarkm/// (and how many cycles) are "used" by an instruction. 337652Sjkhstruct ResourceUsage { 338652Sjkh CycleSegment CS; 339652Sjkh unsigned NumUnits; 34033473Sscrappy ResourceUsage(CycleSegment Cycles, unsigned Units = 1) 341652Sjkh : CS(Cycles), NumUnits(Units) {} 342652Sjkh unsigned size() const { return CS.size(); } 343652Sjkh bool isReserved() const { return CS.isReserved(); } 34430866Smarkm void setReserved() { CS.setReserved(); } 34530866Smarkm}; 34630866Smarkm 34730866Smarkm/// An instruction descriptor 348652Sjkhstruct InstrDesc { 34930866Smarkm SmallVector<WriteDescriptor, 4> Writes; // Implicit writes are at the end. 35030866Smarkm SmallVector<ReadDescriptor, 4> Reads; // Implicit reads are at the end. 35130866Smarkm 35230866Smarkm // For every resource used by an instruction of this kind, this vector 353652Sjkh // reports the number of "consumed cycles". 354652Sjkh SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Resources; 355652Sjkh 356652Sjkh // A bitmask of used hardware buffers. 357652Sjkh uint64_t UsedBuffers; 358652Sjkh 359652Sjkh // A bitmask of used processor resource units. 360652Sjkh uint64_t UsedProcResUnits; 361652Sjkh 362652Sjkh // A bitmask of used processor resource groups. 363652Sjkh uint64_t UsedProcResGroups; 364652Sjkh 365652Sjkh unsigned MaxLatency; 366652Sjkh // Number of MicroOps for this instruction. 367652Sjkh unsigned NumMicroOps; 368652Sjkh // SchedClassID used to construct this InstrDesc. 369652Sjkh // This information is currently used by views to do fast queries on the 370652Sjkh // subtarget when computing the reciprocal throughput. 37130866Smarkm unsigned SchedClassID; 37230866Smarkm 373652Sjkh bool MayLoad; 37465335Scg bool MayStore; 375652Sjkh bool HasSideEffects; 376652Sjkh bool BeginGroup; 377652Sjkh bool EndGroup; 378652Sjkh 379652Sjkh // True if all buffered resources are in-order, and there is at least one 380652Sjkh // buffer which is a dispatch hazard (BufferSize = 0). 381652Sjkh bool MustIssueImmediately; 382108533Sschweikh 383652Sjkh // A zero latency instruction doesn't consume any scheduler resources. 384652Sjkh bool isZeroLatency() const { return !MaxLatency && Resources.empty(); } 385652Sjkh 386652Sjkh InstrDesc() = default; 387652Sjkh InstrDesc(const InstrDesc &Other) = delete; 388652Sjkh InstrDesc &operator=(const InstrDesc &Other) = delete; 389652Sjkh}; 39030866Smarkm 39130866Smarkm/// Base class for instructions consumed by the simulation pipeline. 39230866Smarkm/// 39330866Smarkm/// This class tracks data dependencies as well as generic properties 39430866Smarkm/// of the instruction. 39530866Smarkmclass InstructionBase { 396652Sjkh const InstrDesc &Desc; 397652Sjkh 398652Sjkh // This field is set for instructions that are candidates for move 399652Sjkh // elimination. For more information about move elimination, see the 40030866Smarkm // definition of RegisterMappingTracker in RegisterFile.h 40130866Smarkm bool IsOptimizableMove; 402652Sjkh 40365335Scg // Output dependencies. 404652Sjkh // One entry per each implicit and explicit register definition. 405652Sjkh SmallVector<WriteState, 4> Defs; 406652Sjkh 407652Sjkh // Input dependencies. 408652Sjkh // One entry per each implicit and explicit register use. 40930866Smarkm SmallVector<ReadState, 4> Uses; 41030866Smarkm 41130866Smarkmpublic: 412652Sjkh InstructionBase(const InstrDesc &D) : Desc(D), IsOptimizableMove(false) {} 41330866Smarkm 41430866Smarkm SmallVectorImpl<WriteState> &getDefs() { return Defs; } 41530866Smarkm const ArrayRef<WriteState> getDefs() const { return Defs; } 41630866Smarkm SmallVectorImpl<ReadState> &getUses() { return Uses; } 41730866Smarkm const ArrayRef<ReadState> getUses() const { return Uses; } 41830866Smarkm const InstrDesc &getDesc() const { return Desc; } 41965335Scg 42030866Smarkm unsigned getLatency() const { return Desc.MaxLatency; } 42130866Smarkm unsigned getNumMicroOps() const { return Desc.NumMicroOps; } 42230866Smarkm 42330866Smarkm bool hasDependentUsers() const { 424652Sjkh return any_of(Defs, 4253256Sswallace [](const WriteState &Def) { return Def.getNumUsers() > 0; }); 42630866Smarkm } 42730866Smarkm 42830866Smarkm unsigned getNumUsers() const { 42930866Smarkm unsigned NumUsers = 0; 43030866Smarkm for (const WriteState &Def : Defs) 43130866Smarkm NumUsers += Def.getNumUsers(); 43230866Smarkm return NumUsers; 4333256Sswallace } 434652Sjkh 435652Sjkh // Returns true if this instruction is a candidate for move elimination. 436652Sjkh bool isOptimizableMove() const { return IsOptimizableMove; } 437652Sjkh void setOptimizableMove() { IsOptimizableMove = true; } 438652Sjkh bool isMemOp() const { return Desc.MayLoad || Desc.MayStore; } 439652Sjkh}; 44033473Sscrappy 44133473Sscrappy/// An instruction propagated through the simulated instruction pipeline. 44233473Sscrappy/// 44333473Sscrappy/// This class is used to monitor changes to the internal state of instructions 444652Sjkh/// that are sent to the various components of the simulated hardware pipeline. 445652Sjkhclass Instruction : public InstructionBase { 446652Sjkh enum InstrStage { 447652Sjkh IS_INVALID, // Instruction in an invalid state. 448652Sjkh IS_DISPATCHED, // Instruction dispatched but operands are not ready. 449652Sjkh IS_PENDING, // Instruction is not ready, but operand latency is known. 450652Sjkh IS_READY, // Instruction dispatched and operands ready. 451652Sjkh IS_EXECUTING, // Instruction issued. 452652Sjkh IS_EXECUTED, // Instruction executed. Values are written back. 453652Sjkh IS_RETIRED // Instruction retired. 454652Sjkh }; 455652Sjkh 45665335Scg // The current instruction stage. 457652Sjkh enum InstrStage Stage; 458652Sjkh 459652Sjkh // This value defaults to the instruction latency. This instruction is 460652Sjkh // considered executed when field CyclesLeft goes to zero. 46130866Smarkm int CyclesLeft; 462652Sjkh 463652Sjkh // Retire Unit token ID for this instruction. 464108533Sschweikh unsigned RCUTokenID; 465652Sjkh 466652Sjkh // LS token ID for this instruction. 467652Sjkh // This field is set to the invalid null token if this is not a memory 468652Sjkh // operation. 469652Sjkh unsigned LSUTokenID; 47065335Scg 47165335Scg // A resource mask which identifies buffered resources consumed by this 472652Sjkh // instruction at dispatch stage. In the absence of macro-fusion, this value 473652Sjkh // should always match the value of field `UsedBuffers` from the instruction 474652Sjkh // descriptor (see field InstrBase::Desc). 475652Sjkh uint64_t UsedBuffers; 476652Sjkh 477652Sjkh // Critical register dependency. 478652Sjkh CriticalDependency CriticalRegDep; 479652Sjkh 480652Sjkh // Critical memory dependency. 481652Sjkh CriticalDependency CriticalMemDep; 482652Sjkh 483652Sjkh // A bitmask of busy processor resource units. 484652Sjkh // This field is set to zero only if execution is not delayed during this 485652Sjkh // cycle because of unavailable pipeline resources. 486652Sjkh uint64_t CriticalResourceMask; 487652Sjkh 488652Sjkh // True if this instruction has been optimized at register renaming stage. 489652Sjkh bool IsEliminated; 490652Sjkh 49165335Scgpublic: 492652Sjkh Instruction(const InstrDesc &D) 493652Sjkh : InstructionBase(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES), 494652Sjkh RCUTokenID(0), LSUTokenID(0), UsedBuffers(D.UsedBuffers), 49530866Smarkm CriticalRegDep(), CriticalMemDep(), CriticalResourceMask(0), 49630866Smarkm IsEliminated(false) {} 49730866Smarkm 498652Sjkh unsigned getRCUTokenID() const { return RCUTokenID; } 49930866Smarkm unsigned getLSUTokenID() const { return LSUTokenID; } 50030866Smarkm void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; } 50130866Smarkm 50230866Smarkm uint64_t getUsedBuffers() const { return UsedBuffers; } 503652Sjkh void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; } 50430866Smarkm void clearUsedBuffers() { UsedBuffers = 0ULL; } 50530866Smarkm 506652Sjkh int getCyclesLeft() const { return CyclesLeft; } 507652Sjkh 508652Sjkh // Transition to the dispatch stage, and assign a RCUToken to this 509652Sjkh // instruction. The RCUToken is used to track the completion of every 510652Sjkh // register write performed by this instruction. 511652Sjkh void dispatch(unsigned RCUTokenID); 512652Sjkh 513652Sjkh // Instruction issued. Transition to the IS_EXECUTING state, and update 514652Sjkh // all the register definitions. 515652Sjkh void execute(unsigned IID); 516652Sjkh 517652Sjkh // Force a transition from the IS_DISPATCHED state to the IS_READY or 518652Sjkh // IS_PENDING state. State transitions normally occur either at the beginning 519652Sjkh // of a new cycle (see method cycleEvent()), or as a result of another issue 520652Sjkh // event. This method is called every time the instruction might have changed 521652Sjkh // in state. It internally delegates to method updateDispatched() and 52265335Scg // updateWaiting(). 523652Sjkh void update(); 524652Sjkh bool updateDispatched(); 525652Sjkh bool updatePending(); 526652Sjkh 527652Sjkh bool isDispatched() const { return Stage == IS_DISPATCHED; } 528652Sjkh bool isPending() const { return Stage == IS_PENDING; } 5293256Sswallace bool isReady() const { return Stage == IS_READY; } 530652Sjkh bool isExecuting() const { return Stage == IS_EXECUTING; } 531652Sjkh bool isExecuted() const { return Stage == IS_EXECUTED; } 532652Sjkh bool isRetired() const { return Stage == IS_RETIRED; } 533652Sjkh bool isEliminated() const { return IsEliminated; } 534652Sjkh 535652Sjkh // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED. 536652Sjkh void forceExecuted(); 537652Sjkh void setEliminated() { IsEliminated = true; } 538652Sjkh 539652Sjkh void retire() { 540652Sjkh assert(isExecuted() && "Instruction is in an invalid state!"); 541652Sjkh Stage = IS_RETIRED; 5423256Sswallace } 543652Sjkh 544652Sjkh const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; } 5453256Sswallace const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; } 546652Sjkh const CriticalDependency &computeCriticalRegDep(); 547652Sjkh void setCriticalMemDep(const CriticalDependency &MemDep) { 548652Sjkh CriticalMemDep = MemDep; 5493256Sswallace } 550652Sjkh 551652Sjkh uint64_t getCriticalResourceMask() const { return CriticalResourceMask; } 5523256Sswallace void setCriticalResourceMask(uint64_t ResourceMask) { 55333473Sscrappy CriticalResourceMask = ResourceMask; 5543256Sswallace } 55533473Sscrappy 55633473Sscrappy void cycleEvent(); 55733473Sscrappy}; 55833473Sscrappy 55933473Sscrappy/// An InstRef contains both a SourceMgr index and Instruction pair. The index 56033473Sscrappy/// is used as a unique identifier for the instruction. MCA will make use of 56133473Sscrappy/// this index as a key throughout MCA. 5623256Sswallaceclass InstRef { 5633256Sswallace std::pair<unsigned, Instruction *> Data; 56433473Sscrappy 56533473Sscrappypublic: 56633473Sscrappy InstRef() : Data(std::make_pair(0, nullptr)) {} 56733473Sscrappy InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {} 56833473Sscrappy 56933473Sscrappy bool operator==(const InstRef &Other) const { return Data == Other.Data; } 57033473Sscrappy bool operator!=(const InstRef &Other) const { return Data != Other.Data; } 57133473Sscrappy bool operator<(const InstRef &Other) const { 57233473Sscrappy return Data.first < Other.Data.first; 57333473Sscrappy } 57433473Sscrappy 57533473Sscrappy unsigned getSourceIndex() const { return Data.first; } 57633473Sscrappy Instruction *getInstruction() { return Data.second; } 57733473Sscrappy const Instruction *getInstruction() const { return Data.second; } 57833473Sscrappy 57933473Sscrappy /// Returns true if this references a valid instruction. 58033473Sscrappy explicit operator bool() const { return Data.second != nullptr; } 58133473Sscrappy 5823256Sswallace /// Invalidate this reference. 58333473Sscrappy void invalidate() { Data.second = nullptr; } 5843256Sswallace 58533473Sscrappy#ifndef NDEBUG 58633473Sscrappy void print(raw_ostream &OS) const { OS << getSourceIndex(); } 58733473Sscrappy#endif 58833473Sscrappy}; 58933473Sscrappy 59033473Sscrappy#ifndef NDEBUG 59133473Sscrappyinline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) { 59233473Sscrappy IR.print(OS); 59333473Sscrappy return OS; 59433473Sscrappy} 59533473Sscrappy#endif 59633473Sscrappy 59733473Sscrappy/// A reference to a register write. 59833473Sscrappy/// 59933473Sscrappy/// This class is mainly used by the register file to describe register 60033473Sscrappy/// mappings. It correlates a register write to the source index of the 60133473Sscrappy/// defining instruction. 6023256Sswallaceclass WriteRef { 60333473Sscrappy std::pair<unsigned, WriteState *> Data; 60433473Sscrappy static const unsigned INVALID_IID; 60533473Sscrappy 60633473Sscrappypublic: 60733473Sscrappy WriteRef() : Data(INVALID_IID, nullptr) {} 60833473Sscrappy WriteRef(unsigned SourceIndex, WriteState *WS) : Data(SourceIndex, WS) {} 60933473Sscrappy 61033473Sscrappy unsigned getSourceIndex() const { return Data.first; } 61133473Sscrappy const WriteState *getWriteState() const { return Data.second; } 61233473Sscrappy WriteState *getWriteState() { return Data.second; } 61333473Sscrappy void invalidate() { Data.second = nullptr; } 61433473Sscrappy bool isWriteZero() const { 61533473Sscrappy assert(isValid() && "Invalid null WriteState found!"); 61633473Sscrappy return getWriteState()->isWriteZero(); 61733473Sscrappy } 61833473Sscrappy 61933473Sscrappy /// Returns true if this register write has been executed, and the new 62033473Sscrappy /// register value is therefore available to users. 62133473Sscrappy bool isAvailable() const { 6223256Sswallace if (getSourceIndex() == INVALID_IID) 6233256Sswallace return false; 62433473Sscrappy const WriteState *WS = getWriteState(); 62533473Sscrappy return !WS || WS->isExecuted(); 62633473Sscrappy } 62733473Sscrappy 62833473Sscrappy bool isValid() const { return Data.second && Data.first != INVALID_IID; } 629652Sjkh bool operator==(const WriteRef &Other) const { return Data == Other.Data; } 6301402Sache 631652Sjkh#ifndef NDEBUG 632652Sjkh void dump() const; 6331402Sache#endif 6341402Sache}; 6351402Sache 6361402Sache} // namespace mca 6371402Sache} // namespace llvm 6381402Sache 6391402Sache#endif // LLVM_MCA_INSTRUCTION_H 640652Sjkh