[llvm-mca] Avoid calling method update() on instructions that are already in the IS_READY state. NFCI

When promoting instructions from the wait queue to the ready queue, we should
check if an instruction has already reached the IS_READY state before
calling method update().

llvm-svn: 335722
diff --git a/llvm/tools/llvm-mca/Instruction.cpp b/llvm/tools/llvm-mca/Instruction.cpp
index 3abf30c..f84c781 100644
--- a/llvm/tools/llvm-mca/Instruction.cpp
+++ b/llvm/tools/llvm-mca/Instruction.cpp
@@ -32,8 +32,10 @@
   --DependentWrites;
   TotalCycles = std::max(TotalCycles, Cycles);
 
-  if (!DependentWrites)
+  if (!DependentWrites) {
     CyclesLeft = TotalCycles;
+    IsReady = !CyclesLeft;
+  }
 }
 
 void WriteState::onInstructionIssued() {
@@ -83,8 +85,10 @@
   if (CyclesLeft == UNKNOWN_CYCLES)
     return;
 
-  if (CyclesLeft)
+  if (CyclesLeft) {
     --CyclesLeft;
+    IsReady = !CyclesLeft;
+  }
 }
 
 #ifndef NDEBUG
@@ -119,9 +123,7 @@
 }
 
 void Instruction::update() {
-  if (!isDispatched())
-    return;
-
+  assert(isDispatched() && "Unexpected instruction stage found!");
   if (llvm::all_of(Uses, [](const UniqueUse &Use) { return Use->isReady(); }))
     Stage = IS_READY;
 }
@@ -131,9 +133,14 @@
     return;
 
   if (isDispatched()) {
-    for (UniqueUse &Use : Uses)
+    bool IsReady = true;
+    for (UniqueUse &Use : Uses) {
       Use->cycleEvent();
-    update();
+      IsReady &= Use->isReady();
+    }
+
+    if (IsReady)
+      Stage = IS_READY;
     return;
   }
 
diff --git a/llvm/tools/llvm-mca/Instruction.h b/llvm/tools/llvm-mca/Instruction.h
index 880d57b..32246ce 100644
--- a/llvm/tools/llvm-mca/Instruction.h
+++ b/llvm/tools/llvm-mca/Instruction.h
@@ -162,17 +162,16 @@
   // dependent writes (i.e. field DependentWrite) is zero, this value is
   // propagated to field CyclesLeft.
   unsigned TotalCycles;
+  // This field is set to true only if there are no dependent writes, and
+  // there are no `CyclesLeft' to wait.
+  bool IsReady;
 
 public:
-  bool isReady() const {
-    if (DependentWrites)
-      return false;
-    return (CyclesLeft == UNKNOWN_CYCLES || CyclesLeft == 0);
-  }
+  bool isReady() const { return IsReady; }
 
   ReadState(const ReadDescriptor &Desc, unsigned RegID)
       : RD(Desc), RegisterID(RegID), DependentWrites(0),
-        CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0) {}
+        CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true) {}
   ReadState(const ReadState &Other) = delete;
   ReadState &operator=(const ReadState &Other) = delete;
 
@@ -182,7 +181,10 @@
 
   void cycleEvent();
   void writeStartEvent(unsigned Cycles);
-  void setDependentWrites(unsigned Writes) { DependentWrites = Writes; }
+  void setDependentWrites(unsigned Writes) {
+    DependentWrites = Writes;
+    IsReady = !Writes;
+  }
 };
 
 /// A sequence of cycles.
diff --git a/llvm/tools/llvm-mca/Scheduler.cpp b/llvm/tools/llvm-mca/Scheduler.cpp
index f79eda7..deefb46 100644
--- a/llvm/tools/llvm-mca/Scheduler.cpp
+++ b/llvm/tools/llvm-mca/Scheduler.cpp
@@ -293,7 +293,8 @@
 
     // Check if this instruction is now ready. In case, force
     // a transition in state using method 'update()'.
-    IS->update();
+    if (!IS->isReady())
+      IS->update();
 
     const InstrDesc &Desc = IS->getDesc();
     bool IsMemOp = Desc.MayLoad || Desc.MayStore;