[llvm] ecf372f - [llvm-mca][RISCV] vsetivli and vsetvli act as instruments

Michael Maitland via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 6 15:14:30 PDT 2023


Author: Michael Maitland
Date: 2023-07-06T15:12:08-07:00
New Revision: ecf372f993fa0f1ae417a3159e5c397f36c2d48c

URL: https://github.com/llvm/llvm-project/commit/ecf372f993fa0f1ae417a3159e5c397f36c2d48c
DIFF: https://github.com/llvm/llvm-project/commit/ecf372f993fa0f1ae417a3159e5c397f36c2d48c.diff

LOG: [llvm-mca][RISCV] vsetivli and vsetvli act as instruments

Since the LMUL data that is needed to create an instrument is
avaliable statically from vsetivli and vsetvli instructions,
LMUL instruments can be automatically generated so that clients
of the tool do no need to manually insert instrument comments.

Instrument comments may be placed after a vset{i}vli instruction,
which will override instrument that was automatically inserted.
As a result, clients of llvm-mca instruments do not need to update
their existing instrument comments. However, if the instrument
has the same LMUL as the vset{i}vli, then it is reccomended to
remove the instrument comment as it becomes redundant.

Differential Revision: https://reviews.llvm.org/D154526

Added: 
    llvm/test/tools/llvm-mca/RISCV/no-vsetvli-to-start.s
    llvm/test/tools/llvm-mca/RISCV/vsetivli-lmul-instrument.s
    llvm/test/tools/llvm-mca/RISCV/vsetvli-lmul-instrument.s

Modified: 
    llvm/include/llvm/MCA/CustomBehaviour.h
    llvm/lib/MCA/CustomBehaviour.cpp
    llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
    llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h
    llvm/tools/llvm-mca/CodeRegion.h
    llvm/tools/llvm-mca/CodeRegionGenerator.cpp
    llvm/tools/llvm-mca/CodeRegionGenerator.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h
index 348f2e869e20ce..b3774894517ab4 100644
--- a/llvm/include/llvm/MCA/CustomBehaviour.h
+++ b/llvm/include/llvm/MCA/CustomBehaviour.h
@@ -156,9 +156,16 @@ class InstrumentManager {
   // Instrument.Desc equal to Type
   virtual bool supportsInstrumentType(StringRef Type) const { return false; }
 
-  /// Allocate an Instrument, and return a unique pointer to it.
+  /// Allocate an Instrument, and return a unique pointer to it. This function
+  /// may be useful to create instruments coming from comments in the assembly.
+  /// See createInstruments to create Instruments from MCInst
   virtual UniqueInstrument createInstrument(StringRef Desc, StringRef Data);
 
+  /// Return a list of unique pointers to Instruments, where each Instrument
+  /// is allocated by this function. See createInstrument to create Instrument
+  /// from a description and data.
+  virtual SmallVector<UniqueInstrument> createInstruments(const MCInst &Inst);
+
   /// Given an MCInst and a vector of Instrument, a target can
   /// return a SchedClassID. This can be used by a subtarget to return a
   /// PseudoInstruction SchedClassID instead of the one that belongs to the

diff  --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp
index a690850bc5ba3c..1aa266e0a1e43b 100644
--- a/llvm/lib/MCA/CustomBehaviour.cpp
+++ b/llvm/lib/MCA/CustomBehaviour.cpp
@@ -47,6 +47,11 @@ UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc,
   return std::make_unique<Instrument>(Desc, Data);
 }
 
+SmallVector<UniqueInstrument>
+InstrumentManager::createInstruments(const MCInst &Inst) {
+  return SmallVector<UniqueInstrument>();
+}
+
 unsigned InstrumentManager::getSchedClassID(
     const MCInstrInfo &MCII, const MCInst &MCI,
     const llvm::SmallVector<Instrument *> &IVec) const {

diff  --git a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
index 00ffde0925b367..9f152710318db5 100644
--- a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
+++ b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.cpp
@@ -13,6 +13,7 @@
 
 #include "RISCVCustomBehaviour.h"
 #include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "RISCV.h"
 #include "RISCVInstrInfo.h"
 #include "TargetInfo/RISCVTargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -89,6 +90,49 @@ RISCVInstrumentManager::createInstrument(llvm::StringRef Desc,
   return std::make_unique<RISCVLMULInstrument>(Data);
 }
 
