10b57cec5SDimitry Andric //===--------------------- Instruction.h ------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// 100b57cec5SDimitry Andric /// This file defines abstractions used by the Pipeline to model register reads, 110b57cec5SDimitry Andric /// register writes and instructions. 120b57cec5SDimitry Andric /// 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #ifndef LLVM_MCA_INSTRUCTION_H 160b57cec5SDimitry Andric #define LLVM_MCA_INSTRUCTION_H 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 190b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 218bcb0991SDimitry Andric #include "llvm/MC/MCRegister.h" // definition of MCPhysReg. 220b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric #ifndef NDEBUG 250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 260b57cec5SDimitry Andric #endif 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric #include <memory> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace llvm { 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric namespace mca { 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric constexpr int UNKNOWN_CYCLES = -512; 350b57cec5SDimitry Andric 36fe6060f1SDimitry Andric /// A representation of an mca::Instruction operand 37fe6060f1SDimitry Andric /// for use in mca::CustomBehaviour. 38fe6060f1SDimitry Andric class MCAOperand { 39fe6060f1SDimitry Andric // This class is mostly copied from MCOperand within 40fe6060f1SDimitry Andric // MCInst.h except that we don't keep track of 41fe6060f1SDimitry Andric // expressions or sub-instructions. 42fe6060f1SDimitry Andric enum MCAOperandType : unsigned char { 43fe6060f1SDimitry Andric kInvalid, ///< Uninitialized, Relocatable immediate, or Sub-instruction. 44fe6060f1SDimitry Andric kRegister, ///< Register operand. 45fe6060f1SDimitry Andric kImmediate, ///< Immediate operand. 46fe6060f1SDimitry Andric kSFPImmediate, ///< Single-floating-point immediate operand. 47fe6060f1SDimitry Andric kDFPImmediate, ///< Double-Floating-point immediate operand. 48fe6060f1SDimitry Andric }; 49349cc55cSDimitry Andric MCAOperandType Kind; 50fe6060f1SDimitry Andric 51fe6060f1SDimitry Andric union { 52fe6060f1SDimitry Andric unsigned RegVal; 53fe6060f1SDimitry Andric int64_t ImmVal; 54fe6060f1SDimitry Andric uint32_t SFPImmVal; 55fe6060f1SDimitry Andric uint64_t FPImmVal; 56fe6060f1SDimitry Andric }; 57fe6060f1SDimitry Andric 58fe6060f1SDimitry Andric // We only store specific operands for specific instructions 59fe6060f1SDimitry Andric // so an instruction's operand 3 may be stored within the list 60fe6060f1SDimitry Andric // of MCAOperand as element 0. This Index attribute keeps track 61fe6060f1SDimitry Andric // of the original index (3 for this example). 62fe6060f1SDimitry Andric unsigned Index; 63fe6060f1SDimitry Andric 64fe6060f1SDimitry Andric public: MCAOperand()65349cc55cSDimitry Andric MCAOperand() : Kind(kInvalid), FPImmVal(), Index() {} 66fe6060f1SDimitry Andric isValid()67fe6060f1SDimitry Andric bool isValid() const { return Kind != kInvalid; } isReg()68fe6060f1SDimitry Andric bool isReg() const { return Kind == kRegister; } isImm()69fe6060f1SDimitry Andric bool isImm() const { return Kind == kImmediate; } isSFPImm()70fe6060f1SDimitry Andric bool isSFPImm() const { return Kind == kSFPImmediate; } isDFPImm()71fe6060f1SDimitry Andric bool isDFPImm() const { return Kind == kDFPImmediate; } 72fe6060f1SDimitry Andric 73fe6060f1SDimitry Andric /// Returns the register number. getReg()74fe6060f1SDimitry Andric unsigned getReg() const { 75fe6060f1SDimitry Andric assert(isReg() && "This is not a register operand!"); 76fe6060f1SDimitry Andric return RegVal; 77fe6060f1SDimitry Andric } 78fe6060f1SDimitry Andric getImm()79fe6060f1SDimitry Andric int64_t getImm() const { 80fe6060f1SDimitry Andric assert(isImm() && "This is not an immediate"); 81fe6060f1SDimitry Andric return ImmVal; 82fe6060f1SDimitry Andric } 83fe6060f1SDimitry Andric getSFPImm()84fe6060f1SDimitry Andric uint32_t getSFPImm() const { 85fe6060f1SDimitry Andric assert(isSFPImm() && "This is not an SFP immediate"); 86fe6060f1SDimitry Andric return SFPImmVal; 87fe6060f1SDimitry Andric } 88fe6060f1SDimitry Andric getDFPImm()89fe6060f1SDimitry Andric uint64_t getDFPImm() const { 90fe6060f1SDimitry Andric assert(isDFPImm() && "This is not an FP immediate"); 91fe6060f1SDimitry Andric return FPImmVal; 92fe6060f1SDimitry Andric } 93fe6060f1SDimitry Andric setIndex(const unsigned Idx)94fe6060f1SDimitry Andric void setIndex(const unsigned Idx) { Index = Idx; } 95fe6060f1SDimitry Andric getIndex()96fe6060f1SDimitry Andric unsigned getIndex() const { return Index; } 97fe6060f1SDimitry Andric createReg(unsigned Reg)98fe6060f1SDimitry Andric static MCAOperand createReg(unsigned Reg) { 99fe6060f1SDimitry Andric MCAOperand Op; 100fe6060f1SDimitry Andric Op.Kind = kRegister; 101fe6060f1SDimitry Andric Op.RegVal = Reg; 102fe6060f1SDimitry Andric return Op; 103fe6060f1SDimitry Andric } 104fe6060f1SDimitry Andric createImm(int64_t Val)105fe6060f1SDimitry Andric static MCAOperand createImm(int64_t Val) { 106fe6060f1SDimitry Andric MCAOperand Op; 107fe6060f1SDimitry Andric Op.Kind = kImmediate; 108fe6060f1SDimitry Andric Op.ImmVal = Val; 109fe6060f1SDimitry Andric return Op; 110fe6060f1SDimitry Andric } 111fe6060f1SDimitry Andric createSFPImm(uint32_t Val)112fe6060f1SDimitry Andric static MCAOperand createSFPImm(uint32_t Val) { 113fe6060f1SDimitry Andric MCAOperand Op; 114fe6060f1SDimitry Andric Op.Kind = kSFPImmediate; 115fe6060f1SDimitry Andric Op.SFPImmVal = Val; 116fe6060f1SDimitry Andric return Op; 117fe6060f1SDimitry Andric } 118fe6060f1SDimitry Andric createDFPImm(uint64_t Val)119fe6060f1SDimitry Andric static MCAOperand createDFPImm(uint64_t Val) { 120fe6060f1SDimitry Andric MCAOperand Op; 121fe6060f1SDimitry Andric Op.Kind = kDFPImmediate; 122fe6060f1SDimitry Andric Op.FPImmVal = Val; 123fe6060f1SDimitry Andric return Op; 124fe6060f1SDimitry Andric } 125fe6060f1SDimitry Andric createInvalid()126fe6060f1SDimitry Andric static MCAOperand createInvalid() { 127fe6060f1SDimitry Andric MCAOperand Op; 128fe6060f1SDimitry Andric Op.Kind = kInvalid; 129fe6060f1SDimitry Andric Op.FPImmVal = 0; 130fe6060f1SDimitry Andric return Op; 131fe6060f1SDimitry Andric } 132fe6060f1SDimitry Andric }; 133fe6060f1SDimitry Andric 1340b57cec5SDimitry Andric /// A register write descriptor. 1350b57cec5SDimitry Andric struct WriteDescriptor { 1360b57cec5SDimitry Andric // Operand index. The index is negative for implicit writes only. 1370b57cec5SDimitry Andric // For implicit writes, the actual operand index is computed performing 1380b57cec5SDimitry Andric // a bitwise not of the OpIndex. 1390b57cec5SDimitry Andric int OpIndex; 1400b57cec5SDimitry Andric // Write latency. Number of cycles before write-back stage. 1410b57cec5SDimitry Andric unsigned Latency; 1420b57cec5SDimitry Andric // This field is set to a value different than zero only if this 1430b57cec5SDimitry Andric // is an implicit definition. 1448bcb0991SDimitry Andric MCPhysReg RegisterID; 1450b57cec5SDimitry Andric // Instruction itineraries would set this field to the SchedClass ID. 1460b57cec5SDimitry Andric // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry 1470b57cec5SDimitry Andric // element associated to this write. 1480b57cec5SDimitry Andric // When computing read latencies, this value is matched against the 1490b57cec5SDimitry Andric // "ReadAdvance" information. The hardware backend may implement 1500b57cec5SDimitry Andric // dedicated forwarding paths to quickly propagate write results to dependent 1510b57cec5SDimitry Andric // instructions waiting in the reservation station (effectively bypassing the 1520b57cec5SDimitry Andric // write-back stage). 1530b57cec5SDimitry Andric unsigned SClassOrWriteResourceID; 1540b57cec5SDimitry Andric // True only if this is a write obtained from an optional definition. 1550b57cec5SDimitry Andric // Optional definitions are allowed to reference regID zero (i.e. "no 1560b57cec5SDimitry Andric // register"). 1570b57cec5SDimitry Andric bool IsOptionalDef; 1580b57cec5SDimitry Andric isImplicitWriteWriteDescriptor1590b57cec5SDimitry Andric bool isImplicitWrite() const { return OpIndex < 0; }; 1600b57cec5SDimitry Andric }; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric /// A register read descriptor. 1630b57cec5SDimitry Andric struct ReadDescriptor { 1640b57cec5SDimitry Andric // A MCOperand index. This is used by the Dispatch logic to identify register 1650b57cec5SDimitry Andric // reads. Implicit reads have negative indices. The actual operand index of an 1660b57cec5SDimitry Andric // implicit read is the bitwise not of field OpIndex. 1670b57cec5SDimitry Andric int OpIndex; 1680b57cec5SDimitry Andric // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit 1690b57cec5SDimitry Andric // uses always come first in the sequence of uses. 1700b57cec5SDimitry Andric unsigned UseIndex; 1710b57cec5SDimitry Andric // This field is only set if this is an implicit read. 1728bcb0991SDimitry Andric MCPhysReg RegisterID; 1730b57cec5SDimitry Andric // Scheduling Class Index. It is used to query the scheduling model for the 1740b57cec5SDimitry Andric // MCSchedClassDesc object. 1750b57cec5SDimitry Andric unsigned SchedClassID; 1760b57cec5SDimitry Andric isImplicitReadReadDescriptor1770b57cec5SDimitry Andric bool isImplicitRead() const { return OpIndex < 0; }; 1780b57cec5SDimitry Andric }; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric class ReadState; 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric /// A critical data dependency descriptor. 1830b57cec5SDimitry Andric /// 1840b57cec5SDimitry Andric /// Field RegID is set to the invalid register for memory dependencies. 1850b57cec5SDimitry Andric struct CriticalDependency { 1860b57cec5SDimitry Andric unsigned IID; 1878bcb0991SDimitry Andric MCPhysReg RegID; 1880b57cec5SDimitry Andric unsigned Cycles; 1890b57cec5SDimitry Andric }; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric /// Tracks uses of a register definition (e.g. register write). 1920b57cec5SDimitry Andric /// 1930b57cec5SDimitry Andric /// Each implicit/explicit register write is associated with an instance of 1940b57cec5SDimitry Andric /// this class. A WriteState object tracks the dependent users of a 1950b57cec5SDimitry Andric /// register write. It also tracks how many cycles are left before the write 1960b57cec5SDimitry Andric /// back stage. 1970b57cec5SDimitry Andric class WriteState { 1980b57cec5SDimitry Andric const WriteDescriptor *WD; 1990b57cec5SDimitry Andric // On instruction issue, this field is set equal to the write latency. 2000b57cec5SDimitry Andric // Before instruction issue, this field defaults to -512, a special 2010b57cec5SDimitry Andric // value that represents an "unknown" number of cycles. 2020b57cec5SDimitry Andric int CyclesLeft; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric // Actual register defined by this write. This field is only used 2050b57cec5SDimitry Andric // to speedup queries on the register file. 2060b57cec5SDimitry Andric // For implicit writes, this field always matches the value of 2070b57cec5SDimitry Andric // field RegisterID from WD. 2088bcb0991SDimitry Andric MCPhysReg RegisterID; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric // Physical register file that serves register RegisterID. 2110b57cec5SDimitry Andric unsigned PRFID; 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric // True if this write implicitly clears the upper portion of RegisterID's 2140b57cec5SDimitry Andric // super-registers. 2150b57cec5SDimitry Andric bool ClearsSuperRegs; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric // True if this write is from a dependency breaking zero-idiom instruction. 2180b57cec5SDimitry Andric bool WritesZero; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric // True if this write has been eliminated at register renaming stage. 2210b57cec5SDimitry Andric // Example: a register move doesn't consume scheduler/pipleline resources if 2220b57cec5SDimitry Andric // it is eliminated at register renaming stage. It still consumes 2230b57cec5SDimitry Andric // decode bandwidth, and ROB entries. 2240b57cec5SDimitry Andric bool IsEliminated; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric // This field is set if this is a partial register write, and it has a false 2270b57cec5SDimitry Andric // dependency on any previous write of the same register (or a portion of it). 2280b57cec5SDimitry Andric // DependentWrite must be able to complete before this write completes, so 2290b57cec5SDimitry Andric // that we don't break the WAW, and the two writes can be merged together. 2300b57cec5SDimitry Andric const WriteState *DependentWrite; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric // A partial write that is in a false dependency with this write. 2330b57cec5SDimitry Andric WriteState *PartialWrite; 2340b57cec5SDimitry Andric unsigned DependentWriteCyclesLeft; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric // Critical register dependency for this write. 2370b57cec5SDimitry Andric CriticalDependency CRD; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric // A list of dependent reads. Users is a set of dependent 2400b57cec5SDimitry Andric // reads. A dependent read is added to the set only if CyclesLeft 2410b57cec5SDimitry Andric // is "unknown". As soon as CyclesLeft is 'known', each user in the set 2420b57cec5SDimitry Andric // gets notified with the actual CyclesLeft. 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric // The 'second' element of a pair is a "ReadAdvance" number of cycles. 2450b57cec5SDimitry Andric SmallVector<std::pair<ReadState *, int>, 4> Users; 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric public: 2488bcb0991SDimitry Andric WriteState(const WriteDescriptor &Desc, MCPhysReg RegID, 2490b57cec5SDimitry Andric bool clearsSuperRegs = false, bool writesZero = false) 2500b57cec5SDimitry Andric : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0), 2510b57cec5SDimitry Andric ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero), 2520b57cec5SDimitry Andric IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr), 2530b57cec5SDimitry Andric DependentWriteCyclesLeft(0), CRD() {} 2540b57cec5SDimitry Andric 2550b57cec5SDimitry Andric WriteState(const WriteState &Other) = default; 2560b57cec5SDimitry Andric WriteState &operator=(const WriteState &Other) = default; 2570b57cec5SDimitry Andric getCyclesLeft()2580b57cec5SDimitry Andric int getCyclesLeft() const { return CyclesLeft; } getWriteResourceID()2590b57cec5SDimitry Andric unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; } getRegisterID()2608bcb0991SDimitry Andric MCPhysReg getRegisterID() const { return RegisterID; } setRegisterID(const MCPhysReg RegID)261fe6060f1SDimitry Andric void setRegisterID(const MCPhysReg RegID) { RegisterID = RegID; } getRegisterFileID()2620b57cec5SDimitry Andric unsigned getRegisterFileID() const { return PRFID; } getLatency()2630b57cec5SDimitry Andric unsigned getLatency() const { return WD->Latency; } getDependentWriteCyclesLeft()2640b57cec5SDimitry Andric unsigned getDependentWriteCyclesLeft() const { 2650b57cec5SDimitry Andric return DependentWriteCyclesLeft; 2660b57cec5SDimitry Andric } getDependentWrite()2670b57cec5SDimitry Andric const WriteState *getDependentWrite() const { return DependentWrite; } getCriticalRegDep()2680b57cec5SDimitry Andric const CriticalDependency &getCriticalRegDep() const { return CRD; } 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric // This method adds Use to the set of data dependent reads. IID is the 2710b57cec5SDimitry Andric // instruction identifier associated with this write. ReadAdvance is the 2720b57cec5SDimitry Andric // number of cycles to subtract from the latency of this data dependency. 2730b57cec5SDimitry Andric // Use is in a RAW dependency with this write. 2740b57cec5SDimitry Andric void addUser(unsigned IID, ReadState *Use, int ReadAdvance); 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric // Use is a younger register write that is in a false dependency with this 2770b57cec5SDimitry Andric // write. IID is the instruction identifier associated with this write. 2780b57cec5SDimitry Andric void addUser(unsigned IID, WriteState *Use); 2790b57cec5SDimitry Andric getNumUsers()2800b57cec5SDimitry Andric unsigned getNumUsers() const { 2810b57cec5SDimitry Andric unsigned NumUsers = Users.size(); 2820b57cec5SDimitry Andric if (PartialWrite) 2830b57cec5SDimitry Andric ++NumUsers; 2840b57cec5SDimitry Andric return NumUsers; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric clearsSuperRegisters()2870b57cec5SDimitry Andric bool clearsSuperRegisters() const { return ClearsSuperRegs; } isWriteZero()2880b57cec5SDimitry Andric bool isWriteZero() const { return WritesZero; } isEliminated()2890b57cec5SDimitry Andric bool isEliminated() const { return IsEliminated; } 2900b57cec5SDimitry Andric isReady()2910b57cec5SDimitry Andric bool isReady() const { 2920b57cec5SDimitry Andric if (DependentWrite) 2930b57cec5SDimitry Andric return false; 2940b57cec5SDimitry Andric unsigned CyclesLeft = getDependentWriteCyclesLeft(); 2950b57cec5SDimitry Andric return !CyclesLeft || CyclesLeft < getLatency(); 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric isExecuted()2980b57cec5SDimitry Andric bool isExecuted() const { 2990b57cec5SDimitry Andric return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric setDependentWrite(const WriteState * Other)3020b57cec5SDimitry Andric void setDependentWrite(const WriteState *Other) { DependentWrite = Other; } 3038bcb0991SDimitry Andric void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles); setWriteZero()3040b57cec5SDimitry Andric void setWriteZero() { WritesZero = true; } setEliminated()3050b57cec5SDimitry Andric void setEliminated() { 3060b57cec5SDimitry Andric assert(Users.empty() && "Write is in an inconsistent state."); 3070b57cec5SDimitry Andric CyclesLeft = 0; 3080b57cec5SDimitry Andric IsEliminated = true; 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric setPRF(unsigned PRF)3110b57cec5SDimitry Andric void setPRF(unsigned PRF) { PRFID = PRF; } 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric // On every cycle, update CyclesLeft and notify dependent users. 3140b57cec5SDimitry Andric void cycleEvent(); 3150b57cec5SDimitry Andric void onInstructionIssued(unsigned IID); 3160b57cec5SDimitry Andric 3170b57cec5SDimitry Andric #ifndef NDEBUG 3180b57cec5SDimitry Andric void dump() const; 3190b57cec5SDimitry Andric #endif 3200b57cec5SDimitry Andric }; 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric /// Tracks register operand latency in cycles. 3230b57cec5SDimitry Andric /// 3240b57cec5SDimitry Andric /// A read may be dependent on more than one write. This occurs when some 3250b57cec5SDimitry Andric /// writes only partially update the register associated to this read. 3260b57cec5SDimitry Andric class ReadState { 3270b57cec5SDimitry Andric const ReadDescriptor *RD; 3280b57cec5SDimitry Andric // Physical register identified associated to this read. 3298bcb0991SDimitry Andric MCPhysReg RegisterID; 3300b57cec5SDimitry Andric // Physical register file that serves register RegisterID. 3310b57cec5SDimitry Andric unsigned PRFID; 3320b57cec5SDimitry Andric // Number of writes that contribute to the definition of RegisterID. 3330b57cec5SDimitry Andric // In the absence of partial register updates, the number of DependentWrites 3340b57cec5SDimitry Andric // cannot be more than one. 3350b57cec5SDimitry Andric unsigned DependentWrites; 3360b57cec5SDimitry Andric // Number of cycles left before RegisterID can be read. This value depends on 3370b57cec5SDimitry Andric // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES. 3380b57cec5SDimitry Andric // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of 3390b57cec5SDimitry Andric // every dependent write is known. 3400b57cec5SDimitry Andric int CyclesLeft; 3410b57cec5SDimitry Andric // This field is updated on every writeStartEvent(). When the number of 3420b57cec5SDimitry Andric // dependent writes (i.e. field DependentWrite) is zero, this value is 3430b57cec5SDimitry Andric // propagated to field CyclesLeft. 3440b57cec5SDimitry Andric unsigned TotalCycles; 3450b57cec5SDimitry Andric // Longest register dependency. 3460b57cec5SDimitry Andric CriticalDependency CRD; 3470b57cec5SDimitry Andric // This field is set to true only if there are no dependent writes, and 3480b57cec5SDimitry Andric // there are no `CyclesLeft' to wait. 3490b57cec5SDimitry Andric bool IsReady; 3500b57cec5SDimitry Andric // True if this is a read from a known zero register. 3510b57cec5SDimitry Andric bool IsZero; 3520b57cec5SDimitry Andric // True if this register read is from a dependency-breaking instruction. 3530b57cec5SDimitry Andric bool IndependentFromDef; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric public: ReadState(const ReadDescriptor & Desc,MCPhysReg RegID)3568bcb0991SDimitry Andric ReadState(const ReadDescriptor &Desc, MCPhysReg RegID) 3570b57cec5SDimitry Andric : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0), 3580b57cec5SDimitry Andric CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true), 3590b57cec5SDimitry Andric IsZero(false), IndependentFromDef(false) {} 3600b57cec5SDimitry Andric getDescriptor()3610b57cec5SDimitry Andric const ReadDescriptor &getDescriptor() const { return *RD; } getSchedClass()3620b57cec5SDimitry Andric unsigned getSchedClass() const { return RD->SchedClassID; } getRegisterID()3638bcb0991SDimitry Andric MCPhysReg getRegisterID() const { return RegisterID; } getRegisterFileID()3640b57cec5SDimitry Andric unsigned getRegisterFileID() const { return PRFID; } getCriticalRegDep()3650b57cec5SDimitry Andric const CriticalDependency &getCriticalRegDep() const { return CRD; } 3660b57cec5SDimitry Andric isPending()3670b57cec5SDimitry Andric bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; } isReady()3680b57cec5SDimitry Andric bool isReady() const { return IsReady; } isImplicitRead()3690b57cec5SDimitry Andric bool isImplicitRead() const { return RD->isImplicitRead(); } 3700b57cec5SDimitry Andric isIndependentFromDef()3710b57cec5SDimitry Andric bool isIndependentFromDef() const { return IndependentFromDef; } setIndependentFromDef()3720b57cec5SDimitry Andric void setIndependentFromDef() { IndependentFromDef = true; } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric void cycleEvent(); 3758bcb0991SDimitry Andric void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles); setDependentWrites(unsigned Writes)3760b57cec5SDimitry Andric void setDependentWrites(unsigned Writes) { 3770b57cec5SDimitry Andric DependentWrites = Writes; 3780b57cec5SDimitry Andric IsReady = !Writes; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric isReadZero()3810b57cec5SDimitry Andric bool isReadZero() const { return IsZero; } setReadZero()3820b57cec5SDimitry Andric void setReadZero() { IsZero = true; } setPRF(unsigned ID)3830b57cec5SDimitry Andric void setPRF(unsigned ID) { PRFID = ID; } 3840b57cec5SDimitry Andric }; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric /// A sequence of cycles. 3870b57cec5SDimitry Andric /// 3880b57cec5SDimitry Andric /// This class can be used as a building block to construct ranges of cycles. 3890b57cec5SDimitry Andric class CycleSegment { 3900b57cec5SDimitry Andric unsigned Begin; // Inclusive. 3910b57cec5SDimitry Andric unsigned End; // Exclusive. 3920b57cec5SDimitry Andric bool Reserved; // Resources associated to this segment must be reserved. 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric public: 3950b57cec5SDimitry Andric CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false) Begin(StartCycle)3960b57cec5SDimitry Andric : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {} 3970b57cec5SDimitry Andric contains(unsigned Cycle)3980b57cec5SDimitry Andric bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; } startsAfter(const CycleSegment & CS)3990b57cec5SDimitry Andric bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; } endsBefore(const CycleSegment & CS)4000b57cec5SDimitry Andric bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; } overlaps(const CycleSegment & CS)4010b57cec5SDimitry Andric bool overlaps(const CycleSegment &CS) const { 4020b57cec5SDimitry Andric return !startsAfter(CS) && !endsBefore(CS); 4030b57cec5SDimitry Andric } isExecuting()4040b57cec5SDimitry Andric bool isExecuting() const { return Begin == 0 && End != 0; } isExecuted()4050b57cec5SDimitry Andric bool isExecuted() const { return End == 0; } 4060b57cec5SDimitry Andric bool operator<(const CycleSegment &Other) const { 4070b57cec5SDimitry Andric return Begin < Other.Begin; 4080b57cec5SDimitry Andric } 40904eeddc0SDimitry Andric CycleSegment &operator--() { 4100b57cec5SDimitry Andric if (Begin) 4110b57cec5SDimitry Andric Begin--; 4120b57cec5SDimitry Andric if (End) 4130b57cec5SDimitry Andric End--; 4140b57cec5SDimitry Andric return *this; 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric isValid()4170b57cec5SDimitry Andric bool isValid() const { return Begin <= End; } size()4180b57cec5SDimitry Andric unsigned size() const { return End - Begin; }; subtract(unsigned Cycles)4190b57cec5SDimitry Andric void subtract(unsigned Cycles) { 4200b57cec5SDimitry Andric assert(End >= Cycles); 4210b57cec5SDimitry Andric End -= Cycles; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric begin()4240b57cec5SDimitry Andric unsigned begin() const { return Begin; } end()4250b57cec5SDimitry Andric unsigned end() const { return End; } setEnd(unsigned NewEnd)4260b57cec5SDimitry Andric void setEnd(unsigned NewEnd) { End = NewEnd; } isReserved()4270b57cec5SDimitry Andric bool isReserved() const { return Reserved; } setReserved()4280b57cec5SDimitry Andric void setReserved() { Reserved = true; } 4290b57cec5SDimitry Andric }; 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric /// Helper used by class InstrDesc to describe how hardware resources 4320b57cec5SDimitry Andric /// are used. 4330b57cec5SDimitry Andric /// 4340b57cec5SDimitry Andric /// This class describes how many resource units of a specific resource kind 4350b57cec5SDimitry Andric /// (and how many cycles) are "used" by an instruction. 4360b57cec5SDimitry Andric struct ResourceUsage { 4370b57cec5SDimitry Andric CycleSegment CS; 4380b57cec5SDimitry Andric unsigned NumUnits; 4390b57cec5SDimitry Andric ResourceUsage(CycleSegment Cycles, unsigned Units = 1) CSResourceUsage4400b57cec5SDimitry Andric : CS(Cycles), NumUnits(Units) {} sizeResourceUsage4410b57cec5SDimitry Andric unsigned size() const { return CS.size(); } isReservedResourceUsage4420b57cec5SDimitry Andric bool isReserved() const { return CS.isReserved(); } setReservedResourceUsage4430b57cec5SDimitry Andric void setReserved() { CS.setReserved(); } 4440b57cec5SDimitry Andric }; 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric /// An instruction descriptor 4470b57cec5SDimitry Andric struct InstrDesc { 448fe6060f1SDimitry Andric SmallVector<WriteDescriptor, 2> Writes; // Implicit writes are at the end. 4490b57cec5SDimitry Andric SmallVector<ReadDescriptor, 4> Reads; // Implicit reads are at the end. 4500b57cec5SDimitry Andric 4510b57cec5SDimitry Andric // For every resource used by an instruction of this kind, this vector 4520b57cec5SDimitry Andric // reports the number of "consumed cycles". 4530b57cec5SDimitry Andric SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Resources; 4540b57cec5SDimitry Andric 4558bcb0991SDimitry Andric // A bitmask of used hardware buffers. 4568bcb0991SDimitry Andric uint64_t UsedBuffers; 4570b57cec5SDimitry Andric 4588bcb0991SDimitry Andric // A bitmask of used processor resource units. 4598bcb0991SDimitry Andric uint64_t UsedProcResUnits; 4608bcb0991SDimitry Andric 4618bcb0991SDimitry Andric // A bitmask of used processor resource groups. 4628bcb0991SDimitry Andric uint64_t UsedProcResGroups; 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric unsigned MaxLatency; 4650b57cec5SDimitry Andric // Number of MicroOps for this instruction. 4660b57cec5SDimitry Andric unsigned NumMicroOps; 4670b57cec5SDimitry Andric // SchedClassID used to construct this InstrDesc. 4680b57cec5SDimitry Andric // This information is currently used by views to do fast queries on the 4690b57cec5SDimitry Andric // subtarget when computing the reciprocal throughput. 4700b57cec5SDimitry Andric unsigned SchedClassID; 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric // True if all buffered resources are in-order, and there is at least one 4730b57cec5SDimitry Andric // buffer which is a dispatch hazard (BufferSize = 0). 474fe6060f1SDimitry Andric unsigned MustIssueImmediately : 1; 4750b57cec5SDimitry Andric 47681ad6265SDimitry Andric // True if the corresponding mca::Instruction can be recycled. Currently only 47781ad6265SDimitry Andric // instructions that are neither variadic nor have any variant can be 47881ad6265SDimitry Andric // recycled. 47981ad6265SDimitry Andric unsigned IsRecyclable : 1; 48081ad6265SDimitry Andric 481*bdd1243dSDimitry Andric // True if some of the consumed group resources are partially overlapping. 482*bdd1243dSDimitry Andric unsigned HasPartiallyOverlappingGroups : 1; 483*bdd1243dSDimitry Andric 4840b57cec5SDimitry Andric // A zero latency instruction doesn't consume any scheduler resources. isZeroLatencyInstrDesc4850b57cec5SDimitry Andric bool isZeroLatency() const { return !MaxLatency && Resources.empty(); } 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric InstrDesc() = default; 4880b57cec5SDimitry Andric InstrDesc(const InstrDesc &Other) = delete; 4890b57cec5SDimitry Andric InstrDesc &operator=(const InstrDesc &Other) = delete; 4900b57cec5SDimitry Andric }; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric /// Base class for instructions consumed by the simulation pipeline. 4930b57cec5SDimitry Andric /// 4940b57cec5SDimitry Andric /// This class tracks data dependencies as well as generic properties 4950b57cec5SDimitry Andric /// of the instruction. 4960b57cec5SDimitry Andric class InstructionBase { 4970b57cec5SDimitry Andric const InstrDesc &Desc; 4980b57cec5SDimitry Andric 4990b57cec5SDimitry Andric // This field is set for instructions that are candidates for move 5000b57cec5SDimitry Andric // elimination. For more information about move elimination, see the 5010b57cec5SDimitry Andric // definition of RegisterMappingTracker in RegisterFile.h 5020b57cec5SDimitry Andric bool IsOptimizableMove; 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric // Output dependencies. 5050b57cec5SDimitry Andric // One entry per each implicit and explicit register definition. 506fe6060f1SDimitry Andric SmallVector<WriteState, 2> Defs; 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric // Input dependencies. 5090b57cec5SDimitry Andric // One entry per each implicit and explicit register use. 5100b57cec5SDimitry Andric SmallVector<ReadState, 4> Uses; 5110b57cec5SDimitry Andric 512fe6060f1SDimitry Andric // List of operands which can be used by mca::CustomBehaviour 513fe6060f1SDimitry Andric std::vector<MCAOperand> Operands; 514fe6060f1SDimitry Andric 515fe6060f1SDimitry Andric // Instruction opcode which can be used by mca::CustomBehaviour 516fe6060f1SDimitry Andric unsigned Opcode; 517fe6060f1SDimitry Andric 51804eeddc0SDimitry Andric // Flags used by the LSUnit. 51981ad6265SDimitry Andric bool IsALoadBarrier : 1; 52081ad6265SDimitry Andric bool IsAStoreBarrier : 1; 52181ad6265SDimitry Andric // Flags copied from the InstrDesc and potentially modified by 52281ad6265SDimitry Andric // CustomBehaviour or (more likely) InstrPostProcess. 52381ad6265SDimitry Andric bool MayLoad : 1; 52481ad6265SDimitry Andric bool MayStore : 1; 52581ad6265SDimitry Andric bool HasSideEffects : 1; 52681ad6265SDimitry Andric bool BeginGroup : 1; 52781ad6265SDimitry Andric bool EndGroup : 1; 52881ad6265SDimitry Andric bool RetireOOO : 1; 52904eeddc0SDimitry Andric 5300b57cec5SDimitry Andric public: InstructionBase(const InstrDesc & D,const unsigned Opcode)531fe6060f1SDimitry Andric InstructionBase(const InstrDesc &D, const unsigned Opcode) 53204eeddc0SDimitry Andric : Desc(D), IsOptimizableMove(false), Operands(0), Opcode(Opcode), 53304eeddc0SDimitry Andric IsALoadBarrier(false), IsAStoreBarrier(false) {} 5340b57cec5SDimitry Andric getDefs()5350b57cec5SDimitry Andric SmallVectorImpl<WriteState> &getDefs() { return Defs; } getDefs()536fe6060f1SDimitry Andric ArrayRef<WriteState> getDefs() const { return Defs; } getUses()5370b57cec5SDimitry Andric SmallVectorImpl<ReadState> &getUses() { return Uses; } getUses()538fe6060f1SDimitry Andric ArrayRef<ReadState> getUses() const { return Uses; } getDesc()5390b57cec5SDimitry Andric const InstrDesc &getDesc() const { return Desc; } 5400b57cec5SDimitry Andric getLatency()5410b57cec5SDimitry Andric unsigned getLatency() const { return Desc.MaxLatency; } getNumMicroOps()5428bcb0991SDimitry Andric unsigned getNumMicroOps() const { return Desc.NumMicroOps; } getOpcode()543fe6060f1SDimitry Andric unsigned getOpcode() const { return Opcode; } isALoadBarrier()54404eeddc0SDimitry Andric bool isALoadBarrier() const { return IsALoadBarrier; } isAStoreBarrier()54504eeddc0SDimitry Andric bool isAStoreBarrier() const { return IsAStoreBarrier; } setLoadBarrier(bool IsBarrier)54604eeddc0SDimitry Andric void setLoadBarrier(bool IsBarrier) { IsALoadBarrier = IsBarrier; } setStoreBarrier(bool IsBarrier)54704eeddc0SDimitry Andric void setStoreBarrier(bool IsBarrier) { IsAStoreBarrier = IsBarrier; } 548fe6060f1SDimitry Andric 549fe6060f1SDimitry Andric /// Return the MCAOperand which corresponds to index Idx within the original 550fe6060f1SDimitry Andric /// MCInst. getOperand(const unsigned Idx)551fe6060f1SDimitry Andric const MCAOperand *getOperand(const unsigned Idx) const { 552*bdd1243dSDimitry Andric auto It = llvm::find_if(Operands, [&Idx](const MCAOperand &Op) { 553*bdd1243dSDimitry Andric return Op.getIndex() == Idx; 554*bdd1243dSDimitry Andric }); 555fe6060f1SDimitry Andric if (It == Operands.end()) 556fe6060f1SDimitry Andric return nullptr; 557fe6060f1SDimitry Andric return &(*It); 558fe6060f1SDimitry Andric } getNumOperands()559fe6060f1SDimitry Andric unsigned getNumOperands() const { return Operands.size(); } addOperand(const MCAOperand Op)560fe6060f1SDimitry Andric void addOperand(const MCAOperand Op) { Operands.push_back(Op); } 5610b57cec5SDimitry Andric hasDependentUsers()5620b57cec5SDimitry Andric bool hasDependentUsers() const { 5630b57cec5SDimitry Andric return any_of(Defs, 5640b57cec5SDimitry Andric [](const WriteState &Def) { return Def.getNumUsers() > 0; }); 5650b57cec5SDimitry Andric } 5660b57cec5SDimitry Andric getNumUsers()5670b57cec5SDimitry Andric unsigned getNumUsers() const { 5680b57cec5SDimitry Andric unsigned NumUsers = 0; 5690b57cec5SDimitry Andric for (const WriteState &Def : Defs) 5700b57cec5SDimitry Andric NumUsers += Def.getNumUsers(); 5710b57cec5SDimitry Andric return NumUsers; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric // Returns true if this instruction is a candidate for move elimination. isOptimizableMove()5750b57cec5SDimitry Andric bool isOptimizableMove() const { return IsOptimizableMove; } setOptimizableMove()5760b57cec5SDimitry Andric void setOptimizableMove() { IsOptimizableMove = true; } clearOptimizableMove()57781ad6265SDimitry Andric void clearOptimizableMove() { IsOptimizableMove = false; } isMemOp()57881ad6265SDimitry Andric bool isMemOp() const { return MayLoad || MayStore; } 57981ad6265SDimitry Andric 58081ad6265SDimitry Andric // Getters and setters for general instruction flags. setMayLoad(bool newVal)58181ad6265SDimitry Andric void setMayLoad(bool newVal) { MayLoad = newVal; } setMayStore(bool newVal)58281ad6265SDimitry Andric void setMayStore(bool newVal) { MayStore = newVal; } setHasSideEffects(bool newVal)58381ad6265SDimitry Andric void setHasSideEffects(bool newVal) { HasSideEffects = newVal; } setBeginGroup(bool newVal)58481ad6265SDimitry Andric void setBeginGroup(bool newVal) { BeginGroup = newVal; } setEndGroup(bool newVal)58581ad6265SDimitry Andric void setEndGroup(bool newVal) { EndGroup = newVal; } setRetireOOO(bool newVal)58681ad6265SDimitry Andric void setRetireOOO(bool newVal) { RetireOOO = newVal; } 58781ad6265SDimitry Andric getMayLoad()58881ad6265SDimitry Andric bool getMayLoad() const { return MayLoad; } getMayStore()58981ad6265SDimitry Andric bool getMayStore() const { return MayStore; } getHasSideEffects()59081ad6265SDimitry Andric bool getHasSideEffects() const { return HasSideEffects; } getBeginGroup()59181ad6265SDimitry Andric bool getBeginGroup() const { return BeginGroup; } getEndGroup()59281ad6265SDimitry Andric bool getEndGroup() const { return EndGroup; } getRetireOOO()59381ad6265SDimitry Andric bool getRetireOOO() const { return RetireOOO; } 5940b57cec5SDimitry Andric }; 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric /// An instruction propagated through the simulated instruction pipeline. 5970b57cec5SDimitry Andric /// 5980b57cec5SDimitry Andric /// This class is used to monitor changes to the internal state of instructions 5990b57cec5SDimitry Andric /// that are sent to the various components of the simulated hardware pipeline. 6000b57cec5SDimitry Andric class Instruction : public InstructionBase { 6010b57cec5SDimitry Andric enum InstrStage { 6020b57cec5SDimitry Andric IS_INVALID, // Instruction in an invalid state. 6030b57cec5SDimitry Andric IS_DISPATCHED, // Instruction dispatched but operands are not ready. 6040b57cec5SDimitry Andric IS_PENDING, // Instruction is not ready, but operand latency is known. 6050b57cec5SDimitry Andric IS_READY, // Instruction dispatched and operands ready. 6060b57cec5SDimitry Andric IS_EXECUTING, // Instruction issued. 6070b57cec5SDimitry Andric IS_EXECUTED, // Instruction executed. Values are written back. 6080b57cec5SDimitry Andric IS_RETIRED // Instruction retired. 6090b57cec5SDimitry Andric }; 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric // The current instruction stage. 6120b57cec5SDimitry Andric enum InstrStage Stage; 6130b57cec5SDimitry Andric 6140b57cec5SDimitry Andric // This value defaults to the instruction latency. This instruction is 6150b57cec5SDimitry Andric // considered executed when field CyclesLeft goes to zero. 6160b57cec5SDimitry Andric int CyclesLeft; 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric // Retire Unit token ID for this instruction. 6190b57cec5SDimitry Andric unsigned RCUTokenID; 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric // LS token ID for this instruction. 6220b57cec5SDimitry Andric // This field is set to the invalid null token if this is not a memory 6230b57cec5SDimitry Andric // operation. 6240b57cec5SDimitry Andric unsigned LSUTokenID; 6250b57cec5SDimitry Andric 6268bcb0991SDimitry Andric // A resource mask which identifies buffered resources consumed by this 6278bcb0991SDimitry Andric // instruction at dispatch stage. In the absence of macro-fusion, this value 6288bcb0991SDimitry Andric // should always match the value of field `UsedBuffers` from the instruction 6298bcb0991SDimitry Andric // descriptor (see field InstrBase::Desc). 6308bcb0991SDimitry Andric uint64_t UsedBuffers; 6318bcb0991SDimitry Andric 6320b57cec5SDimitry Andric // Critical register dependency. 6330b57cec5SDimitry Andric CriticalDependency CriticalRegDep; 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric // Critical memory dependency. 6360b57cec5SDimitry Andric CriticalDependency CriticalMemDep; 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric // A bitmask of busy processor resource units. 6390b57cec5SDimitry Andric // This field is set to zero only if execution is not delayed during this 6400b57cec5SDimitry Andric // cycle because of unavailable pipeline resources. 6410b57cec5SDimitry Andric uint64_t CriticalResourceMask; 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric // True if this instruction has been optimized at register renaming stage. 6440b57cec5SDimitry Andric bool IsEliminated; 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric public: Instruction(const InstrDesc & D,const unsigned Opcode)647fe6060f1SDimitry Andric Instruction(const InstrDesc &D, const unsigned Opcode) 648fe6060f1SDimitry Andric : InstructionBase(D, Opcode), Stage(IS_INVALID), 649fe6060f1SDimitry Andric CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0), LSUTokenID(0), 650fe6060f1SDimitry Andric UsedBuffers(D.UsedBuffers), CriticalRegDep(), CriticalMemDep(), 651fe6060f1SDimitry Andric CriticalResourceMask(0), IsEliminated(false) {} 6520b57cec5SDimitry Andric 65381ad6265SDimitry Andric void reset(); 65481ad6265SDimitry Andric getRCUTokenID()6550b57cec5SDimitry Andric unsigned getRCUTokenID() const { return RCUTokenID; } getLSUTokenID()6560b57cec5SDimitry Andric unsigned getLSUTokenID() const { return LSUTokenID; } setLSUTokenID(unsigned LSUTok)6570b57cec5SDimitry Andric void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; } 6588bcb0991SDimitry Andric getUsedBuffers()6598bcb0991SDimitry Andric uint64_t getUsedBuffers() const { return UsedBuffers; } setUsedBuffers(uint64_t Mask)6608bcb0991SDimitry Andric void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; } clearUsedBuffers()6618bcb0991SDimitry Andric void clearUsedBuffers() { UsedBuffers = 0ULL; } 6628bcb0991SDimitry Andric getCyclesLeft()6630b57cec5SDimitry Andric int getCyclesLeft() const { return CyclesLeft; } 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric // Transition to the dispatch stage, and assign a RCUToken to this 6660b57cec5SDimitry Andric // instruction. The RCUToken is used to track the completion of every 6670b57cec5SDimitry Andric // register write performed by this instruction. 6680b57cec5SDimitry Andric void dispatch(unsigned RCUTokenID); 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric // Instruction issued. Transition to the IS_EXECUTING state, and update 6710b57cec5SDimitry Andric // all the register definitions. 6720b57cec5SDimitry Andric void execute(unsigned IID); 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric // Force a transition from the IS_DISPATCHED state to the IS_READY or 6750b57cec5SDimitry Andric // IS_PENDING state. State transitions normally occur either at the beginning 6760b57cec5SDimitry Andric // of a new cycle (see method cycleEvent()), or as a result of another issue 6770b57cec5SDimitry Andric // event. This method is called every time the instruction might have changed 6780b57cec5SDimitry Andric // in state. It internally delegates to method updateDispatched() and 6790b57cec5SDimitry Andric // updateWaiting(). 6800b57cec5SDimitry Andric void update(); 6810b57cec5SDimitry Andric bool updateDispatched(); 6820b57cec5SDimitry Andric bool updatePending(); 6830b57cec5SDimitry Andric isInvalid()68481ad6265SDimitry Andric bool isInvalid() const { return Stage == IS_INVALID; } isDispatched()6850b57cec5SDimitry Andric bool isDispatched() const { return Stage == IS_DISPATCHED; } isPending()6860b57cec5SDimitry Andric bool isPending() const { return Stage == IS_PENDING; } isReady()6870b57cec5SDimitry Andric bool isReady() const { return Stage == IS_READY; } isExecuting()6880b57cec5SDimitry Andric bool isExecuting() const { return Stage == IS_EXECUTING; } isExecuted()6890b57cec5SDimitry Andric bool isExecuted() const { return Stage == IS_EXECUTED; } isRetired()6900b57cec5SDimitry Andric bool isRetired() const { return Stage == IS_RETIRED; } isEliminated()6910b57cec5SDimitry Andric bool isEliminated() const { return IsEliminated; } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED. 6940b57cec5SDimitry Andric void forceExecuted(); setEliminated()6950b57cec5SDimitry Andric void setEliminated() { IsEliminated = true; } 6960b57cec5SDimitry Andric retire()6970b57cec5SDimitry Andric void retire() { 6980b57cec5SDimitry Andric assert(isExecuted() && "Instruction is in an invalid state!"); 6990b57cec5SDimitry Andric Stage = IS_RETIRED; 7000b57cec5SDimitry Andric } 7010b57cec5SDimitry Andric getCriticalRegDep()7020b57cec5SDimitry Andric const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; } getCriticalMemDep()7030b57cec5SDimitry Andric const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; } 7040b57cec5SDimitry Andric const CriticalDependency &computeCriticalRegDep(); setCriticalMemDep(const CriticalDependency & MemDep)7050b57cec5SDimitry Andric void setCriticalMemDep(const CriticalDependency &MemDep) { 7060b57cec5SDimitry Andric CriticalMemDep = MemDep; 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric getCriticalResourceMask()7090b57cec5SDimitry Andric uint64_t getCriticalResourceMask() const { return CriticalResourceMask; } setCriticalResourceMask(uint64_t ResourceMask)7100b57cec5SDimitry Andric void setCriticalResourceMask(uint64_t ResourceMask) { 7110b57cec5SDimitry Andric CriticalResourceMask = ResourceMask; 7120b57cec5SDimitry Andric } 7130b57cec5SDimitry Andric 7140b57cec5SDimitry Andric void cycleEvent(); 7150b57cec5SDimitry Andric }; 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric /// An InstRef contains both a SourceMgr index and Instruction pair. The index 7180b57cec5SDimitry Andric /// is used as a unique identifier for the instruction. MCA will make use of 7190b57cec5SDimitry Andric /// this index as a key throughout MCA. 7200b57cec5SDimitry Andric class InstRef { 7210b57cec5SDimitry Andric std::pair<unsigned, Instruction *> Data; 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric public: InstRef()7240b57cec5SDimitry Andric InstRef() : Data(std::make_pair(0, nullptr)) {} InstRef(unsigned Index,Instruction * I)7250b57cec5SDimitry Andric InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {} 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric bool operator==(const InstRef &Other) const { return Data == Other.Data; } 7280b57cec5SDimitry Andric bool operator!=(const InstRef &Other) const { return Data != Other.Data; } 7290b57cec5SDimitry Andric bool operator<(const InstRef &Other) const { 7300b57cec5SDimitry Andric return Data.first < Other.Data.first; 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric getSourceIndex()7330b57cec5SDimitry Andric unsigned getSourceIndex() const { return Data.first; } getInstruction()7340b57cec5SDimitry Andric Instruction *getInstruction() { return Data.second; } getInstruction()7350b57cec5SDimitry Andric const Instruction *getInstruction() const { return Data.second; } 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric /// Returns true if this references a valid instruction. 7380b57cec5SDimitry Andric explicit operator bool() const { return Data.second != nullptr; } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric /// Invalidate this reference. invalidate()7410b57cec5SDimitry Andric void invalidate() { Data.second = nullptr; } 7420b57cec5SDimitry Andric 7430b57cec5SDimitry Andric #ifndef NDEBUG print(raw_ostream & OS)7440b57cec5SDimitry Andric void print(raw_ostream &OS) const { OS << getSourceIndex(); } 7450b57cec5SDimitry Andric #endif 7460b57cec5SDimitry Andric }; 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric #ifndef NDEBUG 7490b57cec5SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) { 7500b57cec5SDimitry Andric IR.print(OS); 7510b57cec5SDimitry Andric return OS; 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric #endif 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric } // namespace mca 7560b57cec5SDimitry Andric } // namespace llvm 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric #endif // LLVM_MCA_INSTRUCTION_H 759