xref: /llvm-project/llvm/tools/llvm-mca/Views/TimelineView.h (revision 14f77576c9c4f502267a92992abe3bdcbeb96b2c)
110aa09f0SMatt Davis //===--------------------- TimelineView.h -----------------------*- C++ -*-===//
210aa09f0SMatt Davis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
610aa09f0SMatt Davis //
710aa09f0SMatt Davis //===----------------------------------------------------------------------===//
810aa09f0SMatt Davis /// \brief
910aa09f0SMatt Davis ///
1010aa09f0SMatt Davis /// This file implements a timeline view for the llvm-mca tool.
1110aa09f0SMatt Davis ///
1210aa09f0SMatt Davis /// Class TimelineView observes events generated by the pipeline. For every
1310aa09f0SMatt Davis /// instruction executed by the pipeline, it stores information related to
1410aa09f0SMatt Davis /// state transition. It then plots that information in the form of a table
1510aa09f0SMatt Davis /// as reported by the example below:
1610aa09f0SMatt Davis ///
1710aa09f0SMatt Davis /// Timeline view:
1810aa09f0SMatt Davis ///     	          0123456
1910aa09f0SMatt Davis /// Index	0123456789
2010aa09f0SMatt Davis ///
2110aa09f0SMatt Davis /// [0,0]	DeER .    .    ..	vmovshdup  %xmm0, %xmm1
2210aa09f0SMatt Davis /// [0,1]	DeER .    .    ..	vpermilpd  $1, %xmm0, %xmm2
2310aa09f0SMatt Davis /// [0,2]	.DeER.    .    ..	vpermilps  $231, %xmm0, %xmm5
2410aa09f0SMatt Davis /// [0,3]	.DeeeER   .    ..	vaddss  %xmm1, %xmm0, %xmm3
2510aa09f0SMatt Davis /// [0,4]	. D==eeeER.    ..	vaddss  %xmm3, %xmm2, %xmm4
2610aa09f0SMatt Davis /// [0,5]	. D=====eeeER  ..	vaddss  %xmm4, %xmm5, %xmm6
2710aa09f0SMatt Davis ///
2810aa09f0SMatt Davis /// [1,0]	.  DeE------R  ..	vmovshdup  %xmm0, %xmm1
2910aa09f0SMatt Davis /// [1,1]	.  DeE------R  ..	vpermilpd  $1, %xmm0, %xmm2
3010aa09f0SMatt Davis /// [1,2]	.   DeE-----R  ..	vpermilps  $231, %xmm0, %xmm5
3110aa09f0SMatt Davis /// [1,3]	.   D=eeeE--R  ..	vaddss  %xmm1, %xmm0, %xmm3
3210aa09f0SMatt Davis /// [1,4]	.    D===eeeER ..	vaddss  %xmm3, %xmm2, %xmm4
3310aa09f0SMatt Davis /// [1,5]	.    D======eeeER	vaddss  %xmm4, %xmm5, %xmm6
3410aa09f0SMatt Davis ///
3510aa09f0SMatt Davis /// There is an entry for every instruction in the input assembly sequence.
3610aa09f0SMatt Davis /// The first field is a pair of numbers obtained from the instruction index.
3710aa09f0SMatt Davis /// The first element of the pair is the iteration index, while the second
3810aa09f0SMatt Davis /// element of the pair is a sequence number (i.e. a position in the assembly
3910aa09f0SMatt Davis /// sequence).
4010aa09f0SMatt Davis /// The second field of the table is the actual timeline information; each
4110aa09f0SMatt Davis /// column is the information related to a specific cycle of execution.
4210aa09f0SMatt Davis /// The timeline of an instruction is described by a sequence of character
4310aa09f0SMatt Davis /// where each character represents the instruction state at a specific cycle.
4410aa09f0SMatt Davis ///
4510aa09f0SMatt Davis /// Possible instruction states are:
4610aa09f0SMatt Davis ///  D: Instruction Dispatched
4710aa09f0SMatt Davis ///  e: Instruction Executing
4810aa09f0SMatt Davis ///  E: Instruction Executed (write-back stage)
4910aa09f0SMatt Davis ///  R: Instruction retired
5010aa09f0SMatt Davis ///  =: Instruction waiting in the Scheduler's queue
5110aa09f0SMatt Davis ///  -: Instruction executed, waiting to retire in order.
5210aa09f0SMatt Davis ///
5310aa09f0SMatt Davis /// dots ('.') and empty spaces are cycles where the instruction is not
5410aa09f0SMatt Davis /// in-flight.
5510aa09f0SMatt Davis ///
5610aa09f0SMatt Davis /// The last column is the assembly instruction associated to the entry.
5710aa09f0SMatt Davis ///
5810aa09f0SMatt Davis /// Based on the timeline view information from the example, instruction 0
5910aa09f0SMatt Davis /// at iteration 0 was dispatched at cycle 0, and was retired at cycle 3.
6010aa09f0SMatt Davis /// Instruction [0,1] was also dispatched at cycle 0, and it retired at
6110aa09f0SMatt Davis /// the same cycle than instruction [0,0].
6210aa09f0SMatt Davis /// Instruction [0,4] has been dispatched at cycle 2. However, it had to
6310aa09f0SMatt Davis /// wait for two cycles before being issued. That is because operands
6410aa09f0SMatt Davis /// became ready only at cycle 5.
6510aa09f0SMatt Davis ///
6610aa09f0SMatt Davis /// This view helps further understanding bottlenecks and the impact of
6710aa09f0SMatt Davis /// resource pressure on the code.
6810aa09f0SMatt Davis ///
6910aa09f0SMatt Davis /// To better understand why instructions had to wait for multiple cycles in
7010aa09f0SMatt Davis /// the scheduler's queue, class TimelineView also reports extra timing info
7110aa09f0SMatt Davis /// in another table named "Average Wait times" (see example below).
7210aa09f0SMatt Davis ///
7310aa09f0SMatt Davis ///
7410aa09f0SMatt Davis /// Average Wait times (based on the timeline view):
7510aa09f0SMatt Davis /// [0]: Executions
7610aa09f0SMatt Davis /// [1]: Average time spent waiting in a scheduler's queue
7710aa09f0SMatt Davis /// [2]: Average time spent waiting in a scheduler's queue while ready
7810aa09f0SMatt Davis /// [3]: Average time elapsed from WB until retire stage
7910aa09f0SMatt Davis ///
8010aa09f0SMatt Davis ///	[0]	[1]	[2]	[3]
8110aa09f0SMatt Davis /// 0.	 2	1.0	1.0	3.0	vmovshdup  %xmm0, %xmm1
8210aa09f0SMatt Davis /// 1.	 2	1.0	1.0	3.0	vpermilpd  $1, %xmm0, %xmm2
8310aa09f0SMatt Davis /// 2.	 2	1.0	1.0	2.5	vpermilps  $231, %xmm0, %xmm5
8410aa09f0SMatt Davis /// 3.	 2	1.5	0.5	1.0	vaddss  %xmm1, %xmm0, %xmm3
8510aa09f0SMatt Davis /// 4.	 2	3.5	0.0	0.0	vaddss  %xmm3, %xmm2, %xmm4
8610aa09f0SMatt Davis /// 5.	 2	6.5	0.0	0.0	vaddss  %xmm4, %xmm5, %xmm6
87a5e65c1cSRoman Lebedev ///      2	2.4	0.6	1.6     <total>
8810aa09f0SMatt Davis ///
8910aa09f0SMatt Davis /// By comparing column [2] with column [1], we get an idea about how many
9010aa09f0SMatt Davis /// cycles were spent in the scheduler's queue due to data dependencies.
9110aa09f0SMatt Davis ///
9210aa09f0SMatt Davis /// In this example, instruction 5 spent an average of ~6 cycles in the
9310aa09f0SMatt Davis /// scheduler's queue. As soon as operands became ready, the instruction
9410aa09f0SMatt Davis /// was immediately issued to the pipeline(s).
9510aa09f0SMatt Davis /// That is expected because instruction 5 cannot transition to the "ready"
9610aa09f0SMatt Davis /// state until %xmm4 is written by instruction 4.
9710aa09f0SMatt Davis ///
9810aa09f0SMatt Davis //===----------------------------------------------------------------------===//
9910aa09f0SMatt Davis 
10010aa09f0SMatt Davis #ifndef LLVM_TOOLS_LLVM_MCA_TIMELINEVIEW_H
10110aa09f0SMatt Davis #define LLVM_TOOLS_LLVM_MCA_TIMELINEVIEW_H
10210aa09f0SMatt Davis 
103d38be2baSWolfgang Pieb #include "Views/InstructionView.h"
10484d00513SAndrea Di Biagio #include "llvm/ADT/ArrayRef.h"
10584d00513SAndrea Di Biagio #include "llvm/MC/MCInst.h"
10610aa09f0SMatt Davis #include "llvm/MC/MCInstPrinter.h"
10710aa09f0SMatt Davis #include "llvm/MC/MCSubtargetInfo.h"
10810aa09f0SMatt Davis #include "llvm/Support/FormattedStream.h"
109d38be2baSWolfgang Pieb #include "llvm/Support/JSON.h"
11010aa09f0SMatt Davis #include "llvm/Support/raw_ostream.h"
11110aa09f0SMatt Davis 
1125a8fd657SFangrui Song namespace llvm {
11310aa09f0SMatt Davis namespace mca {
11410aa09f0SMatt Davis 
11510aa09f0SMatt Davis /// This class listens to instruction state transition events
11610aa09f0SMatt Davis /// in order to construct a timeline information.
11710aa09f0SMatt Davis ///
11810aa09f0SMatt Davis /// For every instruction executed by the Pipeline, this class constructs
11910aa09f0SMatt Davis /// a TimelineViewEntry object. TimelineViewEntry objects are then used
12010aa09f0SMatt Davis /// to print the timeline information, as well as the "average wait times"
12110aa09f0SMatt Davis /// for every instruction in the input assembly sequence.
122e02920feSWolfgang Pieb class TimelineView : public InstructionView {
12310aa09f0SMatt Davis   unsigned CurrentCycle;
12410aa09f0SMatt Davis   unsigned MaxCycle;
12510aa09f0SMatt Davis   unsigned LastCycle;
12610aa09f0SMatt Davis 
12710aa09f0SMatt Davis   struct TimelineViewEntry {
1288b647dcfSAndrea Di Biagio     int CycleDispatched; // A negative value is an "invalid cycle".
12910aa09f0SMatt Davis     unsigned CycleReady;
13010aa09f0SMatt Davis     unsigned CycleIssued;
13110aa09f0SMatt Davis     unsigned CycleExecuted;
13210aa09f0SMatt Davis     unsigned CycleRetired;
13310aa09f0SMatt Davis   };
13410aa09f0SMatt Davis   std::vector<TimelineViewEntry> Timeline;
13510aa09f0SMatt Davis 
13610aa09f0SMatt Davis   struct WaitTimeEntry {
13710aa09f0SMatt Davis     unsigned CyclesSpentInSchedulerQueue;
13810aa09f0SMatt Davis     unsigned CyclesSpentInSQWhileReady;
13910aa09f0SMatt Davis     unsigned CyclesSpentAfterWBAndBeforeRetire;
14010aa09f0SMatt Davis   };
14110aa09f0SMatt Davis   std::vector<WaitTimeEntry> WaitTime;
1424269d64bSAndrea Di Biagio 
1434269d64bSAndrea Di Biagio   // This field is used to map instructions to buffered resources.
1444269d64bSAndrea Di Biagio   // Elements of this vector are <resourceID, BufferSizer> pairs.
1454269d64bSAndrea Di Biagio   std::vector<std::pair<unsigned, int>> UsedBuffer;
14610aa09f0SMatt Davis 
14710aa09f0SMatt Davis   void printTimelineViewEntry(llvm::formatted_raw_ostream &OS,
14810aa09f0SMatt Davis                               const TimelineViewEntry &E, unsigned Iteration,
14910aa09f0SMatt Davis                               unsigned SourceIndex) const;
15010aa09f0SMatt Davis   void printWaitTimeEntry(llvm::formatted_raw_ostream &OS,
151d17d371cSAndrea Di Biagio                           const WaitTimeEntry &E, unsigned Index,
152d17d371cSAndrea Di Biagio                           unsigned Executions) const;
15310aa09f0SMatt Davis 
15410aa09f0SMatt Davis   // Display characters for the TimelineView report output.
15510aa09f0SMatt Davis   struct DisplayChar {
15610aa09f0SMatt Davis     static const char Dispatched = 'D';
15710aa09f0SMatt Davis     static const char Executed = 'E';
15810aa09f0SMatt Davis     static const char Retired = 'R';
15910aa09f0SMatt Davis     static const char Waiting = '='; // Instruction is waiting in the scheduler.
16010aa09f0SMatt Davis     static const char Executing = 'e';
16110aa09f0SMatt Davis     static const char RetireLag = '-'; // The instruction is waiting to retire.
16210aa09f0SMatt Davis   };
16310aa09f0SMatt Davis 
16410aa09f0SMatt Davis public:
16510aa09f0SMatt Davis   TimelineView(const llvm::MCSubtargetInfo &sti, llvm::MCInstPrinter &Printer,
16684d00513SAndrea Di Biagio                llvm::ArrayRef<llvm::MCInst> S, unsigned Iterations,
167d17d371cSAndrea Di Biagio                unsigned Cycles);
16810aa09f0SMatt Davis 
16910aa09f0SMatt Davis   // Event handlers.
onCycleEnd()17010aa09f0SMatt Davis   void onCycleEnd() override { ++CurrentCycle; }
17110aa09f0SMatt Davis   void onEvent(const HWInstructionEvent &Event) override;
172d17d371cSAndrea Di Biagio   void onReservedBuffers(const InstRef &IR,
173d17d371cSAndrea Di Biagio                          llvm::ArrayRef<unsigned> Buffers) override;
17410aa09f0SMatt Davis 
17510aa09f0SMatt Davis   // print functionalities.
17610aa09f0SMatt Davis   void printTimeline(llvm::raw_ostream &OS) const;
17710aa09f0SMatt Davis   void printAverageWaitTimes(llvm::raw_ostream &OS) const;
printView(llvm::raw_ostream & OS)17810aa09f0SMatt Davis   void printView(llvm::raw_ostream &OS) const override {
17910aa09f0SMatt Davis     printTimeline(OS);
18010aa09f0SMatt Davis     printAverageWaitTimes(OS);
18110aa09f0SMatt Davis   }
getNameAsString()182d38be2baSWolfgang Pieb   StringRef getNameAsString() const override { return "TimelineView"; }
183*c6e8f814SWolfgang Pieb   json::Value toJSON() const override;
18410aa09f0SMatt Davis };
18510aa09f0SMatt Davis } // namespace mca
1865a8fd657SFangrui Song } // namespace llvm
18710aa09f0SMatt Davis 
18810aa09f0SMatt Davis #endif
189