+SmallVector<UniqueInstrument>
+RISCVInstrumentManager::createInstruments(const MCInst &Inst) {
+  if (Inst.getOpcode() == RISCV::VSETVLI ||
+      Inst.getOpcode() == RISCV::VSETIVLI) {
+    LLVM_DEBUG(dbgs() << "RVCB: Found VSETVLI and creating instrument for it: "
+                      << Inst << "\n");
+    unsigned VTypeI = Inst.getOperand(2).getImm();
+    RISCVII::VLMUL VLMUL = RISCVVType::getVLMUL(VTypeI);
+
+    StringRef LMUL;
+    switch (VLMUL) {
+    case RISCVII::LMUL_1:
+      LMUL = "M1";
+      break;
+    case RISCVII::LMUL_2:
+      LMUL = "M2";
+      break;
+    case RISCVII::LMUL_4:
+      LMUL = "M4";
+      break;
+    case RISCVII::LMUL_8:
+      LMUL = "M8";
+      break;
+    case RISCVII::LMUL_F2:
+      LMUL = "MF2";
+      break;
+    case RISCVII::LMUL_F4:
+      LMUL = "MF4";
+      break;
+    case RISCVII::LMUL_F8:
+      LMUL = "MF8";
+      break;
+    case RISCVII::LMUL_RESERVED:
+      llvm_unreachable("Cannot create instrument for LMUL_RESERVED");
+    }
+    SmallVector<UniqueInstrument> Instruments;
+    Instruments.emplace_back(
+        createInstrument(RISCVLMULInstrument::DESC_NAME, LMUL));
+    return Instruments;
+  }
+  return SmallVector<UniqueInstrument>();
+}
+
 unsigned RISCVInstrumentManager::getSchedClassID(
     const MCInstrInfo &MCII, const MCInst &MCI,
     const llvm::SmallVector<Instrument *> &IVec) const {

diff  --git a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h
index 7ce072b3840ce1..8e4c00b35dc39d 100644
--- a/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h
+++ b/llvm/lib/Target/RISCV/MCA/RISCVCustomBehaviour.h
@@ -49,6 +49,8 @@ class RISCVInstrumentManager : public InstrumentManager {
   /// Create a Instrument for RISC-V target
   UniqueInstrument createInstrument(StringRef Desc, StringRef Data) override;
 
+  SmallVector<UniqueInstrument> createInstruments(const MCInst &Inst) override;
+
   /// Using the Instrument, returns a SchedClassID to use instead of
   /// the SchedClassID that belongs to the MCI or the original SchedClassID.
   unsigned

diff  --git a/llvm/test/tools/llvm-mca/RISCV/no-vsetvli-to-start.s b/llvm/test/tools/llvm-mca/RISCV/no-vsetvli-to-start.s
new file mode 100644
index 00000000000000..c976d8ba4c9f5f
--- /dev/null
+++ b/llvm/test/tools/llvm-mca/RISCV/no-vsetvli-to-start.s
@@ -0,0 +1,69 @@
+# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
+# RUN: llvm-mca -mtriple=riscv64 -mcpu=sifive-x280 -timeline -iterations=1 < %s | FileCheck %s
+
+vadd.vv v12, v12, v12
+vsetvli zero, a0, e8, m1, tu, mu
+vadd.vv v12, v12, v12
+
+# CHECK:      Iterations:        1
+# CHECK-NEXT: Instructions:      3
+# CHECK-NEXT: Total Cycles:      21
+# CHECK-NEXT: Total uOps:        3
+
+# CHECK:      Dispatch Width:    2
+# CHECK-NEXT: uOps Per Cycle:    0.14
+# CHECK-NEXT: IPC:               0.14
+# CHECK-NEXT: Block RThroughput: 18.0
+
+# CHECK:      Instruction Info:
+# CHECK-NEXT: [1]: #uOps
+# CHECK-NEXT: [2]: Latency
+# CHECK-NEXT: [3]: RThroughput
+# CHECK-NEXT: [4]: MayLoad
+# CHECK-NEXT: [5]: MayStore
+# CHECK-NEXT: [6]: HasSideEffects (U)
+
+# CHECK:      [1]    [2]    [3]    [4]    [5]    [6]    Instructions:
+# CHECK-NEXT:  1      4     16.00                       vadd.vv	v12, v12, v12
+# CHECK-NEXT:  1      3     1.00                  U     vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT:  1      4     2.00                        vadd.vv	v12, v12, v12
+
+# CHECK:      Resources:
+# CHECK-NEXT: [0]   - SiFive7FDiv
+# CHECK-NEXT: [1]   - SiFive7IDiv
+# CHECK-NEXT: [2]   - SiFive7PipeA
+# CHECK-NEXT: [3]   - SiFive7PipeB
+# CHECK-NEXT: [4]   - SiFive7PipeV
+# CHECK-NEXT: [5]   - SiFive7VA
+# CHECK-NEXT: [6]   - SiFive7VL
+# CHECK-NEXT: [7]   - SiFive7VS
+
+# CHECK:      Resource pressure per iteration:
+# CHECK-NEXT: [0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]
+# CHECK-NEXT:  -      -     1.00    -     18.00  18.00   -      -
+
+# CHECK:      Resource pressure by instruction:
+# CHECK-NEXT: [0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]    Instructions:
+# CHECK-NEXT:  -      -      -      -     16.00  16.00   -      -     vadd.vv	v12, v12, v12
+# CHECK-NEXT:  -      -     1.00    -      -      -      -      -     vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT:  -      -      -      -     2.00   2.00    -      -     vadd.vv	v12, v12, v12
+
+# CHECK:      Timeline view:
+# CHECK-NEXT:                     0123456789
+# CHECK-NEXT: Index     0123456789          0
+
+# CHECK:      [0,0]     DeeeE.    .    .    .   vadd.vv	v12, v12, v12
+# CHECK-NEXT: [0,1]     .DeeE.    .    .    .   vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT: [0,2]     .    .    .    .DeeeE   vadd.vv	v12, v12, v12
+
+# CHECK:      Average Wait times (based on the timeline view):
+# CHECK-NEXT: [0]: Executions
+# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue
+# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready
+# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
+
+# CHECK:            [0]    [1]    [2]    [3]
+# CHECK-NEXT: 0.     1     0.0    0.0    0.0       vadd.vv	v12, v12, v12
+# CHECK-NEXT: 1.     1     0.0    0.0    0.0       vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT: 2.     1     0.0    0.0    0.0       vadd.vv	v12, v12, v12
+# CHECK-NEXT:        1     0.0    0.0    0.0       <total>

diff  --git a/llvm/test/tools/llvm-mca/RISCV/vsetivli-lmul-instrument.s b/llvm/test/tools/llvm-mca/RISCV/vsetivli-lmul-instrument.s
new file mode 100644
index 00000000000000..9c958f5a4939bf
--- /dev/null
+++ b/llvm/test/tools/llvm-mca/RISCV/vsetivli-lmul-instrument.s
@@ -0,0 +1,74 @@
+# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
+# RUN: llvm-mca -mtriple=riscv64 -mcpu=sifive-x280 -timeline -iterations=1 < %s | FileCheck %s
+
+vsetivli zero, 8, e8, m1, tu, mu
+vadd.vv v12, v12, v12
+vsetivli zero, 8, e8, m8, tu, mu
+vadd.vv v12, v12, v12
+
+# CHECK:      Iterations:        1
+# CHECK-NEXT: Instructions:      4
+# CHECK-NEXT: Total Cycles:      12
+# CHECK-NEXT: Total uOps:        4
+
+# CHECK:      Dispatch Width:    2
+# CHECK-NEXT: uOps Per Cycle:    0.33
+# CHECK-NEXT: IPC:               0.33
+# CHECK-NEXT: Block RThroughput: 18.0
+
+# CHECK:      Instruction Info:
+# CHECK-NEXT: [1]: #uOps
+# CHECK-NEXT: [2]: Latency
+# CHECK-NEXT: [3]: RThroughput
+# CHECK-NEXT: [4]: MayLoad
+# CHECK-NEXT: [5]: MayStore
+# CHECK-NEXT: [6]: HasSideEffects (U)
+
+# CHECK:      [1]    [2]    [3]    [4]    [5]    [6]    Instructions:
+# CHECK-NEXT:  1      3     1.00                  U     vsetivli	zero, 8, e8, m1, tu, mu
+# CHECK-NEXT:  1      4     2.00                        vadd.vv	v12, v12, v12
+# CHECK-NEXT:  1      3     1.00                  U     vsetivli	zero, 8, e8, m8, tu, mu
+# CHECK-NEXT:  1      4     16.00                       vadd.vv	v12, v12, v12
+
+# CHECK:      Resources:
+# CHECK-NEXT: [0]   - SiFive7FDiv
+# CHECK-NEXT: [1]   - SiFive7IDiv
+# CHECK-NEXT: [2]   - SiFive7PipeA
+# CHECK-NEXT: [3]   - SiFive7PipeB
+# CHECK-NEXT: [4]   - SiFive7PipeV
+# CHECK-NEXT: [5]   - SiFive7VA
+# CHECK-NEXT: [6]   - SiFive7VL
+# CHECK-NEXT: [7]   - SiFive7VS
+
+# CHECK:      Resource pressure per iteration:
+# CHECK-NEXT: [0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]
+# CHECK-NEXT:  -      -     2.00    -     18.00  18.00   -      -
+
+# CHECK:      Resource pressure by instruction:
+# CHECK-NEXT: [0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]    Instructions:
+# CHECK-NEXT:  -      -     1.00    -      -      -      -      -     vsetivli	zero, 8, e8, m1, tu, mu
+# CHECK-NEXT:  -      -      -      -     2.00   2.00    -      -     vadd.vv	v12, v12, v12
+# CHECK-NEXT:  -      -     1.00    -      -      -      -      -     vsetivli	zero, 8, e8, m8, tu, mu
+# CHECK-NEXT:  -      -      -      -     16.00  16.00   -      -     vadd.vv	v12, v12, v12
+
+# CHECK:      Timeline view:
+# CHECK-NEXT:                     01
+# CHECK-NEXT: Index     0123456789
+
+# CHECK:      [0,0]     DeeE .    ..   vsetivli	zero, 8, e8, m1, tu, mu
+# CHECK-NEXT: [0,1]     .  DeeeE  ..   vadd.vv	v12, v12, v12
+# CHECK-NEXT: [0,2]     .   DeeE  ..   vsetivli	zero, 8, e8, m8, tu, mu
+# CHECK-NEXT: [0,3]     .    . DeeeE   vadd.vv	v12, v12, v12
+
+# CHECK:      Average Wait times (based on the timeline view):
+# CHECK-NEXT: [0]: Executions
+# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue
+# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready
+# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
+
+# CHECK:            [0]    [1]    [2]    [3]
+# CHECK-NEXT: 0.     1     0.0    0.0    0.0       vsetivli	zero, 8, e8, m1, tu, mu
+# CHECK-NEXT: 1.     1     0.0    0.0    0.0       vadd.vv	v12, v12, v12
+# CHECK-NEXT: 2.     1     0.0    0.0    0.0       vsetivli	zero, 8, e8, m8, tu, mu
+# CHECK-NEXT: 3.     1     0.0    0.0    0.0       vadd.vv	v12, v12, v12
+# CHECK-NEXT:        1     0.0    0.0    0.0       <total>

diff  --git a/llvm/test/tools/llvm-mca/RISCV/vsetvli-lmul-instrument.s b/llvm/test/tools/llvm-mca/RISCV/vsetvli-lmul-instrument.s
new file mode 100644
index 00000000000000..8beefd39cf844e
--- /dev/null
+++ b/llvm/test/tools/llvm-mca/RISCV/vsetvli-lmul-instrument.s
@@ -0,0 +1,74 @@
+# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py
+# RUN: llvm-mca -mtriple=riscv64 -mcpu=sifive-x280 -timeline -iterations=1 < %s | FileCheck %s
+
+vsetvli zero, a0, e8, m1, tu, mu
+vadd.vv v12, v12, v12
+vsetvli zero, a0, e8, m8, tu, mu
+vadd.vv v12, v12, v12
+
+# CHECK:      Iterations:        1
+# CHECK-NEXT: Instructions:      4
+# CHECK-NEXT: Total Cycles:      12
+# CHECK-NEXT: Total uOps:        4
+
+# CHECK:      Dispatch Width:    2
+# CHECK-NEXT: uOps Per Cycle:    0.33
+# CHECK-NEXT: IPC:               0.33
+# CHECK-NEXT: Block RThroughput: 18.0
+
+# CHECK:      Instruction Info:
+# CHECK-NEXT: [1]: #uOps
+# CHECK-NEXT: [2]: Latency
+# CHECK-NEXT: [3]: RThroughput
+# CHECK-NEXT: [4]: MayLoad
+# CHECK-NEXT: [5]: MayStore
+# CHECK-NEXT: [6]: HasSideEffects (U)
+
+# CHECK:      [1]    [2]    [3]    [4]    [5]    [6]    Instructions:
+# CHECK-NEXT:  1      3     1.00                  U     vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT:  1      4     2.00                        vadd.vv	v12, v12, v12
+# CHECK-NEXT:  1      3     1.00                  U     vsetvli	zero, a0, e8, m8, tu, mu
+# CHECK-NEXT:  1      4     16.00                       vadd.vv	v12, v12, v12
+
+# CHECK:      Resources:
+# CHECK-NEXT: [0]   - SiFive7FDiv
+# CHECK-NEXT: [1]   - SiFive7IDiv
+# CHECK-NEXT: [2]   - SiFive7PipeA
+# CHECK-NEXT: [3]   - SiFive7PipeB
+# CHECK-NEXT: [4]   - SiFive7PipeV
+# CHECK-NEXT: [5]   - SiFive7VA
+# CHECK-NEXT: [6]   - SiFive7VL
+# CHECK-NEXT: [7]   - SiFive7VS
+
+# CHECK:      Resource pressure per iteration:
+# CHECK-NEXT: [0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]
+# CHECK-NEXT:  -      -     2.00    -     18.00  18.00   -      -
+
+# CHECK:      Resource pressure by instruction:
+# CHECK-NEXT: [0]    [1]    [2]    [3]    [4]    [5]    [6]    [7]    Instructions:
+# CHECK-NEXT:  -      -     1.00    -      -      -      -      -     vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT:  -      -      -      -     2.00   2.00    -      -     vadd.vv	v12, v12, v12
+# CHECK-NEXT:  -      -     1.00    -      -      -      -      -     vsetvli	zero, a0, e8, m8, tu, mu
+# CHECK-NEXT:  -      -      -      -     16.00  16.00   -      -     vadd.vv	v12, v12, v12
+
+# CHECK:      Timeline view:
+# CHECK-NEXT:                     01
+# CHECK-NEXT: Index     0123456789
+
+# CHECK:      [0,0]     DeeE .    ..   vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT: [0,1]     .  DeeeE  ..   vadd.vv	v12, v12, v12
+# CHECK-NEXT: [0,2]     .   DeeE  ..   vsetvli	zero, a0, e8, m8, tu, mu
+# CHECK-NEXT: [0,3]     .    . DeeeE   vadd.vv	v12, v12, v12
+
+# CHECK:      Average Wait times (based on the timeline view):
+# CHECK-NEXT: [0]: Executions
+# CHECK-NEXT: [1]: Average time spent waiting in a scheduler's queue
+# CHECK-NEXT: [2]: Average time spent waiting in a scheduler's queue while ready
+# CHECK-NEXT: [3]: Average time elapsed from WB until retire stage
+
+# CHECK:            [0]    [1]    [2]    [3]
+# CHECK-NEXT: 0.     1     0.0    0.0    0.0       vsetvli	zero, a0, e8, m1, tu, mu
+# CHECK-NEXT: 1.     1     0.0    0.0    0.0       vadd.vv	v12, v12, v12
+# CHECK-NEXT: 2.     1     0.0    0.0    0.0       vsetvli	zero, a0, e8, m8, tu, mu
+# CHECK-NEXT: 3.     1     0.0    0.0    0.0       vadd.vv	v12, v12, v12
+# CHECK-NEXT:        1     0.0    0.0    0.0       <total>

diff  --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h
index 61ee40bacba06d..ce107fd8f3b62e 100644
--- a/llvm/tools/llvm-mca/CodeRegion.h
+++ b/llvm/tools/llvm-mca/CodeRegion.h
@@ -172,22 +172,30 @@ class CodeRegions {
   bool isRegionActive(llvm::StringRef Description) const {
     return ActiveRegions.contains(Description);
   }
+
+  virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
+  virtual void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
+                           UniqueInstrument Instrument) = 0;
+  virtual void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) = 0;
 };
 
 struct AnalysisRegions : public CodeRegions {
   AnalysisRegions(llvm::SourceMgr &S);
 
-  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
-  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
+  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
+                   UniqueInstrument Instrument) override {}
+  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
 };
 
 struct InstrumentRegions : public CodeRegions {
 
   InstrumentRegions(llvm::SourceMgr &S);
 
+  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc) override{};
   void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
