[llvm-mca] Simplify (and better standardize) the Instruction interface.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@328190 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/llvm-mca/Backend.cpp b/tools/llvm-mca/Backend.cpp
index 7d69466..94edf87 100644
--- a/tools/llvm-mca/Backend.cpp
+++ b/tools/llvm-mca/Backend.cpp
@@ -42,7 +42,7 @@
 
     Instruction *IS = NewIS.get();
     Instructions[IR.first] = std::move(NewIS);
-    IS->setRCUTokenID(DU->dispatch(IR.first, IS, STI));
+    DU->dispatch(IR.first, IS, STI);
     SM.updateNext();
   }
 
diff --git a/tools/llvm-mca/Dispatch.cpp b/tools/llvm-mca/Dispatch.cpp
index 36f1bc3..c1e5d3e 100644
--- a/tools/llvm-mca/Dispatch.cpp
+++ b/tools/llvm-mca/Dispatch.cpp
@@ -348,8 +348,8 @@
   DependentWrites.clear();
 }
 
-unsigned DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
-                                const MCSubtargetInfo &STI) {
+void DispatchUnit::dispatch(unsigned IID, Instruction *NewInst,
+                            const MCSubtargetInfo &STI) {
   assert(!CarryOver && "Cannot dispatch another instruction!");
   unsigned NumMicroOps = NewInst->getDesc().NumMicroOps;
   if (NumMicroOps > DispatchWidth) {
@@ -370,17 +370,17 @@
   for (std::unique_ptr<WriteState> &WS : NewInst->getDefs())
     RAT->addRegisterMapping(*WS, RegisterFiles);
 
-  // Set the cycles left before the write-back stage.
-  const InstrDesc &D = NewInst->getDesc();
-  NewInst->setCyclesLeft(D.MaxLatency);
+  // Reserve slots in the RCU, and notify the instruction that it has been
+  // dispatched to the schedulers for execution.
+  NewInst->dispatch(RCU->reserveSlot(IID, NumMicroOps));
 
-  // Reserve slots in the RCU.
-  unsigned RCUTokenID = RCU->reserveSlot(IID, NumMicroOps);
-  NewInst->setRCUTokenID(RCUTokenID);
+  // Notify listeners of the "instruction dispatched" event.
   notifyInstructionDispatched(IID, RegisterFiles);
 
+  // Now move the instruction into the scheduler's queue.
+  // The scheduler is responsible for checking if this is a zero-latency
+  // instruction that doesn't consume pipeline/scheduler resources.
   SC->scheduleInstruction(IID, *NewInst);
-  return RCUTokenID;
 }
 
 #ifndef NDEBUG
diff --git a/tools/llvm-mca/Dispatch.h b/tools/llvm-mca/Dispatch.h
index c1093fa..9ac7c3c 100644
--- a/tools/llvm-mca/Dispatch.h
+++ b/tools/llvm-mca/Dispatch.h
@@ -250,7 +250,8 @@
   bool checkScheduler(unsigned Index, const InstrDesc &Desc);
 
   void updateRAWDependencies(ReadState &RS, const llvm::MCSubtargetInfo &STI);
-  void notifyInstructionDispatched(unsigned IID, llvm::ArrayRef<unsigned> UsedPhysRegs);
+  void notifyInstructionDispatched(unsigned IID,
+                                   llvm::ArrayRef<unsigned> UsedPhysRegs);
 
 public:
   DispatchUnit(Backend *B, const llvm::MCRegisterInfo &MRI,
@@ -279,8 +280,7 @@
            checkScheduler(Index, Desc);
   }
 
-  unsigned dispatch(unsigned IID, Instruction *NewInst,
-                    const llvm::MCSubtargetInfo &STI);
+  void dispatch(unsigned IID, Instruction *I, const llvm::MCSubtargetInfo &STI);
 
   void collectWrites(llvm::SmallVectorImpl<WriteState *> &Vec,
                      unsigned RegID) const {
@@ -306,7 +306,6 @@
   void dump() const;
 #endif
 };
-
 } // namespace mca
 
 #endif
diff --git a/tools/llvm-mca/Instruction.cpp b/tools/llvm-mca/Instruction.cpp
index e3b26bd..edf321a 100644
--- a/tools/llvm-mca/Instruction.cpp
+++ b/tools/llvm-mca/Instruction.cpp
@@ -92,10 +92,12 @@
 }
 #endif
 
