Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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 representation of an mca::Instruction operand
  37. /// for use in mca::CustomBehaviour.
  38. class MCAOperand {
  39.   // This class is mostly copied from MCOperand within
  40.   // MCInst.h except that we don't keep track of
  41.   // expressions or sub-instructions.
  42.   enum MCAOperandType : unsigned char {
  43.     kInvalid,   ///< Uninitialized, Relocatable immediate, or Sub-instruction.
  44.     kRegister,  ///< Register operand.
  45.     kImmediate, ///< Immediate operand.
  46.     kSFPImmediate, ///< Single-floating-point immediate operand.
  47.     kDFPImmediate, ///< Double-Floating-point immediate operand.
  48.   };
  49.   MCAOperandType Kind;
  50.  
  51.   union {
  52.     unsigned RegVal;
  53.     int64_t ImmVal;
  54.     uint32_t SFPImmVal;
  55.     uint64_t FPImmVal;
  56.   };
  57.  
  58.   // We only store specific operands for specific instructions
  59.   // so an instruction's operand 3 may be stored within the list
  60.   // of MCAOperand as element 0. This Index attribute keeps track
  61.   // of the original index (3 for this example).
  62.   unsigned Index;
  63.  
  64. public:
  65.   MCAOperand() : Kind(kInvalid), FPImmVal(), Index() {}
  66.  
  67.   bool isValid() const { return Kind != kInvalid; }
  68.   bool isReg() const { return Kind == kRegister; }
  69.   bool isImm() const { return Kind == kImmediate; }
  70.   bool isSFPImm() const { return Kind == kSFPImmediate; }
  71.   bool isDFPImm() const { return Kind == kDFPImmediate; }
  72.  
  73.   /// Returns the register number.
  74.   unsigned getReg() const {
  75.     assert(isReg() && "This is not a register operand!");
  76.     return RegVal;
  77.   }
  78.  
  79.   int64_t getImm() const {
  80.     assert(isImm() && "This is not an immediate");
  81.     return ImmVal;
  82.   }
  83.  
  84.   uint32_t getSFPImm() const {
  85.     assert(isSFPImm() && "This is not an SFP immediate");
  86.     return SFPImmVal;
  87.   }
  88.  
  89.   uint64_t getDFPImm() const {
  90.     assert(isDFPImm() && "This is not an FP immediate");
  91.     return FPImmVal;
  92.   }
  93.  
  94.   void setIndex(const unsigned Idx) { Index = Idx; }
  95.  
  96.   unsigned getIndex() const { return Index; }
  97.  
  98.   static MCAOperand createReg(unsigned Reg) {
  99.     MCAOperand Op;
  100.     Op.Kind = kRegister;
  101.     Op.RegVal = Reg;
  102.     return Op;
  103.   }
  104.  
  105.   static MCAOperand createImm(int64_t Val) {
  106.     MCAOperand Op;
  107.     Op.Kind = kImmediate;
  108.     Op.ImmVal = Val;
  109.     return Op;
  110.   }
  111.  
  112.   static MCAOperand createSFPImm(uint32_t Val) {
  113.     MCAOperand Op;
  114.     Op.Kind = kSFPImmediate;
  115.     Op.SFPImmVal = Val;
  116.     return Op;
  117.   }
  118.  
  119.   static MCAOperand createDFPImm(uint64_t Val) {
  120.     MCAOperand Op;
  121.     Op.Kind = kDFPImmediate;
  122.     Op.FPImmVal = Val;
  123.     return Op;
  124.   }
  125.  
  126.   static MCAOperand createInvalid() {
  127.     MCAOperand Op;
  128.     Op.Kind = kInvalid;
  129.     Op.FPImmVal = 0;
  130.     return Op;
  131.   }
  132. };
  133.  
  134. /// A register write descriptor.
  135. struct WriteDescriptor {
  136.   // Operand index. The index is negative for implicit writes only.
  137.   // For implicit writes, the actual operand index is computed performing
  138.   // a bitwise not of the OpIndex.
  139.   int OpIndex;
  140.   // Write latency. Number of cycles before write-back stage.
  141.   unsigned Latency;
  142.   // This field is set to a value different than zero only if this
  143.   // is an implicit definition.
  144.   MCPhysReg RegisterID;
  145.   // Instruction itineraries would set this field to the SchedClass ID.
  146.   // Otherwise, it defaults to the WriteResourceID from the MCWriteLatencyEntry
  147.   // element associated to this write.
  148.   // When computing read latencies, this value is matched against the
  149.   // "ReadAdvance" information. The hardware backend may implement
  150.   // dedicated forwarding paths to quickly propagate write results to dependent
  151.   // instructions waiting in the reservation station (effectively bypassing the
  152.   // write-back stage).
  153.   unsigned SClassOrWriteResourceID;
  154.   // True only if this is a write obtained from an optional definition.
  155.   // Optional definitions are allowed to reference regID zero (i.e. "no
  156.   // register").
  157.   bool IsOptionalDef;
  158.  
  159.   bool isImplicitWrite() const { return OpIndex < 0; };
  160. };
  161.  
  162. /// A register read descriptor.
  163. struct ReadDescriptor {
  164.   // A MCOperand index. This is used by the Dispatch logic to identify register
  165.   // reads. Implicit reads have negative indices. The actual operand index of an
  166.   // implicit read is the bitwise not of field OpIndex.
  167.   int OpIndex;
  168.   // The actual "UseIdx". This is used to query the ReadAdvance table. Explicit
  169.   // uses always come first in the sequence of uses.
  170.   unsigned UseIndex;
  171.   // This field is only set if this is an implicit read.
  172.   MCPhysReg RegisterID;
  173.   // Scheduling Class Index. It is used to query the scheduling model for the
  174.   // MCSchedClassDesc object.
  175.   unsigned SchedClassID;
  176.  
  177.   bool isImplicitRead() const { return OpIndex < 0; };
  178. };
  179.  
  180. class ReadState;
  181.  
  182. /// A critical data dependency descriptor.
  183. ///
  184. /// Field RegID is set to the invalid register for memory dependencies.
  185. struct CriticalDependency {
  186.   unsigned IID;
  187.   MCPhysReg RegID;
  188.   unsigned Cycles;
  189. };
  190.  
  191. /// Tracks uses of a register definition (e.g. register write).
  192. ///
  193. /// Each implicit/explicit register write is associated with an instance of
  194. /// this class. A WriteState object tracks the dependent users of a
  195. /// register write. It also tracks how many cycles are left before the write
  196. /// back stage.
  197. class WriteState {
  198.   const WriteDescriptor *WD;
  199.   // On instruction issue, this field is set equal to the write latency.
  200.   // Before instruction issue, this field defaults to -512, a special
  201.   // value that represents an "unknown" number of cycles.
  202.   int CyclesLeft;
  203.  
  204.   // Actual register defined by this write. This field is only used
  205.   // to speedup queries on the register file.
  206.   // For implicit writes, this field always matches the value of
  207.   // field RegisterID from WD.
  208.   MCPhysReg RegisterID;
  209.  
  210.   // Physical register file that serves register RegisterID.
  211.   unsigned PRFID;
  212.  
  213.   // True if this write implicitly clears the upper portion of RegisterID's
  214.   // super-registers.
  215.   bool ClearsSuperRegs;
  216.  
  217.   // True if this write is from a dependency breaking zero-idiom instruction.
  218.   bool WritesZero;
  219.  
  220.   // True if this write has been eliminated at register renaming stage.
  221.   // Example: a register move doesn't consume scheduler/pipleline resources if
  222.   // it is eliminated at register renaming stage. It still consumes
  223.   // decode bandwidth, and ROB entries.
  224.   bool IsEliminated;
  225.  
  226.   // This field is set if this is a partial register write, and it has a false
  227.   // dependency on any previous write of the same register (or a portion of it).
  228.   // DependentWrite must be able to complete before this write completes, so
  229.   // that we don't break the WAW, and the two writes can be merged together.
  230.   const WriteState *DependentWrite;
  231.  
  232.   // A partial write that is in a false dependency with this write.
  233.   WriteState *PartialWrite;
  234.   unsigned DependentWriteCyclesLeft;
  235.  
  236.   // Critical register dependency for this write.
  237.   CriticalDependency CRD;
  238.  
  239.   // A list of dependent reads. Users is a set of dependent
  240.   // reads. A dependent read is added to the set only if CyclesLeft
  241.   // is "unknown". As soon as CyclesLeft is 'known', each user in the set
  242.   // gets notified with the actual CyclesLeft.
  243.  
  244.   // The 'second' element of a pair is a "ReadAdvance" number of cycles.
  245.   SmallVector<std::pair<ReadState *, int>, 4> Users;
  246.  
  247. public:
  248.   WriteState(const WriteDescriptor &Desc, MCPhysReg RegID,
  249.              bool clearsSuperRegs = false, bool writesZero = false)
  250.       : WD(&Desc), CyclesLeft(UNKNOWN_CYCLES), RegisterID(RegID), PRFID(0),
  251.         ClearsSuperRegs(clearsSuperRegs), WritesZero(writesZero),
  252.         IsEliminated(false), DependentWrite(nullptr), PartialWrite(nullptr),
  253.         DependentWriteCyclesLeft(0), CRD() {}
  254.  
  255.   WriteState(const WriteState &Other) = default;
  256.   WriteState &operator=(const WriteState &Other) = default;
  257.  
  258.   int getCyclesLeft() const { return CyclesLeft; }
  259.   unsigned getWriteResourceID() const { return WD->SClassOrWriteResourceID; }
  260.   MCPhysReg getRegisterID() const { return RegisterID; }
  261.   void setRegisterID(const MCPhysReg RegID) { RegisterID = RegID; }
  262.   unsigned getRegisterFileID() const { return PRFID; }
  263.   unsigned getLatency() const { return WD->Latency; }
  264.   unsigned getDependentWriteCyclesLeft() const {
  265.     return DependentWriteCyclesLeft;
  266.   }
  267.   const WriteState *getDependentWrite() const { return DependentWrite; }
  268.   const CriticalDependency &getCriticalRegDep() const { return CRD; }
  269.  
  270.   // This method adds Use to the set of data dependent reads. IID is the
  271.   // instruction identifier associated with this write. ReadAdvance is the
  272.   // number of cycles to subtract from the latency of this data dependency.
  273.   // Use is in a RAW dependency with this write.
  274.   void addUser(unsigned IID, ReadState *Use, int ReadAdvance);
  275.  
  276.   // Use is a younger register write that is in a false dependency with this
  277.   // write. IID is the instruction identifier associated with this write.
  278.   void addUser(unsigned IID, WriteState *Use);
  279.  
  280.   unsigned getNumUsers() const {
  281.     unsigned NumUsers = Users.size();
  282.     if (PartialWrite)
  283.       ++NumUsers;
  284.     return NumUsers;
  285.   }
  286.  
  287.   bool clearsSuperRegisters() const { return ClearsSuperRegs; }
  288.   bool isWriteZero() const { return WritesZero; }
  289.   bool isEliminated() const { return IsEliminated; }
  290.  
  291.   bool isReady() const {
  292.     if (DependentWrite)
  293.       return false;
  294.     unsigned CyclesLeft = getDependentWriteCyclesLeft();
  295.     return !CyclesLeft || CyclesLeft < getLatency();
  296.   }
  297.  
  298.   bool isExecuted() const {
  299.     return CyclesLeft != UNKNOWN_CYCLES && CyclesLeft <= 0;
  300.   }
  301.  
  302.   void setDependentWrite(const WriteState *Other) { DependentWrite = Other; }
  303.   void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
  304.   void setWriteZero() { WritesZero = true; }
  305.   void setEliminated() {
  306.     assert(Users.empty() && "Write is in an inconsistent state.");
  307.     CyclesLeft = 0;
  308.     IsEliminated = true;
  309.   }
  310.  
  311.   void setPRF(unsigned PRF) { PRFID = PRF; }
  312.  
  313.   // On every cycle, update CyclesLeft and notify dependent users.
  314.   void cycleEvent();
  315.   void onInstructionIssued(unsigned IID);
  316.  
  317. #ifndef NDEBUG
  318.   void dump() const;
  319. #endif
  320. };
  321.  
  322. /// Tracks register operand latency in cycles.
  323. ///
  324. /// A read may be dependent on more than one write. This occurs when some
  325. /// writes only partially update the register associated to this read.
  326. class ReadState {
  327.   const ReadDescriptor *RD;
  328.   // Physical register identified associated to this read.
  329.   MCPhysReg RegisterID;
  330.   // Physical register file that serves register RegisterID.
  331.   unsigned PRFID;
  332.   // Number of writes that contribute to the definition of RegisterID.
  333.   // In the absence of partial register updates, the number of DependentWrites
  334.   // cannot be more than one.
  335.   unsigned DependentWrites;
  336.   // Number of cycles left before RegisterID can be read. This value depends on
  337.   // the latency of all the dependent writes. It defaults to UNKNOWN_CYCLES.
  338.   // It gets set to the value of field TotalCycles only when the 'CyclesLeft' of
  339.   // every dependent write is known.
  340.   int CyclesLeft;
  341.   // This field is updated on every writeStartEvent(). When the number of
  342.   // dependent writes (i.e. field DependentWrite) is zero, this value is
  343.   // propagated to field CyclesLeft.
  344.   unsigned TotalCycles;
  345.   // Longest register dependency.
  346.   CriticalDependency CRD;
  347.   // This field is set to true only if there are no dependent writes, and
  348.   // there are no `CyclesLeft' to wait.
  349.   bool IsReady;
  350.   // True if this is a read from a known zero register.
  351.   bool IsZero;
  352.   // True if this register read is from a dependency-breaking instruction.
  353.   bool IndependentFromDef;
  354.  
  355. public:
  356.   ReadState(const ReadDescriptor &Desc, MCPhysReg RegID)
  357.       : RD(&Desc), RegisterID(RegID), PRFID(0), DependentWrites(0),
  358.         CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), CRD(), IsReady(true),
  359.         IsZero(false), IndependentFromDef(false) {}
  360.  
  361.   const ReadDescriptor &getDescriptor() const { return *RD; }
  362.   unsigned getSchedClass() const { return RD->SchedClassID; }
  363.   MCPhysReg getRegisterID() const { return RegisterID; }
  364.   unsigned getRegisterFileID() const { return PRFID; }
  365.   const CriticalDependency &getCriticalRegDep() const { return CRD; }
  366.  
  367.   bool isPending() const { return !IndependentFromDef && CyclesLeft > 0; }
  368.   bool isReady() const { return IsReady; }
  369.   bool isImplicitRead() const { return RD->isImplicitRead(); }
  370.  
  371.   bool isIndependentFromDef() const { return IndependentFromDef; }
  372.   void setIndependentFromDef() { IndependentFromDef = true; }
  373.  
  374.   void cycleEvent();
  375.   void writeStartEvent(unsigned IID, MCPhysReg RegID, unsigned Cycles);
  376.   void setDependentWrites(unsigned Writes) {
  377.     DependentWrites = Writes;
  378.     IsReady = !Writes;
  379.   }
  380.  
  381.   bool isReadZero() const { return IsZero; }
  382.   void setReadZero() { IsZero = true; }
  383.   void setPRF(unsigned ID) { PRFID = ID; }
  384. };
  385.  
  386. /// A sequence of cycles.
  387. ///
  388. /// This class can be used as a building block to construct ranges of cycles.
  389. class CycleSegment {
  390.   unsigned Begin; // Inclusive.
  391.   unsigned End;   // Exclusive.
  392.   bool Reserved;  // Resources associated to this segment must be reserved.
  393.  
  394. public:
  395.   CycleSegment(unsigned StartCycle, unsigned EndCycle, bool IsReserved = false)
  396.       : Begin(StartCycle), End(EndCycle), Reserved(IsReserved) {}
  397.  
  398.   bool contains(unsigned Cycle) const { return Cycle >= Begin && Cycle < End; }
  399.   bool startsAfter(const CycleSegment &CS) const { return End <= CS.Begin; }
  400.   bool endsBefore(const CycleSegment &CS) const { return Begin >= CS.End; }
  401.   bool overlaps(const CycleSegment &CS) const {
  402.     return !startsAfter(CS) && !endsBefore(CS);
  403.   }
  404.   bool isExecuting() const { return Begin == 0 && End != 0; }
  405.   bool isExecuted() const { return End == 0; }
  406.   bool operator<(const CycleSegment &Other) const {
  407.     return Begin < Other.Begin;
  408.   }
  409.   CycleSegment &operator--() {
  410.     if (Begin)
  411.       Begin--;
  412.     if (End)
  413.       End--;
  414.     return *this;
  415.   }
  416.  
  417.   bool isValid() const { return Begin <= End; }
  418.   unsigned size() const { return End - Begin; };
  419.   void subtract(unsigned Cycles) {
  420.     assert(End >= Cycles);
  421.     End -= Cycles;
  422.   }
  423.  
  424.   unsigned begin() const { return Begin; }
  425.   unsigned end() const { return End; }
  426.   void setEnd(unsigned NewEnd) { End = NewEnd; }
  427.   bool isReserved() const { return Reserved; }
  428.   void setReserved() { Reserved = true; }
  429. };
  430.  
  431. /// Helper used by class InstrDesc to describe how hardware resources
  432. /// are used.
  433. ///
  434. /// This class describes how many resource units of a specific resource kind
  435. /// (and how many cycles) are "used" by an instruction.
  436. struct ResourceUsage {
  437.   CycleSegment CS;
  438.   unsigned NumUnits;
  439.   ResourceUsage(CycleSegment Cycles, unsigned Units = 1)
  440.       : CS(Cycles), NumUnits(Units) {}
  441.   unsigned size() const { return CS.size(); }
  442.   bool isReserved() const { return CS.isReserved(); }
  443.   void setReserved() { CS.setReserved(); }
  444. };
  445.  
  446. /// An instruction descriptor
  447. struct InstrDesc {
  448.   SmallVector<WriteDescriptor, 2> Writes; // Implicit writes are at the end.
  449.   SmallVector<ReadDescriptor, 4> Reads;   // Implicit reads are at the end.
  450.  
  451.   // For every resource used by an instruction of this kind, this vector
  452.   // reports the number of "consumed cycles".
  453.   SmallVector<std::pair<uint64_t, ResourceUsage>, 4> Resources;
  454.  
  455.   // A bitmask of used hardware buffers.
  456.   uint64_t UsedBuffers;
  457.  
  458.   // A bitmask of used processor resource units.
  459.   uint64_t UsedProcResUnits;
  460.  
  461.   // A bitmask of used processor resource groups.
  462.   uint64_t UsedProcResGroups;
  463.  
  464.   unsigned MaxLatency;
  465.   // Number of MicroOps for this instruction.
  466.   unsigned NumMicroOps;
  467.   // SchedClassID used to construct this InstrDesc.
  468.   // This information is currently used by views to do fast queries on the
  469.   // subtarget when computing the reciprocal throughput.
  470.   unsigned SchedClassID;
  471.  
  472.   // True if all buffered resources are in-order, and there is at least one
  473.   // buffer which is a dispatch hazard (BufferSize = 0).
  474.   unsigned MustIssueImmediately : 1;
  475.  
  476.   // True if the corresponding mca::Instruction can be recycled. Currently only
  477.   // instructions that are neither variadic nor have any variant can be
  478.   // recycled.
  479.   unsigned IsRecyclable : 1;
  480.  
  481.   // True if some of the consumed group resources are partially overlapping.
  482.   unsigned HasPartiallyOverlappingGroups : 1;
  483.  
  484.   // A zero latency instruction doesn't consume any scheduler resources.
  485.   bool isZeroLatency() const { return !MaxLatency && Resources.empty(); }
  486.  
  487.   InstrDesc() = default;
  488.   InstrDesc(const InstrDesc &Other) = delete;
  489.   InstrDesc &operator=(const InstrDesc &Other) = delete;
  490. };
  491.  
  492. /// Base class for instructions consumed by the simulation pipeline.
  493. ///
  494. /// This class tracks data dependencies as well as generic properties
  495. /// of the instruction.
  496. class InstructionBase {
  497.   const InstrDesc &Desc;
  498.  
  499.   // This field is set for instructions that are candidates for move
  500.   // elimination. For more information about move elimination, see the
  501.   // definition of RegisterMappingTracker in RegisterFile.h
  502.   bool IsOptimizableMove;
  503.  
  504.   // Output dependencies.
  505.   // One entry per each implicit and explicit register definition.
  506.   SmallVector<WriteState, 2> Defs;
  507.  
  508.   // Input dependencies.
  509.   // One entry per each implicit and explicit register use.
  510.   SmallVector<ReadState, 4> Uses;
  511.  
  512.   // List of operands which can be used by mca::CustomBehaviour
  513.   std::vector<MCAOperand> Operands;
  514.  
  515.   // Instruction opcode which can be used by mca::CustomBehaviour
  516.   unsigned Opcode;
  517.  
  518.   // Flags used by the LSUnit.
  519.   bool IsALoadBarrier : 1;
  520.   bool IsAStoreBarrier : 1;
  521.   // Flags copied from the InstrDesc and potentially modified by
  522.   // CustomBehaviour or (more likely) InstrPostProcess.
  523.   bool MayLoad : 1;
  524.   bool MayStore : 1;
  525.   bool HasSideEffects : 1;
  526.   bool BeginGroup : 1;
  527.   bool EndGroup : 1;
  528.   bool RetireOOO : 1;
  529.  
  530. public:
  531.   InstructionBase(const InstrDesc &D, const unsigned Opcode)
  532.       : Desc(D), IsOptimizableMove(false), Operands(0), Opcode(Opcode),
  533.         IsALoadBarrier(false), IsAStoreBarrier(false) {}
  534.  
  535.   SmallVectorImpl<WriteState> &getDefs() { return Defs; }
  536.   ArrayRef<WriteState> getDefs() const { return Defs; }
  537.   SmallVectorImpl<ReadState> &getUses() { return Uses; }
  538.   ArrayRef<ReadState> getUses() const { return Uses; }
  539.   const InstrDesc &getDesc() const { return Desc; }
  540.  
  541.   unsigned getLatency() const { return Desc.MaxLatency; }
  542.   unsigned getNumMicroOps() const { return Desc.NumMicroOps; }
  543.   unsigned getOpcode() const { return Opcode; }
  544.   bool isALoadBarrier() const { return IsALoadBarrier; }
  545.   bool isAStoreBarrier() const { return IsAStoreBarrier; }
  546.   void setLoadBarrier(bool IsBarrier) { IsALoadBarrier = IsBarrier; }
  547.   void setStoreBarrier(bool IsBarrier) { IsAStoreBarrier = IsBarrier; }
  548.  
  549.   /// Return the MCAOperand which corresponds to index Idx within the original
  550.   /// MCInst.
  551.   const MCAOperand *getOperand(const unsigned Idx) const {
  552.     auto It = llvm::find_if(Operands, [&Idx](const MCAOperand &Op) {
  553.       return Op.getIndex() == Idx;
  554.     });
  555.     if (It == Operands.end())
  556.       return nullptr;
  557.     return &(*It);
  558.   }
  559.   unsigned getNumOperands() const { return Operands.size(); }
  560.   void addOperand(const MCAOperand Op) { Operands.push_back(Op); }
  561.  
  562.   bool hasDependentUsers() const {
  563.     return any_of(Defs,
  564.                   [](const WriteState &Def) { return Def.getNumUsers() > 0; });
  565.   }
  566.  
  567.   unsigned getNumUsers() const {
  568.     unsigned NumUsers = 0;
  569.     for (const WriteState &Def : Defs)
  570.       NumUsers += Def.getNumUsers();
  571.     return NumUsers;
  572.   }
  573.  
  574.   // Returns true if this instruction is a candidate for move elimination.
  575.   bool isOptimizableMove() const { return IsOptimizableMove; }
  576.   void setOptimizableMove() { IsOptimizableMove = true; }
  577.   void clearOptimizableMove() { IsOptimizableMove = false; }
  578.   bool isMemOp() const { return MayLoad || MayStore; }
  579.  
  580.   // Getters and setters for general instruction flags.
  581.   void setMayLoad(bool newVal) { MayLoad = newVal; }
  582.   void setMayStore(bool newVal) { MayStore = newVal; }
  583.   void setHasSideEffects(bool newVal) { HasSideEffects = newVal; }
  584.   void setBeginGroup(bool newVal) { BeginGroup = newVal; }
  585.   void setEndGroup(bool newVal) { EndGroup = newVal; }
  586.   void setRetireOOO(bool newVal) { RetireOOO = newVal; }
  587.  
  588.   bool getMayLoad() const { return MayLoad; }
  589.   bool getMayStore() const { return MayStore; }
  590.   bool getHasSideEffects() const { return HasSideEffects; }
  591.   bool getBeginGroup() const { return BeginGroup; }
  592.   bool getEndGroup() const { return EndGroup; }
  593.   bool getRetireOOO() const { return RetireOOO; }
  594. };
  595.  
  596. /// An instruction propagated through the simulated instruction pipeline.
  597. ///
  598. /// This class is used to monitor changes to the internal state of instructions
  599. /// that are sent to the various components of the simulated hardware pipeline.
  600. class Instruction : public InstructionBase {
  601.   enum InstrStage {
  602.     IS_INVALID,    // Instruction in an invalid state.
  603.     IS_DISPATCHED, // Instruction dispatched but operands are not ready.
  604.     IS_PENDING,    // Instruction is not ready, but operand latency is known.
  605.     IS_READY,      // Instruction dispatched and operands ready.
  606.     IS_EXECUTING,  // Instruction issued.
  607.     IS_EXECUTED,   // Instruction executed. Values are written back.
  608.     IS_RETIRED     // Instruction retired.
  609.   };
  610.  
  611.   // The current instruction stage.
  612.   enum InstrStage Stage;
  613.  
  614.   // This value defaults to the instruction latency. This instruction is
  615.   // considered executed when field CyclesLeft goes to zero.
  616.   int CyclesLeft;
  617.  
  618.   // Retire Unit token ID for this instruction.
  619.   unsigned RCUTokenID;
  620.  
  621.   // LS token ID for this instruction.
  622.   // This field is set to the invalid null token if this is not a memory
  623.   // operation.
  624.   unsigned LSUTokenID;
  625.  
  626.   // A resource mask which identifies buffered resources consumed by this
  627.   // instruction at dispatch stage. In the absence of macro-fusion, this value
  628.   // should always match the value of field `UsedBuffers` from the instruction
  629.   // descriptor (see field InstrBase::Desc).
  630.   uint64_t UsedBuffers;
  631.  
  632.   // Critical register dependency.
  633.   CriticalDependency CriticalRegDep;
  634.  
  635.   // Critical memory dependency.
  636.   CriticalDependency CriticalMemDep;
  637.  
  638.   // A bitmask of busy processor resource units.
  639.   // This field is set to zero only if execution is not delayed during this
  640.   // cycle because of unavailable pipeline resources.
  641.   uint64_t CriticalResourceMask;
  642.  
  643.   // True if this instruction has been optimized at register renaming stage.
  644.   bool IsEliminated;
  645.  
  646. public:
  647.   Instruction(const InstrDesc &D, const unsigned Opcode)
  648.       : InstructionBase(D, Opcode), Stage(IS_INVALID),
  649.         CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0), LSUTokenID(0),
  650.         UsedBuffers(D.UsedBuffers), CriticalRegDep(), CriticalMemDep(),
  651.         CriticalResourceMask(0), IsEliminated(false) {}
  652.  
  653.   void reset();
  654.  
  655.   unsigned getRCUTokenID() const { return RCUTokenID; }
  656.   unsigned getLSUTokenID() const { return LSUTokenID; }
  657.   void setLSUTokenID(unsigned LSUTok) { LSUTokenID = LSUTok; }
  658.  
  659.   uint64_t getUsedBuffers() const { return UsedBuffers; }
  660.   void setUsedBuffers(uint64_t Mask) { UsedBuffers = Mask; }
  661.   void clearUsedBuffers() { UsedBuffers = 0ULL; }
  662.  
  663.   int getCyclesLeft() const { return CyclesLeft; }
  664.  
  665.   // Transition to the dispatch stage, and assign a RCUToken to this
  666.   // instruction. The RCUToken is used to track the completion of every
  667.   // register write performed by this instruction.
  668.   void dispatch(unsigned RCUTokenID);
  669.  
  670.   // Instruction issued. Transition to the IS_EXECUTING state, and update
  671.   // all the register definitions.
  672.   void execute(unsigned IID);
  673.  
  674.   // Force a transition from the IS_DISPATCHED state to the IS_READY or
  675.   // IS_PENDING state. State transitions normally occur either at the beginning
  676.   // of a new cycle (see method cycleEvent()), or as a result of another issue
  677.   // event. This method is called every time the instruction might have changed
  678.   // in state. It internally delegates to method updateDispatched() and
  679.   // updateWaiting().
  680.   void update();
  681.   bool updateDispatched();
  682.   bool updatePending();
  683.  
  684.   bool isInvalid() const { return Stage == IS_INVALID; }
  685.   bool isDispatched() const { return Stage == IS_DISPATCHED; }
  686.   bool isPending() const { return Stage == IS_PENDING; }
  687.   bool isReady() const { return Stage == IS_READY; }
  688.   bool isExecuting() const { return Stage == IS_EXECUTING; }
  689.   bool isExecuted() const { return Stage == IS_EXECUTED; }
  690.   bool isRetired() const { return Stage == IS_RETIRED; }
  691.   bool isEliminated() const { return IsEliminated; }
  692.  
  693.   // Forces a transition from state IS_DISPATCHED to state IS_EXECUTED.
  694.   void forceExecuted();
  695.   void setEliminated() { IsEliminated = true; }
  696.  
  697.   void retire() {
  698.     assert(isExecuted() && "Instruction is in an invalid state!");
  699.     Stage = IS_RETIRED;
  700.   }
  701.  
  702.   const CriticalDependency &getCriticalRegDep() const { return CriticalRegDep; }
  703.   const CriticalDependency &getCriticalMemDep() const { return CriticalMemDep; }
  704.   const CriticalDependency &computeCriticalRegDep();
  705.   void setCriticalMemDep(const CriticalDependency &MemDep) {
  706.     CriticalMemDep = MemDep;
  707.   }
  708.  
  709.   uint64_t getCriticalResourceMask() const { return CriticalResourceMask; }
  710.   void setCriticalResourceMask(uint64_t ResourceMask) {
  711.     CriticalResourceMask = ResourceMask;
  712.   }
  713.  
  714.   void cycleEvent();
  715. };
  716.  
  717. /// An InstRef contains both a SourceMgr index and Instruction pair.  The index
  718. /// is used as a unique identifier for the instruction.  MCA will make use of
  719. /// this index as a key throughout MCA.
  720. class InstRef {
  721.   std::pair<unsigned, Instruction *> Data;
  722.  
  723. public:
  724.   InstRef() : Data(std::make_pair(0, nullptr)) {}
  725.   InstRef(unsigned Index, Instruction *I) : Data(std::make_pair(Index, I)) {}
  726.  
  727.   bool operator==(const InstRef &Other) const { return Data == Other.Data; }
  728.   bool operator!=(const InstRef &Other) const { return Data != Other.Data; }
  729.   bool operator<(const InstRef &Other) const {
  730.     return Data.first < Other.Data.first;
  731.   }
  732.  
  733.   unsigned getSourceIndex() const { return Data.first; }
  734.   Instruction *getInstruction() { return Data.second; }
  735.   const Instruction *getInstruction() const { return Data.second; }
  736.  
  737.   /// Returns true if this references a valid instruction.
  738.   explicit operator bool() const { return Data.second != nullptr; }
  739.  
  740.   /// Invalidate this reference.
  741.   void invalidate() { Data.second = nullptr; }
  742.  
  743. #ifndef NDEBUG
  744.   void print(raw_ostream &OS) const { OS << getSourceIndex(); }
  745. #endif
  746. };
  747.  
  748. #ifndef NDEBUG
  749. inline raw_ostream &operator<<(raw_ostream &OS, const InstRef &IR) {
  750.   IR.print(OS);
  751.   return OS;
  752. }
  753. #endif
  754.  
  755. } // namespace mca
  756. } // namespace llvm
  757.  
  758. #endif // LLVM_MCA_INSTRUCTION_H
  759.