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