-void Instruction::dispatch() {
+void Instruction::dispatch(unsigned RCUToken) {
   assert(Stage == IS_INVALID);
   Stage = IS_AVAILABLE;
+  RCUTokenID = RCUToken;
 
+  // Check if input operands are already available.
   if (std::all_of(Uses.begin(), Uses.end(),
                   [](const UniqueUse &Use) { return Use->isReady(); }))
     Stage = IS_READY;
@@ -104,8 +106,14 @@
 void Instruction::execute() {
   assert(Stage == IS_READY);
   Stage = IS_EXECUTING;
+
+  // Set the cycles left before the write-back stage.
+  setCyclesLeft(Desc.MaxLatency);
+
   for (UniqueDef &Def : Defs)
     Def->onInstructionIssued();
+
+  // Transition to the "executed" stage if this is a zero-latency instruction.
   if (!CyclesLeft)
     Stage = IS_EXECUTED;
 }
diff --git a/tools/llvm-mca/Instruction.h b/tools/llvm-mca/Instruction.h
index 7a0591b..a4a1498 100644
--- a/tools/llvm-mca/Instruction.h
+++ b/tools/llvm-mca/Instruction.h
@@ -110,11 +110,9 @@
   int getCyclesLeft() const { return CyclesLeft; }
   unsigned getWriteResourceID() const { return WD.SClassOrWriteResourceID; }
   unsigned getRegisterID() const { return RegisterID; }
-  void setRegisterID(unsigned ID) { RegisterID = ID; }
 
   void addUser(ReadState *Use, int ReadAdvance);
   bool fullyUpdatesSuperRegs() const { return WD.FullyUpdatesSuperRegs; }
-  bool isWrittenBack() const { return CyclesLeft == 0; }
 
   // On every cycle, update CyclesLeft and notify dependent users.
   void cycleEvent();
@@ -291,22 +289,16 @@
   unsigned getRCUTokenID() const { return RCUTokenID; }
   int getCyclesLeft() const { return CyclesLeft; }
   void setCyclesLeft(int Cycles) { CyclesLeft = Cycles; }
-  void setRCUTokenID(unsigned TokenID) { RCUTokenID = TokenID; }
 
-  // Transition to the dispatch stage.
-  // No definition is updated because the instruction is not "executing".
-  void dispatch();
+  // Transition to the dispatch stage, and assign a RCUToken to this
+  // instruction. The RCUToken is used to track the completion of every
+  // register write performed by this instruction.
+  void dispatch(unsigned RCUTokenID);
 
   // Instruction issued. Transition to the IS_EXECUTING state, and update
   // all the definitions.
   void execute();
 
-  void forceExecuted() {
-    assert((Stage == IS_INVALID && isZeroLatency()) ||
-           (Stage == IS_READY && Desc.MaxLatency == 0));
-    Stage = IS_EXECUTED;
-  }
-
   bool isDispatched() const { return Stage == IS_AVAILABLE; }
   bool isReady() const { return Stage == IS_READY; }
   bool isExecuting() const { return Stage == IS_EXECUTING; }
diff --git a/tools/llvm-mca/Scheduler.cpp b/tools/llvm-mca/Scheduler.cpp
index e722844..70b073b 100644
--- a/tools/llvm-mca/Scheduler.cpp
+++ b/tools/llvm-mca/Scheduler.cpp
@@ -241,16 +241,16 @@
   // eliminated at register renaming stage, since we know in advance that those
   // clear their output register.
   if (MCIS.isZeroLatency()) {
+    assert(MCIS.isReady() && "data dependent zero-latency instruction?");
     notifyInstructionReady(Idx);
-    MCIS.forceExecuted();
+    MCIS.execute();
     notifyInstructionIssued(Idx, {});
+    assert(MCIS.isExecuted() && "Unexpected non-zero latency!");
     notifyInstructionExecuted(Idx);
     return;
   }
 
-  // Consume entries in the reservation stations.
   const InstrDesc &Desc = MCIS.getDesc();
-
   if (!Desc.Buffers.empty()) {
     // Reserve a slot in each buffered resource. Also, mark units with
     // BufferSize=0 as reserved. Resources with a buffer size of zero will only
@@ -265,7 +265,6 @@
   if (MayLoad || MayStore)
     LSU->reserve(Idx, MayLoad, MayStore, Desc.HasSideEffects);
 
-  MCIS.dispatch();
   bool IsReady = MCIS.isReady();
   if (IsReady && (MayLoad || MayStore))
     IsReady &= LSU->isReady(Idx);