-                   UniqueInstrument Instrument);
-  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+                   UniqueInstrument Instrument) override;
+  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc) override;
 
   const SmallVector<Instrument *> getActiveInstruments(llvm::SMLoc Loc) const;
 };

diff  --git a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
index 8321cfb5ad77c4..5241b584b74661 100644
--- a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
+++ b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
@@ -17,7 +17,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
-#include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/SMLoc.h"
@@ -29,46 +28,12 @@ namespace mca {
 // This virtual dtor serves as the anchor for the CodeRegionGenerator class.
 CodeRegionGenerator::~CodeRegionGenerator() {}
 
-// This class provides the callbacks that occur when parsing input assembly.
-class MCStreamerWrapper final : public MCStreamer {
-  CodeRegions &Regions;
-
-public:
-  MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
-      : MCStreamer(Context), Regions(R) {}
-
-  // We only want to intercept the emission of new instructions.
-  void emitInstruction(const MCInst &Inst,
-                       const MCSubtargetInfo & /* unused */) override {
-    Regions.addInstruction(Inst);
-  }
-
-  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
-    return true;
-  }
-
-  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        Align ByteAlignment) override {}
-  void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
-                    uint64_t Size = 0, Align ByteAlignment = Align(1),
-                    SMLoc Loc = SMLoc()) override {}
-  void emitGPRel32Value(const MCExpr *Value) override {}
-  void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
-  void emitCOFFSymbolStorageClass(int StorageClass) override {}
-  void emitCOFFSymbolType(int Type) override {}
-  void endCOFFSymbolDef() override {}
-
-  ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
-    return Regions.getInstructionSequence(Index);
-  }
-};
-
 Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
     const std::unique_ptr<MCInstPrinter> &IP) {
   MCTargetOptions Opts;
   Opts.PreserveAsmComments = false;
   CodeRegions &Regions = getRegions();
-  MCStreamerWrapper Str(Ctx, Regions);
+  MCStreamerWrapper *Str = getMCStreamer();
 
   // Need to initialize an MCTargetStreamer otherwise
   // certain asm directives will cause a segfault.
@@ -76,13 +41,13 @@ Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
   // doesn't show up in the llvm-mca output.
   raw_ostream &OSRef = nulls();
   formatted_raw_ostream FOSRef(OSRef);
-  TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(),
+  TheTarget.createAsmTargetStreamer(*Str, FOSRef, IP.get(),
                                     /*IsVerboseAsm=*/true);
 
   // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
   // comments.
   std::unique_ptr<MCAsmParser> Parser(
-      createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
+      createMCAsmParser(Regions.getSourceMgr(), Ctx, *Str, MAI));
   MCAsmLexer &Lexer = Parser->getLexer();
   MCACommentConsumer *CCP = getCommentConsumer();
   Lexer.setCommentConsumer(CCP);

diff  --git a/llvm/tools/llvm-mca/CodeRegionGenerator.h b/llvm/tools/llvm-mca/CodeRegionGenerator.h
index d1b995d772ca83..68da567f3e0f32 100644
--- a/llvm/tools/llvm-mca/CodeRegionGenerator.h
+++ b/llvm/tools/llvm-mca/CodeRegionGenerator.h
@@ -20,6 +20,7 @@
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/MCA/CustomBehaviour.h"
@@ -77,6 +78,67 @@ class InstrumentRegionCommentConsumer : public MCACommentConsumer {
   /// region of type INSTRUMENATION_TYPE, then it will end the active
   /// one and begin a new one using the new data.
   void HandleComment(SMLoc Loc, StringRef CommentText) override;
+
+  InstrumentManager &getInstrumentManager() { return IM; }
+};
+
+// This class provides the callbacks that occur when parsing input assembly.
+class MCStreamerWrapper : public MCStreamer {
+protected:
+  CodeRegions &Regions;
+
+public:
+  MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R)
+      : MCStreamer(Context), Regions(R) {}
+
+  // We only want to intercept the emission of new instructions.
+  void emitInstruction(const MCInst &Inst,
+                       const MCSubtargetInfo & /* unused */) override {
+    Regions.addInstruction(Inst);
+  }
+
+  bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
+    return true;
+  }
+
+  void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
+                        Align ByteAlignment) override {}
+  void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
+                    uint64_t Size = 0, Align ByteAlignment = Align(1),
+                    SMLoc Loc = SMLoc()) override {}
+  void emitGPRel32Value(const MCExpr *Value) override {}
+  void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
+  void emitCOFFSymbolStorageClass(int StorageClass) override {}
+  void emitCOFFSymbolType(int Type) override {}
+  void endCOFFSymbolDef() override {}
+
+  ArrayRef<MCInst> GetInstructionSequence(unsigned Index) const {
+    return Regions.getInstructionSequence(Index);
+  }
+};
+
+class InstrumentMCStreamer : public MCStreamerWrapper {
+  InstrumentManager &IM;
+
+public:
+  InstrumentMCStreamer(MCContext &Context, mca::InstrumentRegions &R,
+                       InstrumentManager &IM)
+      : MCStreamerWrapper(Context, R), IM(IM) {}
+
+  void emitInstruction(const MCInst &Inst,
+                       const MCSubtargetInfo &MCSI) override {
+    MCStreamerWrapper::emitInstruction(Inst, MCSI);
+
+    // We know that Regions is an InstrumentRegions by the constructor.
+    for (UniqueInstrument &I : IM.createInstruments(Inst)) {
+      StringRef InstrumentKind = I.get()->getDesc();
+      // End InstrumentType region if one is open
+      if (Regions.isRegionActive(InstrumentKind))
+        Regions.endRegion(InstrumentKind, Inst.getLoc());
+      // Start new instrumentation region
+      Regions.beginRegion(InstrumentKind, Inst.getLoc(), std::move(I));
+    }
+  }
 };
 
 /// This abstract class is responsible for parsing the input given to
