[PATCH] D104815: [MCA] [TimelineView] Fixing a bug (that I caused) in TimelineView.cpp that was causing instructions that execute after timeline-max-cycles to still be displayed.

Patrick Holland via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 23 13:46:42 PDT 2021


holland11 created this revision.
holland11 added reviewers: andreadb, qcolombet.
Herald added a subscriber: gbedwell.
holland11 requested review of this revision.
Herald added a project: LLVM.

Within this diff https://reviews.llvm.org/D104675, I tried to fix a bug that was causing 0 latency instructions that were being retired within cycle 0 to break the timeline view. The way I fixed it was insufficient, because I didn't understand the reason for the if statement in `TimelineView::printTimeline()`. I now understand its purpose so I've modified my 'fix' to still behave as intended, but to also still fix the 0 latency issue.

To be more clear about what's happening, let's look at `TimelineView::onEvent()`:

  void TimelineView::onEvent(const HWInstructionEvent &Event) {
    const unsigned Index = Event.IR.getSourceIndex();
    if (Index >= Timeline.size())
      return;
  
    switch (Event.Type) {
    case HWInstructionEvent::Retired: {
      TimelineViewEntry &TVEntry = Timeline[Index];
      if (CurrentCycle < MaxCycle)
        TVEntry.CycleRetired = CurrentCycle;
  
      // Update the WaitTime entry which corresponds to this Index.
      assert(TVEntry.CycleDispatched >= 0 && "Invalid TVEntry found!");
      unsigned CycleDispatched = static_cast<unsigned>(TVEntry.CycleDispatched);
      WaitTimeEntry &WTEntry = WaitTime[Index % getSource().size()];
      WTEntry.CyclesSpentInSchedulerQueue +=
          TVEntry.CycleIssued - CycleDispatched;
      assert(CycleDispatched <= TVEntry.CycleReady &&
             "Instruction cannot be ready if it hasn't been dispatched yet!");
      WTEntry.CyclesSpentInSQWhileReady +=
          TVEntry.CycleIssued - TVEntry.CycleReady;
      if (CurrentCycle > TVEntry.CycleExecuted) {
        WTEntry.CyclesSpentAfterWBAndBeforeRetire +=
            (CurrentCycle - 1) - TVEntry.CycleExecuted;
      }
      break;
    }
    case HWInstructionEvent::Ready:
      Timeline[Index].CycleReady = CurrentCycle;
      break;
    case HWInstructionEvent::Issued:
      Timeline[Index].CycleIssued = CurrentCycle;
      break;
    case HWInstructionEvent::Executed:
      Timeline[Index].CycleExecuted = CurrentCycle;
      break;
    case HWInstructionEvent::Dispatched:
      // There may be multiple dispatch events. Microcoded instructions that are
      // expanded into multiple uOps may require multiple dispatch cycles. Here,
      // we want to capture the first dispatch cycle.
      if (Timeline[Index].CycleDispatched == -1)
        Timeline[Index].CycleDispatched = static_cast<int>(CurrentCycle);
      break;
    default:
      return;
    }
    if (CurrentCycle < MaxCycle)
      LastCycle = std::max(LastCycle, CurrentCycle);
  }

We can see that when an instruction is Retired, if `CurrentCycle` is not less than `MaxCycle`, `CycleRetired` stays 0. However, when an instruction is Executed, we set `CycleExecuted` regardless.

So the new change that I am making now will check for `CycleRetired == 0` to determine whether this instruction was Retired within the timeline limits, but it will also check `CycleExecuted` to make sure we aren't looking at a 0 cycle instruction that has a legitimate `CycleRetired` set to 0.

It's possible that during these few days where the bug was present, some new llvm-mca related tests were made (that could now fail). But I ran both `ninja check all` and `ninja check llvm-mca` and there were no failures so we should be fine.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D104815

Files:
  llvm/tools/llvm-mca/Views/TimelineView.cpp


Index: llvm/tools/llvm-mca/Views/TimelineView.cpp
===================================================================
--- llvm/tools/llvm-mca/Views/TimelineView.cpp
+++ llvm/tools/llvm-mca/Views/TimelineView.cpp
@@ -288,6 +288,15 @@
   for (unsigned Iteration = 0; Iteration < Iterations; ++Iteration) {
     for (const MCInst &Inst : Source) {
       const TimelineViewEntry &Entry = Timeline[IID];
+      // When an instruction is retired after timeline-max-cycles,
+      // its CycleRetired is left at 0. However, it's possible for
+      // a 0 latency instruction to be retired during cycle 0 and we
+      // don't want to early exit in that case. The CycleExecuted
+      // attribute is set correctly whether or not it is greater
+      // than timeline-max-cycles so we can use that to ensure
+      // we don't early exit because of a 0 latency instruction.
+      if (Entry.CycleRetired == 0 && Entry.CycleExecuted != 0)
+        return;
 
       unsigned SourceIndex = IID % Source.size();
       printTimelineViewEntry(FOS, Entry, Iteration, SourceIndex);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D104815.354060.patch
Type: text/x-patch
Size: 1070 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210623/f7fc7b0c/attachment.bin>


More information about the llvm-commits mailing list