@@ -121,19 +183,22 @@ class InstrumentRegionGenerator : public virtual CodeRegionGenerator {
 /// generating a CodeRegions instance.
 class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
   const Target &TheTarget;
-  MCContext &Ctx;
   const MCAsmInfo &MAI;
   const MCSubtargetInfo &STI;
   const MCInstrInfo &MCII;
   unsigned AssemblerDialect; // This is set during parsing.
 
+protected:
+  MCContext &Ctx;
+
 public:
   AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,
                          const MCSubtargetInfo &S, const MCInstrInfo &I)
-      : TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I), AssemblerDialect(0) {}
+      : TheTarget(T), MAI(A), STI(S), MCII(I), AssemblerDialect(0), Ctx(C) {}
 
   virtual MCACommentConsumer *getCommentConsumer() = 0;
   virtual CodeRegions &getRegions() = 0;
+  virtual MCStreamerWrapper *getMCStreamer() = 0;
 
   unsigned getAssemblerDialect() const { return AssemblerDialect; }
   Expected<const CodeRegions &>
@@ -143,16 +208,18 @@ class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
 class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
                                          public AsmCodeRegionGenerator {
   AnalysisRegionCommentConsumer CC;
+  MCStreamerWrapper Streamer;
 
 public:
   AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
                              const MCAsmInfo &A, const MCSubtargetInfo &S,
                              const MCInstrInfo &I)
       : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
-        CC(Regions) {}
+        CC(Regions), Streamer(Ctx, Regions) {}
 
   MCACommentConsumer *getCommentConsumer() override { return &CC; };
   CodeRegions &getRegions() override { return Regions; };
+  MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
 
   Expected<const AnalysisRegions &>
   parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
@@ -172,6 +239,7 @@ class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
 class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
                                            public AsmCodeRegionGenerator {
   InstrumentRegionCommentConsumer CC;
+  InstrumentMCStreamer Streamer;
 
 public:
   AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
@@ -179,10 +247,11 @@ class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
                                const MCSubtargetInfo &S, const MCInstrInfo &I,
                                InstrumentManager &IM)
       : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
-        CC(SM, Regions, IM) {}
+        CC(SM, Regions, IM), Streamer(Ctx, Regions, IM) {}
 
   MCACommentConsumer *getCommentConsumer() override { return &CC; };
   CodeRegions &getRegions() override { return Regions; };
+  MCStreamerWrapper *getMCStreamer() override { return &Streamer; }
 
   Expected<const InstrumentRegions &>
   parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override {


        


More information about the llvm-commits mailing list