[llvm] Reland (#120419):[Exegesis][RISCV] Add RISCV support for llvm-exegesis (PR #120467)

Bushev Dmitry via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 18 11:57:19 PST 2024


https://github.com/dybv-sc updated https://github.com/llvm/llvm-project/pull/120467

>From 92344afd6177fe0a29e3f04d9d9b6332f1f68843 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 4 Apr 2024 14:52:53 +0300
Subject: [PATCH 01/37] [Exegesis][RISCV] Add RISCV support for llvm-exegesis

This patch also makes following amendments to core exegesis:
* Added distinction between regular registers aliasing check and registers used as memory address in instruction.
* Added scratch memory space pointer register.
* Added ability for targets to define register name to register number mapping (findRegisterByName).
* General exegesis options were amended:
	* mattr - new option to pass a list of enabled target features
	* opcode-name - this option is amended to accept range of opcodes at once

Llvm-exegesis RISCV port is a result of team effort. Below everyone involved listed.
Co-authored-by: Konstantin Vladimirov <konstantin.vladimirov at syntacore.com>
Co-authored-by: Dmitrii Petrov <dmitrii.petrov at syntacore.com>
Co-authored-by: Dmitry Bushev <dmitry.bushev at syntacore.com>
Co-authored-by: Mark Goncharov <mark.goncharov at syntacore.com>
Co-authored-by: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
---
 llvm/lib/Target/RISCV/RISCVInstrInfo.td       |   4 +-
 .../RISCV/latency-by-extension-A.s            |  59 +++
 .../RISCV/latency-by-extension-C.s            |  65 +++
 .../llvm-exegesis/RISCV/latency-by-load.s     |  60 +++
 .../RISCV/latency-by-opcode-name-FADD_D.s     |  11 +
 .../llvm-exegesis/lib/AArch64/Target.cpp      |   4 +
 llvm/tools/llvm-exegesis/lib/Assembler.cpp    |  10 +-
 llvm/tools/llvm-exegesis/lib/BenchmarkCode.h  |   5 +
 llvm/tools/llvm-exegesis/lib/CMakeLists.txt   |   3 +
 llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp |   8 +
 llvm/tools/llvm-exegesis/lib/CodeTemplate.h   |   6 +
 llvm/tools/llvm-exegesis/lib/LlvmState.cpp    |   6 +
 .../llvm-exegesis/lib/MCInstrDescView.cpp     |  33 +-
 .../tools/llvm-exegesis/lib/MCInstrDescView.h |  13 +-
 llvm/tools/llvm-exegesis/lib/Mips/Target.cpp  |   6 +-
 llvm/tools/llvm-exegesis/lib/PerfHelper.h     |   2 +-
 .../llvm-exegesis/lib/PowerPC/Target.cpp      |   7 +
 .../llvm-exegesis/lib/RISCV/CMakeLists.txt    |  22 +
 .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp |  66 +++
 .../llvm-exegesis/lib/RISCV/RISCVCounters.h   |  31 ++
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 414 ++++++++++++++++++
 .../lib/SerialSnippetGenerator.cpp            |  62 ++-
 llvm/tools/llvm-exegesis/lib/SnippetFile.cpp  |  14 +-
 .../llvm-exegesis/lib/SnippetGenerator.cpp    |  13 +-
 llvm/tools/llvm-exegesis/lib/Target.cpp       |   4 +
 llvm/tools/llvm-exegesis/lib/Target.h         |  19 +
 llvm/tools/llvm-exegesis/lib/X86/Target.cpp   |   6 +
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp    |  68 ++-
 28 files changed, 977 insertions(+), 44 deletions(-)
 create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
 create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
 create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
 create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
 create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
 create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
 create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h
 create mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp

diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index 5747f05ffafd47..e558d3e15a7a01 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -524,7 +524,7 @@ class BranchCC_rri<bits<3> funct3, string opcodestr>
   let isTerminator = 1;
 }
 
-let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0, UseNamedOperandTable = 1 in {
 class Load_ri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>
     : RVInstI<funct3, OPC_LOAD, (outs rty:$rd), (ins GPRMem:$rs1, simm12:$imm12),
               opcodestr, "$rd, ${imm12}(${rs1})">;
@@ -539,7 +539,7 @@ class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
 // Operands for stores are in the order srcreg, base, offset rather than
 // reflecting the order these fields are specified in the instruction
 // encoding.
-let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1, UseNamedOperandTable = 1 in {
 class Store_rri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>
     : RVInstS<funct3, OPC_STORE, (outs),
               (ins rty:$rs2, GPRMem:$rs1, simm12:$imm12),
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
new file mode 100644
index 00000000000000..8cd11ffc3c1f64
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
@@ -0,0 +1,59 @@
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOAND_D -mattr="+a" | FileCheck --check-prefix=TEST1 %s
+
+TEST1:      ---
+TEST1-NEXT: mode: latency
+TEST1-NEXT: key:
+TEST1-NEXT:   instructions:
+TEST1-NEXT:     - 'AMOAND_D [[RE01:X[0-9]+]] X10 [[RE01:X[0-9]+]]'
+TEST1-NEXT: config: ''
+TEST1-NEXT: register_initial_values:
+TEST1-NEXT: - '[[RE01:X[0-9]+]]=0x0'
+TEST1-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOADD_W -mattr="+a" | FileCheck --check-prefix=TEST2 %s
+
+TEST2:      ---
+TEST2-NEXT: mode: latency
+TEST2-NEXT: key:
+TEST2-NEXT:   instructions:
+TEST2-NEXT:     - 'AMOADD_W [[RE02:X[0-9]+]] X10 [[RE02:X[0-9]+]]'
+TEST2-NEXT: config: ''
+TEST2-NEXT: register_initial_values:
+TEST2-NEXT: - '[[RE02:X[0-9]+]]=0x0'
+TEST2-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOMAXU_D -mattr="+a" | FileCheck --check-prefix=TEST3 %s
+
+TEST3:      ---
+TEST3-NEXT: mode: latency
+TEST3-NEXT: key:
+TEST3-NEXT:   instructions:
+TEST3-NEXT:     - 'AMOMAXU_D [[RE03:X[0-9]+]] X10 [[RE03:X[0-9]+]]'
+TEST3-NEXT: config: ''
+TEST3-NEXT: register_initial_values:
+TEST3-NEXT: - '[[RE03:X[0-9]+]]=0x0'
+TEST3-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOMIN_W -mattr="+a" | FileCheck --check-prefix=TEST4 %s
+
+TEST4:      ---
+TEST4-NEXT: mode: latency
+TEST4-NEXT: key:
+TEST4-NEXT:   instructions:
+TEST4-NEXT:     - 'AMOMIN_W [[RE04:X[0-9]+]] X10 [[RE04:X[0-9]+]]'
+TEST4-NEXT: config: ''
+TEST4-NEXT: register_initial_values:
+TEST4-NEXT: - '[[RE04:X[0-9]+]]=0x0'
+TEST4-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOXOR_D -mattr="+a" | FileCheck --check-prefix=TEST5 %s
+
+TEST5:      ---
+TEST5-NEXT: mode: latency
+TEST5-NEXT: key:
+TEST5-NEXT:   instructions:
+TEST5-NEXT:     - 'AMOXOR_D [[RE05:X[0-9]+]] X10 [[RE05:X[0-9]+]]'
+TEST5-NEXT: config: ''
+TEST5-NEXT: register_initial_values:
+TEST5-NEXT: - '[[RE05:X[0-9]+]]=0x0'
+TEST5-LAST: ...
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
new file mode 100644
index 00000000000000..e22ddc2d769554
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
@@ -0,0 +1,65 @@
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ADDI -mattr=+c | FileCheck --check-prefix=TEST1 %s
+
+TEST1:      ---
+TEST1-NEXT: mode: latency
+TEST1-NEXT: key:
+TEST1-NEXT:   instructions:
+TEST1-NEXT:     - 'C_ADDI [[REG01:X[0-9]+]] [[RE02:X[0-9]+]] [[IMM0:i_0x[0-9]+]]'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ADDIW -mattr=+c | FileCheck --check-prefix=TEST2 %s
+
+TEST2:      ---
+TEST2-NEXT: mode: latency
+TEST2-NEXT: key:
+TEST2-NEXT:   instructions:
+TEST2-NEXT:     - 'C_ADDIW [[REG11:X[0-9]+]] [[RE12:X[0-9]+]] [[IMM1:i_0x[0-9]+]]'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ANDI -mattr=+c | FileCheck --check-prefix=TEST3 %s
+
+TEST3:      ---
+TEST3-NEXT: mode: latency
+TEST3-NEXT: key:
+TEST3-NEXT:   instructions:
+TEST3-NEXT:     - 'C_ANDI [[REG31:X[0-9]+]] [[REG32:X[0-9]+]] [[IMM3:i_0x[0-9]+]]'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SLLI -mattr=+c | FileCheck --check-prefix=TEST4 %s
+
+TEST4:      ---
+TEST4-NEXT: mode: latency
+TEST4-NEXT: key:
+TEST4-NEXT:   instructions:
+TEST4-NEXT:     - 'C_SLLI [[REG81:X[0-9]+]] [[REG82:X[0-9]+]] [[IMM8:i_0x[0-9]+]]'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SRAI -mattr=+c | FileCheck --check-prefix=TEST5 %s
+
+TEST5:      ---
+TEST5-NEXT: mode: latency
+TEST5-NEXT: key:
+TEST5-NEXT:   instructions:
+TEST5-NEXT:     - 'C_SRAI [[REG91:X[0-9]+]] [[REG92:X[0-9]+]] [[IMM9:i_0x[0-9]+]]'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SRLI -mattr=+c | FileCheck --check-prefix=TEST6 %s
+
+TEST6:      ---
+TEST6-NEXT: mode: latency
+TEST6-NEXT: key:
+TEST6-NEXT:   instructions:
+TEST6-NEXT:     - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]'
+TEST6-LAST: ...
+
+
+# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=TEST7 %s
+
+TEST7:      ---
+TEST7-NEXT: mode: latency
+TEST7-NEXT: key:
+TEST7-NEXT:   instructions:
+TEST7-NEXT:     - 'C_LD [[REG61:X[0-9]+]] [[REG62:X[0-9]+]] [[IMM6:i_0x[0-9]+]]'
+
+# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_LW -mattr=+c | FileCheck --check-prefix=TEST8 %s
+
+TEST8:      ---
+TEST8-NEXT: mode: latency
+TEST8-NEXT: key:
+TEST8-NEXT:   instructions:
+TEST8-NEXT:     - 'C_LW [[REG71:X[0-9]+]] [[REG72:X[0-9]+]] [[IMM7:i_0x[0-9]+]]'
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
new file mode 100644
index 00000000000000..b685d8759c27c1
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
@@ -0,0 +1,60 @@
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LD | FileCheck --check-prefix=TEST1 %s
+
+TEST1:      ---
+TEST1-NEXT: mode: latency
+TEST1-NEXT: key:
+TEST1-NEXT:   instructions:
+TEST1-NEXT:     - 'LD X10 X10 i_0x0'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LW | FileCheck --check-prefix=TEST2 %s
+
+TEST2:      ---
+TEST2-NEXT: mode: latency
+TEST2-NEXT: key:
+TEST2-NEXT:   instructions:
+TEST2-NEXT:     - 'LW X10 X10 i_0x0'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LH | FileCheck --check-prefix=TEST3 %s
+
+TEST3:      ---
+TEST3-NEXT: mode: latency
+TEST3-NEXT: key:
+TEST3-NEXT:   instructions:
+TEST3-NEXT:     - 'LH X10 X10 i_0x0'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LWU | FileCheck --check-prefix=TEST4 %s
+
+TEST4:      ---
+TEST4-NEXT: mode: latency
+TEST4-NEXT: key:
+TEST4-NEXT:   instructions:
+TEST4-NEXT:     - 'LWU X10 X10 i_0x0'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LBU | FileCheck --check-prefix=TEST5 %s
+
+TEST5:      ---
+TEST5-NEXT: mode: latency
+TEST5-NEXT: key:
+TEST5-NEXT:   instructions:
+TEST5-NEXT:     - 'LBU X10 X10 i_0x0'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LUI 2>&1 | FileCheck --check-prefix=TEST6 %s
+
+TEST6: LUI: No strategy found to make the execution serial
+
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=TEST7 %s
+
+TEST7:      ---
+TEST7-NEXT: mode: latency
+TEST7-NEXT: key:
+TEST7-NEXT:   instructions:
+TEST7-NEXT:     - 'LB X10 X10 i_0x0'
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LR_W_RL -mattr="+a" | FileCheck --check-prefix=TEST8 %s
+
+TEST8:      ---
+TEST8-NEXT: mode: latency
+TEST8-NEXT: key:
+TEST8-NEXT:   instructions:
+TEST8-NEXT:     - 'LR_W_RL X10 X10'
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
new file mode 100644
index 00000000000000..fd58bfb7c1a841
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
@@ -0,0 +1,11 @@
+# RUN: llvm-exegesis -mtriple=riscv64-unknown-linux-gnu -mode=latency --benchmark-phase=assemble-measured-code -mattr=+d -opcode-name=FADD_D | FileCheck %s
+
+CHECK:      ---
+CHECK-NEXT: mode: latency
+CHECK-NEXT: key:
+CHECK-NEXT:   instructions:
+CHECK-NEXT:     - 'FADD_D [[REG1:F[0-9]+_D]] [[REG2:F[0-9]+_D]] [[REG3:F[0-9]+_D]] i_0x7'
+CHECK-NEXT: config: ''
+CHECK-NEXT: register_initial_values:
+CHECK-DAG: - '[[REG1]]=0x0'
+CHECK-LAST: ...
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 51846862f0a734..6a3eba2459556d 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -45,6 +45,10 @@ class ExegesisAArch64Target : public ExegesisTarget {
       : ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}
 
 private:
+  unsigned findRegisterByName(const StringRef RegName) const override {
+    return AArch64::NoRegister;
+  }
+
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override {
     if (AArch64::GPR32RegClass.contains(Reg))
diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
index 13c8c2048a5c03..1e2a324cc8fc68 100644
--- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
@@ -168,7 +168,15 @@ void BasicBlockFiller::addInstruction(const MCInst &Inst, const DebugLoc &DL) {
     } else if (Op.isImm()) {
       Builder.addImm(Op.getImm());
     } else if (!Op.isValid()) {
-      llvm_unreachable("Operand is not set");
+      std::string Message;
+      llvm::raw_string_ostream MessageOut(Message);
+      MessageOut << "Operand is not set: Instr: ";
+      Inst.dump_pretty(MessageOut, MCII->getName(Inst.getOpcode()));
+      MessageOut << "; OpIndex: " << OpIndex;
+      const MCOperandInfo &OperandInfo = MCID.operands()[OpIndex];
+      MessageOut << "; OpInfo.OperandType: "
+                 << static_cast<uint32_t>(OperandInfo.OperandType);
+      report_fatal_error(Twine(Message));
     } else {
       llvm_unreachable("Not yet implemented");
     }
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
index 1db8472e99f7c9..4d5fc241fde0d9 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
@@ -17,6 +17,11 @@
 namespace llvm {
 namespace exegesis {
 
+struct ScratchMemoryStore {
+  unsigned Reg;
+  unsigned Offset;
+};
+
 // A collection of instructions that are to be assembled, executed and measured.
 struct BenchmarkCode {
   BenchmarkKey Key;
diff --git a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
index 414b49e5e021c2..d95c37ff5426bd 100644
--- a/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
+++ b/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
@@ -12,6 +12,9 @@ endif()
 if (LLVM_TARGETS_TO_BUILD MATCHES "Mips")
   list(APPEND LLVM_EXEGESIS_TARGETS "Mips")
 endif()
+if(LLVM_TARGETS_TO_BUILD MATCHES "RISCV")
+  list(APPEND LLVM_EXEGESIS_TARGETS "RISCV")
+endif()
 
 set(LLVM_EXEGESIS_TARGETS ${LLVM_EXEGESIS_TARGETS} PARENT_SCOPE)
 
diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
index fd156ee01e7ce5..9b5bfe3196dcda 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
@@ -57,6 +57,14 @@ const MCOperand &InstructionTemplate::getValueFor(const Operand &Op) const {
   return getValueFor(Instr->Variables[Op.getVariableIndex()]);
 }
 
+MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) {
+  return getValueFor(Instr->Variables[OpIdx]);
+}
+
+const MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) const {
+  return getValueFor(Instr->Variables[OpIdx]);
+}
+
 bool InstructionTemplate::hasImmediateVariables() const {
   return any_of(Instr->Variables, [this](const Variable &Var) {
     return Instr->getPrimaryOperand(Var).isImmediate();
diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
index 7aca224302a1ff..85fcb4e908f017 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
@@ -35,6 +35,8 @@ struct InstructionTemplate {
   const MCOperand &getValueFor(const Variable &Var) const;
   MCOperand &getValueFor(const Operand &Op);
   const MCOperand &getValueFor(const Operand &Op) const;
+  MCOperand &getValueFor(unsigned OpIdx);
+  const MCOperand &getValueFor(unsigned OpIdx) const;
   bool hasImmediateVariables() const;
   const Instruction &getInstr() const { return *Instr; }
   ArrayRef<MCOperand> getVariableValues() const { return VariableValues; }
@@ -133,6 +135,10 @@ struct CodeTemplate {
   // the pointer to this memory is passed in to the function.
   unsigned ScratchSpacePointerInReg = 0;
 
+  // Require to pre-store value of a given register (fisrt)
+  // to scratch memory with given offset (second)
+  SmallVector<std::pair<unsigned, unsigned>, 2> PreinitScratchMemory;
+
 #if defined(__GNUC__) && (defined(__clang__) || LLVM_GNUC_PREREQ(8, 0, 0))
   // FIXME: GCC7 bug workaround. Drop #if after GCC7 no longer supported.
 private:
diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
index 4c44c59286ccfb..713b09937d57a3 100644
--- a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
+++ b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
@@ -45,6 +45,12 @@ Expected<LLVMState> LLVMState::Create(std::string TripleName,
   if (CpuName == "native")
     CpuName = std::string(sys::getHostCPUName());
 
+  if (CpuName.empty()) {
+    std::unique_ptr<MCSubtargetInfo> Empty_STI(
+        TheTarget->createMCSubtargetInfo(TripleName, "", ""));
+    CpuName = Empty_STI->getAllProcessorDescriptions().begin()->Key;
+  }
+
   std::unique_ptr<MCSubtargetInfo> STI(
       TheTarget->createMCSubtargetInfo(TripleName, CpuName, ""));
   assert(STI && "Unable to create subtarget info!");
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
index 9c926d1fc61124..7705d9af4057e8 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
@@ -89,17 +89,17 @@ const BitVector *BitVectorCache::getUnique(BitVector &&BV) const {
   return Entry.get();
 }
 
-Instruction::Instruction(const MCInstrDesc *Description, StringRef Name,
-                         SmallVector<Operand, 8> Operands,
-                         SmallVector<Variable, 4> Variables,
-                         const BitVector *ImplDefRegs,
-                         const BitVector *ImplUseRegs,
-                         const BitVector *AllDefRegs,
-                         const BitVector *AllUseRegs)
+Instruction::Instruction(
+    const MCInstrDesc *Description, StringRef Name,
+    SmallVector<Operand, 8> Operands, SmallVector<Variable, 4> Variables,
+    const BitVector *ImplDefRegs, const BitVector *ImplUseRegs,
+    const BitVector *AllDefRegs, const BitVector *AllUseRegs,
+    const BitVector *MemoryRegs, const BitVector *NotMemoryRegs)
     : Description(*Description), Name(Name), Operands(std::move(Operands)),
       Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs),
       ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs),
-      AllUseRegs(*AllUseRegs) {}
+      AllUseRegs(*AllUseRegs), MemoryRegs(*MemoryRegs),
+      NotMemoryRegs(*NotMemoryRegs) {}
 
 std::unique_ptr<Instruction>
 Instruction::create(const MCInstrInfo &InstrInfo,
@@ -166,6 +166,9 @@ Instruction::create(const MCInstrInfo &InstrInfo,
   BitVector ImplUseRegs = RATC.emptyRegisters();
   BitVector AllDefRegs = RATC.emptyRegisters();
   BitVector AllUseRegs = RATC.emptyRegisters();
+  BitVector MemoryRegs = RATC.emptyRegisters();
+  BitVector NotMemoryRegs = RATC.emptyRegisters();
+
   for (const auto &Op : Operands) {
     if (Op.isReg()) {
       const auto &AliasingBits = Op.getRegisterAliasing().aliasedBits();
@@ -177,6 +180,10 @@ Instruction::create(const MCInstrInfo &InstrInfo,
         ImplDefRegs |= AliasingBits;
       if (Op.isUse() && Op.isImplicit())
         ImplUseRegs |= AliasingBits;
+      if (Op.isUse() && Op.isMemory())
+        MemoryRegs |= AliasingBits;
+      if (Op.isUse() && !Op.isMemory())
+        NotMemoryRegs |= AliasingBits;
     }
   }
   // Can't use make_unique because constructor is private.
@@ -185,7 +192,9 @@ Instruction::create(const MCInstrInfo &InstrInfo,
       std::move(Variables), BVC.getUnique(std::move(ImplDefRegs)),
       BVC.getUnique(std::move(ImplUseRegs)),
       BVC.getUnique(std::move(AllDefRegs)),
-      BVC.getUnique(std::move(AllUseRegs))));
+      BVC.getUnique(std::move(AllUseRegs)),
+      BVC.getUnique(std::move(MemoryRegs)),
+      BVC.getUnique(std::move(NotMemoryRegs))));
 }
 
 const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
@@ -240,6 +249,12 @@ bool Instruction::hasAliasingRegisters(
                                      ForbiddenRegisters);
 }
 
+bool Instruction::hasAliasingNotMemoryRegisters(
+    const BitVector &ForbiddenRegisters) const {
+  return anyCommonExcludingForbidden(AllDefRegs, NotMemoryRegs,
+                                     ForbiddenRegisters);
+}
+
 bool Instruction::hasOneUseOrOneDef() const {
   return AllDefRegs.count() || AllUseRegs.count();
 }
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
index f8ebc07d01f35e..edc1a341b27cee 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
@@ -133,6 +133,12 @@ struct Instruction {
   // aliasing Use and Def registers.
   bool hasAliasingRegisters(const BitVector &ForbiddenRegisters) const;
 
+  // Whether this instruction is self aliasing through some registers.
+  // Repeating this instruction may execute sequentially by picking aliasing
+  // Def and Not Memory Use registers. It may also execute in parallel by
+  // picking non aliasing Def and Not Memory Use registers.
+  bool hasAliasingNotMemoryRegisters(const BitVector &ForbiddenRegisters) const;
+
   // Whether this instruction's registers alias with OtherInstr's registers.
   bool hasAliasingRegistersThrough(const Instruction &OtherInstr,
                                    const BitVector &ForbiddenRegisters) const;
@@ -160,12 +166,17 @@ struct Instruction {
   const BitVector &ImplUseRegs; // The set of aliased implicit use registers.
   const BitVector &AllDefRegs;  // The set of all aliased def registers.
   const BitVector &AllUseRegs;  // The set of all aliased use registers.
+  const BitVector &MemoryRegs;  // The set of all aliased memory use registers.
+  const BitVector
+      &NotMemoryRegs; // The set of all aliased not memory use registers.
+
 private:
   Instruction(const MCInstrDesc *Description, StringRef Name,
               SmallVector<Operand, 8> Operands,
               SmallVector<Variable, 4> Variables, const BitVector *ImplDefRegs,
               const BitVector *ImplUseRegs, const BitVector *AllDefRegs,
-              const BitVector *AllUseRegs);
+              const BitVector *AllUseRegs, const BitVector *MemoryRegs,
+              const BitVector *NotMemoryRegs);
 };
 
 // Instructions are expensive to instantiate. This class provides a cache of
diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
index 731e037c240df0..917c055e29d8f5 100644
--- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
@@ -62,7 +62,7 @@ class ExegesisMipsTarget : public ExegesisTarget {
   unsigned getMaxMemoryAccessSize() const override { return 64; }
   void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
                           unsigned Offset) const override;
-
+  unsigned findRegisterByName(const StringRef RegName) const override;
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override;
   bool matchesArch(Triple::ArchType Arch) const override {
@@ -148,6 +148,10 @@ void ExegesisMipsTarget::fillMemoryOperands(InstructionTemplate &IT,
   setMemOp(IT, 2, MCOperand::createImm(Offset)); // Disp
 }
 
+unsigned ExegesisMipsTarget::findRegisterByName(const StringRef RegName) const {
+  return Mips::NoRegister;
+}
+
 std::vector<MCInst> ExegesisMipsTarget::setRegTo(const MCSubtargetInfo &STI,
                                                  unsigned Reg,
                                                  const APInt &Value) const {
diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
index 4a825b293b7169..1e0fca73808630 100644
--- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h
+++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
@@ -119,7 +119,7 @@ class CounterGroup {
   virtual void start();
 
   /// Stops the measurement of the event.
-  void stop();
+  virtual void stop();
 
   /// Returns the current value of the counter or error if it cannot be read.
   /// FunctionBytes: The benchmark function being executed.
diff --git a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
index 5c944c90384e3e..0031fb89118ddf 100644
--- a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
@@ -33,6 +33,8 @@ class ExegesisPowerPCTarget : public ExegesisTarget {
       : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {}
 
 private:
+  unsigned findRegisterByName(const StringRef RegName) const override;
+
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override;
   bool matchesArch(Triple::ArchType Arch) const override {
@@ -92,6 +94,11 @@ void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
   setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg));   // BaseReg
 }
 
+unsigned
+ExegesisPowerPCTarget::findRegisterByName(const StringRef RegName) const {
+  return PPC::NoRegister;
+}
+
 std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
                                                     unsigned Reg,
                                                     const APInt &Value) const {
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
new file mode 100644
index 00000000000000..ea0ced1786a0cc
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
@@ -0,0 +1,22 @@
+include_directories(
+  ${LLVM_MAIN_SRC_DIR}/lib/Target/RISCV
+  ${LLVM_BINARY_DIR}/lib/Target/RISCV
+)
+
+set(LLVM_LINK_COMPONENTS
+  RISCV
+  Exegesis
+  Core
+  Support
+  )
+
+add_llvm_library(LLVMExegesisRISCV
+  DISABLE_LLVM_LINK_LLVM_DYLIB
+  STATIC
+  Target.cpp
+  RISCVCounters.cpp
+
+  DEPENDS
+  intrinsics_gen
+  RISCVCommonTableGen
+  )
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
new file mode 100644
index 00000000000000..1d421b3c31c36e
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -0,0 +1,66 @@
+//===-- RISCVCounters.cpp ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVCounters.h"
+
+namespace llvm {
+namespace exegesis {
+
+// This implementation of RISCV target for Exegesis doesn't use libpfm
+// and provides manual implementation of performance counters.
+
+inline uint64_t getRISCVCpuCyclesCount() {
+#ifdef __riscv
+  uint64_t Counter;
+  asm("csrr %0, cycle" : "=r"(Counter)::"memory");
+  return Counter;
+#else
+  return 0;
+#endif
+}
+
+class RISCVCpuCyclesCounter : public pfm::CounterGroup {
+  uint64_t StartValue;
+  uint64_t EndValue;
+  uint64_t MeasurementCycles;
+
+public:
+  explicit RISCVCpuCyclesCounter(pfm::PerfEvent &&Event);
+
+  void start() override { StartValue = getRISCVCpuCyclesCount(); }
+
+  void stop() override { EndValue = getRISCVCpuCyclesCount(); }
+
+  Expected<llvm::SmallVector<int64_t, 4>>
+  readOrError(StringRef FunctionBytes) const override;
+};
+
+RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
+    : CounterGroup(std::move(Event), {}) {
+  StartValue = getRISCVCpuCyclesCount();
+  EndValue = getRISCVCpuCyclesCount();
+  MeasurementCycles = EndValue - StartValue;
+  if (MeasurementCycles == 0) {
+    report_fatal_error("MeasurementCycles == 0, "
+                       "performance counters are not configured.");
+  }
+  StartValue = EndValue = 0;
+}
+
+Expected<SmallVector<int64_t, 4>>
+RISCVCpuCyclesCounter::readOrError(StringRef FunctionBytes) const {
+  uint64_t Counter = EndValue - StartValue - MeasurementCycles;
+  return SmallVector<int64_t, 4>({static_cast<int64_t>(Counter)});
+}
+std::unique_ptr<pfm::CounterGroup>
+createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event) {
+  return std::make_unique<RISCVCpuCyclesCounter>(std::move(Event));
+}
+
+} // namespace exegesis
+} // namespace llvm
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h
new file mode 100644
index 00000000000000..203f6af76aaaf8
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h
@@ -0,0 +1,31 @@
+//===-- RISCVCounters.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// RISC-V perf counters.
+///
+/// More info at: https://lwn.net/Articles/680985
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H
+#define LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H
+
+#include "../PerfHelper.h"
+#include "../Target.h"
+#include <memory>
+
+namespace llvm {
+namespace exegesis {
+
+std::unique_ptr<pfm::CounterGroup>
+createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event);
+
+} // namespace exegesis
+} // namespace llvm
+
+#endif // LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
new file mode 100644
index 00000000000000..c6d392b3b6d7a2
--- /dev/null
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -0,0 +1,414 @@
+//===-- Target.cpp ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../Target.h"
+
+#include "RISCVCounters.h"
+
+#include "MCTargetDesc/RISCVBaseInfo.h"
+#include "MCTargetDesc/RISCVMCTargetDesc.h"
+#include "MCTargetDesc/RISCVMatInt.h"
+#include "RISCVInstrInfo.h"
+
+// include computeAvailableFeatures and computeRequiredFeatures.
+#define GET_COMPUTE_FEATURES
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "RISCVGenInstrInfo.inc"
+#undef GET_COMPUTE_FEATURES
+#undef GET_AVAILABLE_OPCODE_CHECKER
+
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+
+#include <vector>
+
+namespace llvm {
+namespace exegesis {
+
+namespace {
+
+// TODO move perf counter data to td files (although it looks like an overkill
+// of sorts)
+
+static const char *RISCVPfmCounterNames[] = {
+    "CPU_CYCLES", // 0
+};
+
+static const PfmCountersInfo RISCVDefaultPfmCounters = {
+    RISCVPfmCounterNames[0], // Cycle counter
+    nullptr,                 // No uops counter.
+    nullptr,                 // No issue counters.
+    0};
+
+static const CpuAndPfmCounters RISCVCpuPfmCounters[] = {
+    {"", &RISCVDefaultPfmCounters},
+};
+
+class ExegesisRISCVTarget : public ExegesisTarget {
+public:
+  ExegesisRISCVTarget();
+
+  Expected<std::unique_ptr<pfm::CounterGroup>>
+  createCounter(StringRef CounterName, const LLVMState &State,
+                ArrayRef<const char *> ValidationCounters,
+                const pid_t ProcessID) const override;
+
+  bool checkOpcodeSupported(int Opcode,
+                            const MCSubtargetInfo &SI) const override;
+
+  unsigned findRegisterByName(const StringRef RegName) const override;
+
+  bool matchesArch(Triple::ArchType Arch) const override;
+
+  std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
+                               const APInt &Value) const override;
+
+  unsigned getDefaultLoopCounterRegister(const Triple &) const override;
+
+  void decrementLoopCounterAndJump(MachineBasicBlock &MBB,
+                                   MachineBasicBlock &TargetMBB,
+                                   const MCInstrInfo &MII,
+                                   unsigned LoopRegister) const override;
+
+  unsigned getScratchMemoryRegister(const Triple &TT) const override;
+
+  void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
+                          unsigned Offset) const override;
+
+  virtual std::vector<MCInst>
+  storeRegValueToScratch(const MCSubtargetInfo &STI, unsigned Reg,
+                         unsigned Offset) const override;
+  ArrayRef<unsigned> getUnavailableRegisters() const override;
+
+  Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var,
+                                 MCOperand &AssignedValue,
+                                 const BitVector &ForbiddenRegs) const override;
+
+  void processInstructionReservedRegs(InstructionTemplate &IT) const override;
+
+  std::vector<InstructionTemplate>
+  generateInstructionVariants(const Instruction &Instr,
+                              unsigned MaxConfigsPerOpcode) const override;
+};
+
+ExegesisRISCVTarget::ExegesisRISCVTarget()
+    : ExegesisTarget(RISCVCpuPfmCounters, RISCV_MC::isOpcodeAvailable) {}
+
+Expected<std::unique_ptr<pfm::CounterGroup>> ExegesisRISCVTarget::createCounter(
+    StringRef CounterName, const LLVMState &State,
+    ArrayRef<const char *> ValidationCounters, const pid_t ProcessID) const {
+  if (CounterName == RISCVPfmCounterNames[0]) {
+    return createRISCVCpuCyclesCounter(pfm::PerfEvent(CounterName));
+  }
+  return make_error<Failure>(Twine("Unsupported performance counter '")
+                                 .concat(CounterName)
+                                 .concat("'"));
+}
+
+bool ExegesisRISCVTarget::checkOpcodeSupported(
+    int Opcode, const MCSubtargetInfo &SI) const {
+  auto Features = SI.getFeatureBits();
+  FeatureBitset AvailableFeatures =
+      RISCV_MC::computeAvailableFeatures(Features);
+  FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode);
+  FeatureBitset MissingFeatures =
+      (AvailableFeatures & RequiredFeatures) ^ RequiredFeatures;
+  return MissingFeatures.none();
+}
+
+#define GET_REGISTER_MATCHER
+#include "RISCVGenAsmMatcher.inc"
+
+unsigned
+ExegesisRISCVTarget::findRegisterByName(const StringRef RegName) const {
+  unsigned Reg;
+  if ((Reg = MatchRegisterName(RegName)))
+    return Reg;
+  if ((Reg = MatchRegisterAltName(RegName)))
+    return Reg;
+  return RISCV::NoRegister;
+}
+
+bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const {
+  return Arch == Triple::riscv32 || Arch == Triple::riscv64;
+}
+
+// Stores constant value to a general-purpose (integer) register.
+static std::vector<MCInst> loadIntReg(const MCSubtargetInfo &STI, unsigned Reg,
+                                      const APInt &Value) {
+  RISCVMatInt::InstSeq InstSeq =
+      RISCVMatInt::generateInstSeq(Value.getSExtValue(), STI);
+  // First instruction has form 'Op DestReg, X0, Imm'
+  MCRegister SrcReg = RISCV::X0;
+  MCRegister DestReg = Reg;
+  std::vector<MCInst> MatIntInstrs;
+  MatIntInstrs.reserve(InstSeq.size());
+  for (const RISCVMatInt::Inst &Inst : InstSeq) {
+    switch (Inst.getOpndKind()) {
+    case RISCVMatInt::Imm:
+      MatIntInstrs.push_back(
+          MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.getImm()));
+      break;
+    case RISCVMatInt::RegX0:
+      MatIntInstrs.push_back(MCInstBuilder(RISCV::ADD_UW)
+                                 .addReg(DestReg)
+                                 .addReg(SrcReg)
+                                 .addReg(RISCV::X0));
+      break;
+    case RISCVMatInt::RegReg:
+      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
+                                 .addReg(DestReg)
+                                 .addReg(SrcReg)
+                                 .addReg(SrcReg));
+      break;
+    case RISCVMatInt::RegImm:
+      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
+                                 .addReg(DestReg)
+                                 .addReg(SrcReg)
+                                 .addImm(Inst.getImm()));
+      break;
+    default:
+      llvm_unreachable("Unexpected kind!");
+    }
+    // Further instructions have form 'Op DestReg, DestReg, Imm'
+    SrcReg = DestReg;
+  }
+  return MatIntInstrs;
+}
+
+const unsigned ScratchIntReg = RISCV::X30; // t5
+
+// Stores constant bits to a floating-point register.
+static std::vector<MCInst> loadFPRegBits(const MCSubtargetInfo &STI,
+                                         unsigned Reg, const APInt &Bits,
+                                         unsigned FmvOpcode) {
+  std::vector<MCInst> Instrs = loadIntReg(STI, ScratchIntReg, Bits);
+  Instrs.push_back(MCInstBuilder(FmvOpcode).addReg(Reg).addReg(ScratchIntReg));
+  return Instrs;
+}
+
+// main idea is:
+// we support APInt only if (represented as double) it have zero fractional
+// part: 1.0, 2.0, 3.0, etc... then we can do the trick: write int to tmp reg t5
+// and then do FCVT this is only reliable thing in 32-bit mode, otherwise we
+// need to use __floatsidf
+static std::vector<MCInst> loadFP64RegBits32(const MCSubtargetInfo &STI,
+                                             unsigned Reg, const APInt &Bits) {
+  double D = Bits.bitsToDouble();
+  double IPart;
+  double FPart = std::modf(D, &IPart);
+
+  if (std::abs(FPart) > std::numeric_limits<double>::epsilon()) {
+    errs() << "loadFP64RegBits32 is not implemented for doubles like " << D
+           << ", please remove fractional part\n";
+    return {};
+  }
+
+  std::vector<MCInst> Instrs = loadIntReg(STI, ScratchIntReg, Bits);
+  Instrs.push_back(
+      MCInstBuilder(RISCV::FCVT_D_W).addReg(Reg).addReg(ScratchIntReg));
+  return Instrs;
+}
+
+static MCInst nop() {
+  // ADDI X0, X0, 0
+  return MCInstBuilder(RISCV::ADDI)
+      .addReg(RISCV::X0)
+      .addReg(RISCV::X0)
+      .addImm(0);
+}
+
+static bool isVectorRegList(unsigned Reg) {
+  return RISCV::VRM2RegClass.contains(Reg) ||
+         RISCV::VRM4RegClass.contains(Reg) ||
+         RISCV::VRM8RegClass.contains(Reg) ||
+         RISCV::VRN2M1RegClass.contains(Reg) ||
+         RISCV::VRN2M2RegClass.contains(Reg) ||
+         RISCV::VRN2M4RegClass.contains(Reg) ||
+         RISCV::VRN3M1RegClass.contains(Reg) ||
+         RISCV::VRN3M2RegClass.contains(Reg) ||
+         RISCV::VRN4M1RegClass.contains(Reg) ||
+         RISCV::VRN4M2RegClass.contains(Reg) ||
+         RISCV::VRN5M1RegClass.contains(Reg) ||
+         RISCV::VRN6M1RegClass.contains(Reg) ||
+         RISCV::VRN7M1RegClass.contains(Reg) ||
+         RISCV::VRN8M1RegClass.contains(Reg);
+}
+
+std::vector<MCInst> ExegesisRISCVTarget::setRegTo(const MCSubtargetInfo &STI,
+                                                  unsigned Reg,
+                                                  const APInt &Value) const {
+  if (RISCV::GPRRegClass.contains(Reg))
+    return loadIntReg(STI, Reg, Value);
+  if (RISCV::FPR16RegClass.contains(Reg))
+    return loadFPRegBits(STI, Reg, Value, RISCV::FMV_H_X);
+  if (RISCV::FPR32RegClass.contains(Reg))
+    return loadFPRegBits(STI, Reg, Value, RISCV::FMV_W_X);
+  if (RISCV::FPR64RegClass.contains(Reg)) {
+    if (STI.hasFeature(RISCV::Feature64Bit))
+      return loadFPRegBits(STI, Reg, Value, RISCV::FMV_D_X);
+    else
+      return loadFP64RegBits32(STI, Reg, Value);
+  }
+  if (Reg == RISCV::FRM || Reg == RISCV::VL || Reg == RISCV::VLENB ||
+      Reg == RISCV::VTYPE || RISCV::GPRPairRegClass.contains(Reg) ||
+      RISCV::VRRegClass.contains(Reg) || isVectorRegList(Reg)) {
+    // Don't initialize:
+    // - FRM
+    // - VL, VLENB, VTYPE
+    // - vector registers (and vector register lists)
+    // - Zfinx registers
+    // Generate 'NOP' so that exegesis treats such registers as initialized
+    // (it tries to initialize them with '0' anyway).
+    return {nop()};
+  }
+  errs() << "setRegTo is not implemented for Reg " << Reg
+         << ", results will be unreliable\n";
+  return {};
+}
+
+const unsigned DefaultLoopCounterReg = RISCV::X31; // t6
+const unsigned ScratchMemoryReg = RISCV::X10;      // a0
+
+unsigned
+ExegesisRISCVTarget::getDefaultLoopCounterRegister(const Triple &) const {
+  return DefaultLoopCounterReg;
+}
+
+void ExegesisRISCVTarget::decrementLoopCounterAndJump(
+    MachineBasicBlock &MBB, MachineBasicBlock &TargetMBB,
+    const MCInstrInfo &MII, unsigned LoopRegister) const {
+  BuildMI(&MBB, DebugLoc(), MII.get(RISCV::ADDI))
+      .addDef(LoopRegister)
+      .addUse(LoopRegister)
+      .addImm(-1);
+  BuildMI(&MBB, DebugLoc(), MII.get(RISCV::BNE))
+      .addUse(LoopRegister)
+      .addUse(RISCV::X0)
+      .addMBB(&TargetMBB);
+}
+
+unsigned ExegesisRISCVTarget::getScratchMemoryRegister(const Triple &TT) const {
+  return ScratchMemoryReg; // a0
+}
+
+void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT,
+                                             unsigned Reg,
+                                             unsigned Offset) const {
+  // TODO: for now we ignore Offset because have no way
+  // to detect it in instruction.
+  auto &I = IT.getInstr();
+
+  auto MemOpIt =
+      find_if(I.Operands, [](Operand const &Op) { return Op.isMemory(); });
+  assert(MemOpIt != I.Operands.end() &&
+         "Instruction must have memory operands");
+
+  auto &MemOp = *MemOpIt;
+
+  assert(MemOp.isReg() && "Memory operand expected to be register");
+
+  IT.getValueFor(MemOp) = MCOperand::createReg(Reg);
+}
+
+std::vector<MCInst> ExegesisRISCVTarget::storeRegValueToScratch(
+    const MCSubtargetInfo &STI, unsigned Reg, unsigned Offset) const {
+  std::vector<MCInst> Ret;
+
+  if (RISCV::GPRRegClass.contains(Reg)) {
+    Ret.push_back(MCInstBuilder(RISCV::SW)
+                      .addReg(Reg)
+                      .addReg(ScratchMemoryReg)
+                      .addImm(Offset));
+    return Ret;
+  }
+
+  errs() << "Failed to store value of " << Reg << " register to scratch memory";
+  return {nop()};
+}
+
+const unsigned UnavailableRegisters[4] = {RISCV::X0, DefaultLoopCounterReg,
+                                          ScratchIntReg, ScratchMemoryReg};
+
+ArrayRef<unsigned> ExegesisRISCVTarget::getUnavailableRegisters() const {
+  return ArrayRef(UnavailableRegisters);
+}
+
+Error ExegesisRISCVTarget::randomizeTargetMCOperand(
+    const Instruction &Instr, const Variable &Var, MCOperand &AssignedValue,
+    const BitVector &ForbiddenRegs) const {
+  uint8_t OperandType =
+      Instr.getPrimaryOperand(Var).getExplicitOperandInfo().OperandType;
+
+  switch (OperandType) {
+  case RISCVOp::OPERAND_FRMARG:
+    AssignedValue = MCOperand::createImm(RISCVFPRndMode::DYN);
+    break;
+  case RISCVOp::OPERAND_SIMM10_LSB0000_NONZERO:
+    AssignedValue = MCOperand::createImm(0b1 << 4);
+    break;
+  case RISCVOp::OPERAND_SIMM6_NONZERO:
+  case RISCVOp::OPERAND_UIMMLOG2XLEN_NONZERO:
+    AssignedValue = MCOperand::createImm(1);
+    break;
+  default:
+    if (OperandType >= RISCVOp::OPERAND_FIRST_RISCV_IMM &&
+        OperandType <= RISCVOp::OPERAND_LAST_RISCV_IMM)
+      AssignedValue = MCOperand::createImm(0);
+  }
+  return Error::success();
+}
+
+// Process instructions that used ReservedRegisters.
+// We must not create instructions that used rd=x0. But for some of them in C
+// extension we use registers in which we are really not going to write to.
+// Registers were reserved in RISCVRegisterInfo.cpp using markSuperRegs function
+// and should not be redeclared. Thus we must set appropriate register
+// explicitly for each instruction according to RVC spec.
+void ExegesisRISCVTarget::processInstructionReservedRegs(
+    InstructionTemplate &IT) const {
+  MCOperand &AssignedValue = IT.getValueFor(0);
+
+  switch (IT.getOpcode()) {
+  case RISCV::C_ADDI16SP:
+    AssignedValue = MCOperand::createReg(RISCV::X2);
+    break;
+  case RISCV::C_ADDI_NOP:
+  case RISCV::C_ADD_HINT:
+  case RISCV::C_SLLI_HINT:
+    AssignedValue = MCOperand::createReg(RISCV::X0);
+    break;
+  default:
+    break;
+  }
+}
+
+std::vector<InstructionTemplate>
+ExegesisRISCVTarget::generateInstructionVariants(
+    const Instruction &Instr, unsigned int MaxConfigsPerOpcode) const {
+  InstructionTemplate IT{&Instr};
+  for (const Operand &Op : Instr.Operands) {
+    if (Op.isMemory()) {
+      IT.getValueFor(Op) = MCOperand::createReg(ScratchMemoryReg);
+    }
+  }
+  return {IT};
+}
+
+} // anonymous namespace
+
+static ExegesisTarget *getTheRISCVExegesisTarget() {
+  static ExegesisRISCVTarget Target;
+  return &Target;
+}
+
+void InitializeRISCVExegesisTarget() {
+  ExegesisTarget::registerTarget(getTheRISCVExegesisTarget());
+}
+
+} // namespace exegesis
+} // namespace llvm
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 7100b51bbb7298..4971c5b6097254 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -52,13 +52,16 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
       continue;
     if (OtherOpcode == Instr->Description.getOpcode())
       continue;
+    if (!State.getExegesisTarget().checkOpcodeSupported(
+            OtherOpcode, State.getSubtargetInfo()))
+      continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
     const MCInstrDesc &OtherInstrDesc = OtherInstr.Description;
     // Ignore instructions that we cannot run.
     if (OtherInstrDesc.isPseudo() || OtherInstrDesc.usesCustomInsertionHook() ||
         OtherInstrDesc.isBranch() || OtherInstrDesc.isIndirectBranch() ||
         OtherInstrDesc.isCall() || OtherInstrDesc.isReturn()) {
-          continue;
+      continue;
     }
     if (OtherInstr.hasMemoryOperands())
       continue;
@@ -81,12 +84,10 @@ static ExecutionMode getExecutionModes(const Instruction &Instr,
     EM |= ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS;
   if (Instr.hasMemoryOperands())
     EM |= ExecutionMode::SERIAL_VIA_MEMORY_INSTR;
-  else {
-    if (Instr.hasAliasingRegisters(ForbiddenRegisters))
-      EM |= ExecutionMode::SERIAL_VIA_EXPLICIT_REGS;
-    if (Instr.hasOneUseOrOneDef())
-      EM |= ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR;
-  }
+  if (Instr.hasAliasingNotMemoryRegisters(ForbiddenRegisters))
+    EM |= ExecutionMode::SERIAL_VIA_EXPLICIT_REGS;
+  if (Instr.hasOneUseOrOneDef())
+    EM |= ExecutionMode::SERIAL_VIA_NON_MEMORY_INSTR;
   return EM;
 }
 
@@ -104,6 +105,7 @@ static void appendCodeTemplates(const LLVMState &State,
   case ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS: {
     // Picking whatever value for the tied variable will make the instruction
     // serial.
+    State.getExegesisTarget().processInstructionReservedRegs(Variant);
     CodeTemplate CT;
     CT.Execution = ExecutionModeBit;
     CT.Info = std::string(ExecutionClassDescription);
@@ -113,7 +115,51 @@ static void appendCodeTemplates(const LLVMState &State,
   }
   case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: {
     // Select back-to-back memory instruction.
-    // TODO: Implement me.
+
+    auto &I = Variant.getInstr();
+    if (I.Description.mayLoad()) {
+      // If instruction is load, we can self-alias it in case when instruction
+      // overrides whole address register. For that we use provided scratch
+      // memory.
+
+      // TODO: now it is not checked if load writes the whole register.
+
+      auto DefOpIt = find_if(I.Operands, [](Operand const &op) {
+        return op.isDef() && op.isReg();
+      });
+
+      if (DefOpIt == I.Operands.end())
+        return;
+
+      auto &DefOp = *DefOpIt;
+      auto &ET = State.getExegesisTarget();
+      auto ScratchMemoryRegister = ET.getScratchMemoryRegister(
+          State.getTargetMachine().getTargetTriple());
+      auto &RegClass =
+          State.getTargetMachine().getMCRegisterInfo()->getRegClass(
+              DefOp.getExplicitOperandInfo().RegClass);
+
+      // Register classes of def operand and memory operand must be the same
+      // to perform aliasing.
+      if (!RegClass.contains(ScratchMemoryRegister))
+        return;
+
+      ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0);
+      Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister);
+
+      CodeTemplate CT;
+      CT.Execution = ExecutionModeBit;
+      if (CT.ScratchSpacePointerInReg == 0)
+        CT.ScratchSpacePointerInReg = ScratchMemoryRegister;
+
+      CT.Info = std::string(ExecutionClassDescription);
+      CT.Instructions.push_back(std::move(Variant));
+      CT.PreinitScratchMemory.emplace_back(ScratchMemoryRegister,
+                                           /* Offset */ 0);
+      CodeTemplates.push_back(std::move(CT));
+    }
+
+    // TODO: implement more cases
     return;
   }
   case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: {
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index b37999ab017f59..d674b87a425cd4 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -37,10 +37,11 @@ namespace {
 // An MCStreamer that reads a BenchmarkCode definition from a file.
 class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
 public:
-  explicit BenchmarkCodeStreamer(MCContext *Context, const LLVMState &State,
-                                 BenchmarkCode *Result)
-      : MCStreamer(*Context), State(State), Result(Result) {}
-
+  explicit BenchmarkCodeStreamer(
+      const ExegesisTarget &Target, MCContext *Context,
+      const LLVMState &State, BenchmarkCode *Result)
+      : MCStreamer(*Context), Target(Target), State(State),
+        Result(Result) {}
   // Implementation of the MCStreamer interface. We only care about
   // instructions.
   void emitInstruction(const MCInst &Instruction,
@@ -208,6 +209,8 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
                     Align ByteAlignment, SMLoc Loc) override {}
 
   unsigned findRegisterByName(const StringRef RegName) const {
+    if (unsigned Reg = Target.findRegisterByName(RegName))
+      return Reg;
     std::optional<MCRegister> RegisterNumber =
         State.getRegisterNumberFromName(RegName);
     if (!RegisterNumber.has_value()) {
@@ -218,6 +221,7 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
     return *RegisterNumber;
   }
 
+  const ExegesisTarget &Target;
   const LLVMState &State;
   BenchmarkCode *const Result;
   unsigned InvalidComments = 0;
@@ -251,7 +255,7 @@ Expected<std::vector<BenchmarkCode>> readSnippets(const LLVMState &State,
       TM.getTarget().createMCObjectFileInfo(Context, /*PIC=*/false));
   Context.setObjectFileInfo(ObjectFileInfo.get());
   Context.initInlineSourceManager();
-  BenchmarkCodeStreamer Streamer(&Context, State, &Result);
+  BenchmarkCodeStreamer Streamer(State.getExegesisTarget(), &Context, State, &Result);
 
   std::string Error;
   raw_string_ostream ErrorStream(Error);
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
index 7dcff60a8fd11f..8eaf83044e0dd1 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
@@ -73,6 +73,9 @@ Error SnippetGenerator::generateConfigurations(
     for (CodeTemplate &CT : Templates) {
       // TODO: Generate as many BenchmarkCode as needed.
       {
+        CT.ScratchSpacePointerInReg =
+            State.getExegesisTarget().getScratchMemoryRegister(
+                State.getTargetMachine().getTargetTriple());
         BenchmarkCode BC;
         BC.Info = CT.Info;
         BC.Key.Instructions.reserve(CT.Instructions.size());
@@ -108,6 +111,12 @@ std::vector<RegisterValue> SnippetGenerator::computeRegisterInitialValues(
   // Loop invariant: DefinedRegs[i] is true iif it has been set at least once
   // before the current instruction.
   BitVector DefinedRegs = State.getRATC().emptyRegisters();
+  // If target always expects a scratch memory register as live input,
+  // mark it as defined.
+  const ExegesisTarget &Target = State.getExegesisTarget();
+  unsigned ScratchMemoryReg = Target.getScratchMemoryRegister(
+      State.getTargetMachine().getTargetTriple());
+  DefinedRegs.set(ScratchMemoryReg);
   std::vector<RegisterValue> RIV;
   for (const InstructionTemplate &IT : Instructions) {
     // Returns the register that this Operand sets or uses, or 0 if this is not
@@ -200,7 +209,9 @@ static void setRegisterOperandValue(const RegisterOperandAssignment &ROV,
   if (ROV.Op->isExplicit()) {
     auto &AssignedValue = IB.getValueFor(*ROV.Op);
     if (AssignedValue.isValid()) {
-      assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg);
+      // TODO don't re-assign register operands which are already "locked"
+      //  by Target in corresponding InstructionTemplate
+      // assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg);
       return;
     }
     AssignedValue = MCOperand::createReg(ROV.Reg);
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 29e58692f0e92b..533f709147eb62 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -212,6 +212,10 @@ class ExegesisDefaultTarget : public ExegesisTarget {
   ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {}
 
 private:
+  unsigned findRegisterByName(const StringRef RegName) const override {
+    llvm_unreachable("Not yet implemented");
+  }
+
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override {
     llvm_unreachable("Not yet implemented");
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 92cc1cb248a1c0..e8dd2757f64c03 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -86,6 +86,14 @@ class ExegesisTarget {
                 ArrayRef<const char *> ValidationCounters,
                 const pid_t ProcessID = 0) const;
 
+  virtual bool checkOpcodeSupported(int Opcode,
+                                    const MCSubtargetInfo &SI) const {
+    return true;
+  }
+
+  // Find register by name, NoRegister if not found.
+  virtual unsigned findRegisterByName(const StringRef RegName) const = 0;
+
   // Targets can use this to add target-specific passes in assembleToStream();
   virtual void addTargetSpecificPasses(PassManagerBase &PM) const {}
 
@@ -201,6 +209,14 @@ class ExegesisTarget {
         "fillMemoryOperands() requires getScratchMemoryRegister() > 0");
   }
 
+  // Generates code to store register into scratch memory with offset.
+  virtual std::vector<MCInst> storeRegValueToScratch(const MCSubtargetInfo &STI,
+                                                     unsigned Reg,
+                                                     unsigned Offset) const {
+    llvm_unreachable(
+        "storeRegValueToScratch() requires getScratchMemoryRegister() > 0");
+  }
+
   // Returns a counter usable as a loop counter.
   virtual unsigned getDefaultLoopCounterRegister(const Triple &) const {
     return 0;
@@ -238,6 +254,9 @@ class ExegesisTarget {
         "targets with target-specific operands should implement this");
   }
 
+  // Process instructions that used reserved registers.
+  virtual void processInstructionReservedRegs(InstructionTemplate &IT) const {}
+
   // Returns true if this instruction is supported as a back-to-back
   // instructions.
   // FIXME: Eventually we should discover this dynamically.
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 3c3bff76fb6812..92cfc64e4173ea 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -747,6 +747,8 @@ class ExegesisX86Target : public ExegesisTarget {
                                    const MCInstrInfo &MII,
                                    unsigned LoopRegister) const override;
 
+  unsigned findRegisterByName(const StringRef RegName) const override;
+
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override;
 
@@ -1020,6 +1022,10 @@ static std::vector<MCInst> loadImmediateSegmentRegister(unsigned Reg,
 #endif // defined(__x86_64__) && defined(__linux__)
 }
 
+unsigned ExegesisX86Target::findRegisterByName(const StringRef RegName) const {
+  return X86::NoRegister;
+}
+
 std::vector<MCInst> ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI,
                                                 unsigned Reg,
                                                 const APInt &Value) const {
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 546ec770a8d221..1e6e6d8dff904d 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -57,7 +57,9 @@ static cl::opt<int> OpcodeIndex(
 
 static cl::opt<std::string>
     OpcodeNames("opcode-name",
-                cl::desc("comma-separated list of opcodes to measure, by name"),
+                cl::desc("comma-separated list of opcodes to measure, "
+                         "each item is either opcode name ('OP') "
+                         "or opcode range ('OP1..OP2', ends are inclusive)"),
                 cl::cat(BenchmarkOptions), cl::init(""));
 
 static cl::opt<std::string> SnippetsFile("snippets-file",
@@ -235,7 +237,7 @@ static cl::opt<std::string>
 static cl::opt<std::string>
     MCPU("mcpu",
          cl::desc("Target a specific cpu type (-mcpu=help for details)"),
-         cl::value_desc("cpu-name"), cl::cat(Options), cl::init("native"));
+         cl::value_desc("cpu-name"), cl::cat(Options), cl::init(""));
 
 static cl::opt<std::string>
     DumpObjectToDisk("dump-object-to-disk",
@@ -274,6 +276,10 @@ static cl::opt<int> BenchmarkProcessCPU(
     cl::desc("The CPU number that the benchmarking process should executon on"),
     cl::cat(BenchmarkOptions), cl::init(-1));
 
+static cl::opt<std::string> MAttr(
+    "mattr", cl::desc("comma-separated list of target architecture features"),
+    cl::value_desc("+feature1,-feature2,..."), cl::cat(Options), cl::init(""));
+
 static ExitOnError ExitOnErr("llvm-exegesis error: ");
 
 // Helper function that logs the error(s) and exits.
@@ -296,6 +302,22 @@ T ExitOnFileError(const Twine &FileName, Expected<T> &&E) {
   return std::move(*E);
 }
 
+static const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,
+                                                unsigned Opcode) {
+  const MCInstrDesc &InstrDesc = State.getIC().getInstr(Opcode).Description;
+  if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook())
+    return "Unsupported opcode: isPseudo/usesCustomInserter";
+  if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch())
+    return "Unsupported opcode: isBranch/isIndirectBranch";
+  if (InstrDesc.isCall() || InstrDesc.isReturn())
+    return "Unsupported opcode: isCall/isReturn";
+  return nullptr;
+}
+
+static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) {
+  return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr;
+}
+
 // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided,
 // and returns the opcode indices or {} if snippets should be read from
 // `SnippetsFile`.
@@ -340,10 +362,32 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) {
   std::vector<unsigned> Result;
   Result.reserve(Pieces.size());
   for (const StringRef &OpcodeName : Pieces) {
-    if (unsigned Opcode = ResolveName(OpcodeName))
+    if (unsigned Opcode = ResolveName(OpcodeName)) {
       Result.push_back(Opcode);
-    else
+      continue;
+    }
+    // Not a known opcode name; should be an opcode name range.
+    size_t DotDotPos = OpcodeName.find("..");
+    if (DotDotPos == StringRef::npos) {
       ExitWithError(Twine("unknown opcode ").concat(OpcodeName));
+    }
+    StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos);
+    unsigned BeginOpcode =
+        BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName);
+    if (BeginOpcode == 0) {
+      ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName));
+    }
+    StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2);
+    unsigned EndOpcode = EndOpcodeName.empty()
+                             ? State.getInstrInfo().getNumOpcodes() - 1
+                             : ResolveName(EndOpcodeName);
+    if (EndOpcode == 0) {
+      ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName));
+    }
+    for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) {
+      if (!isIgnoredOpcode(State, I))
+        Result.push_back(I);
+    }
   }
   return Result;
 }
@@ -352,17 +396,11 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) {
 static Expected<std::vector<BenchmarkCode>>
 generateSnippets(const LLVMState &State, unsigned Opcode,
                  const BitVector &ForbiddenRegs) {
-  const Instruction &Instr = State.getIC().getInstr(Opcode);
-  const MCInstrDesc &InstrDesc = Instr.Description;
   // Ignore instructions that we cannot run.
-  if (InstrDesc.isPseudo() || InstrDesc.usesCustomInsertionHook())
-    return make_error<Failure>(
-        "Unsupported opcode: isPseudo/usesCustomInserter");
-  if (InstrDesc.isBranch() || InstrDesc.isIndirectBranch())
-    return make_error<Failure>("Unsupported opcode: isBranch/isIndirectBranch");
-  if (InstrDesc.isCall() || InstrDesc.isReturn())
-    return make_error<Failure>("Unsupported opcode: isCall/isReturn");
+  if (const char *Reason = getIgnoredOpcodeReasonOrNull(State, Opcode))
+    return make_error<Failure>(Reason);
 
+  const Instruction &Instr = State.getIC().getInstr(Opcode);
   const std::vector<InstructionTemplate> InstructionVariants =
       State.getExegesisTarget().generateInstructionVariants(
           Instr, MaxConfigsPerOpcode);
@@ -485,8 +523,8 @@ void benchmarkMain() {
   LLVMInitialize##TargetName##AsmParser();
 #include "llvm/Config/TargetExegesis.def"
 
-  const LLVMState State =
-      ExitOnErr(LLVMState::Create(TripleName, MCPU, "", UseDummyPerfCounters));
+  const LLVMState State = ExitOnErr(
+      LLVMState::Create(TripleName, MCPU, MAttr, UseDummyPerfCounters));
 
   // Preliminary check to ensure features needed for requested
   // benchmark mode are present on target CPU and/or OS.

>From 68bef562d3d41b18ff9ca6bcdc5e43f7a5ec1d1d Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 16 May 2024 20:11:54 +0300
Subject: [PATCH 02/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp           | 4 ++++
 llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 6 ------
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index c6d392b3b6d7a2..0909c4d3250f77 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -375,9 +375,13 @@ void ExegesisRISCVTarget::processInstructionReservedRegs(
 
   switch (IT.getOpcode()) {
   case RISCV::C_ADDI16SP:
+  case RISCV::C_ADDI4SPN:
     AssignedValue = MCOperand::createReg(RISCV::X2);
     break;
   case RISCV::C_ADDI_NOP:
+  case RISCV::C_LI_HINT:
+  case RISCV::C_LUI_HINT:
+  case RISCV::C_MV_HINT:
   case RISCV::C_ADD_HINT:
   case RISCV::C_SLLI_HINT:
     AssignedValue = MCOperand::createReg(RISCV::X0);
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 4971c5b6097254..9739b48b2b97ee 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -57,12 +57,6 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
       continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
     const MCInstrDesc &OtherInstrDesc = OtherInstr.Description;
-    // Ignore instructions that we cannot run.
-    if (OtherInstrDesc.isPseudo() || OtherInstrDesc.usesCustomInsertionHook() ||
-        OtherInstrDesc.isBranch() || OtherInstrDesc.isIndirectBranch() ||
-        OtherInstrDesc.isCall() || OtherInstrDesc.isReturn()) {
-      continue;
-    }
     if (OtherInstr.hasMemoryOperands())
       continue;
     if (!ET.allowAsBackToBack(OtherInstr))

>From 22dc529585a7121f1df34c54327b1514712c97cf Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Tue, 21 May 2024 16:29:05 +0300
Subject: [PATCH 03/37] Addressing review comments

---
 .../RISCV/latency-by-extension-A.s            | 118 +++++++++---------
 .../RISCV/latency-by-extension-C.s            |  98 +++++++--------
 .../llvm-exegesis/RISCV/latency-by-load.s     |  88 ++++++-------
 .../RISCV/latency-by-opcode-name-FADD_D.s     |   2 +-
 llvm/tools/llvm-exegesis/lib/Assembler.cpp    |  10 +-
 llvm/tools/llvm-exegesis/lib/LlvmState.cpp    |   6 -
 .../tools/llvm-exegesis/lib/MCInstrDescView.h |   4 +-
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp    |   2 +-
 8 files changed, 157 insertions(+), 171 deletions(-)

diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
index 8cd11ffc3c1f64..a0b5932e834674 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
@@ -1,59 +1,59 @@
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOAND_D -mattr="+a" | FileCheck --check-prefix=TEST1 %s
-
-TEST1:      ---
-TEST1-NEXT: mode: latency
-TEST1-NEXT: key:
-TEST1-NEXT:   instructions:
-TEST1-NEXT:     - 'AMOAND_D [[RE01:X[0-9]+]] X10 [[RE01:X[0-9]+]]'
-TEST1-NEXT: config: ''
-TEST1-NEXT: register_initial_values:
-TEST1-NEXT: - '[[RE01:X[0-9]+]]=0x0'
-TEST1-LAST: ...
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOADD_W -mattr="+a" | FileCheck --check-prefix=TEST2 %s
-
-TEST2:      ---
-TEST2-NEXT: mode: latency
-TEST2-NEXT: key:
-TEST2-NEXT:   instructions:
-TEST2-NEXT:     - 'AMOADD_W [[RE02:X[0-9]+]] X10 [[RE02:X[0-9]+]]'
-TEST2-NEXT: config: ''
-TEST2-NEXT: register_initial_values:
-TEST2-NEXT: - '[[RE02:X[0-9]+]]=0x0'
-TEST2-LAST: ...
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOMAXU_D -mattr="+a" | FileCheck --check-prefix=TEST3 %s
-
-TEST3:      ---
-TEST3-NEXT: mode: latency
-TEST3-NEXT: key:
-TEST3-NEXT:   instructions:
-TEST3-NEXT:     - 'AMOMAXU_D [[RE03:X[0-9]+]] X10 [[RE03:X[0-9]+]]'
-TEST3-NEXT: config: ''
-TEST3-NEXT: register_initial_values:
-TEST3-NEXT: - '[[RE03:X[0-9]+]]=0x0'
-TEST3-LAST: ...
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOMIN_W -mattr="+a" | FileCheck --check-prefix=TEST4 %s
-
-TEST4:      ---
-TEST4-NEXT: mode: latency
-TEST4-NEXT: key:
-TEST4-NEXT:   instructions:
-TEST4-NEXT:     - 'AMOMIN_W [[RE04:X[0-9]+]] X10 [[RE04:X[0-9]+]]'
-TEST4-NEXT: config: ''
-TEST4-NEXT: register_initial_values:
-TEST4-NEXT: - '[[RE04:X[0-9]+]]=0x0'
-TEST4-LAST: ...
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=AMOXOR_D -mattr="+a" | FileCheck --check-prefix=TEST5 %s
-
-TEST5:      ---
-TEST5-NEXT: mode: latency
-TEST5-NEXT: key:
-TEST5-NEXT:   instructions:
-TEST5-NEXT:     - 'AMOXOR_D [[RE05:X[0-9]+]] X10 [[RE05:X[0-9]+]]'
-TEST5-NEXT: config: ''
-TEST5-NEXT: register_initial_values:
-TEST5-NEXT: - '[[RE05:X[0-9]+]]=0x0'
-TEST5-LAST: ...
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOAND_D -mattr="+a" | FileCheck --check-prefix=AMOAND_D %s
+
+AMOAND_D:      ---
+AMOAND_D-NEXT: mode: latency
+AMOAND_D-NEXT: key:
+AMOAND_D-NEXT:   instructions:
+AMOAND_D-NEXT:     - 'AMOAND_D [[RE01:X[0-9]+]] X10 [[RE01:X[0-9]+]]'
+AMOAND_D-NEXT: config: ''
+AMOAND_D-NEXT: register_initial_values:
+AMOAND_D-NEXT: - '[[RE01:X[0-9]+]]=0x0'
+AMOAND_D-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOADD_W -mattr="+a" | FileCheck --check-prefix=AMOADD_W %s
+
+AMOADD_W:      ---
+AMOADD_W-NEXT: mode: latency
+AMOADD_W-NEXT: key:
+AMOADD_W-NEXT:   instructions:
+AMOADD_W-NEXT:     - 'AMOADD_W [[RE02:X[0-9]+]] X10 [[RE02:X[0-9]+]]'
+AMOADD_W-NEXT: config: ''
+AMOADD_W-NEXT: register_initial_values:
+AMOADD_W-NEXT: - '[[RE02:X[0-9]+]]=0x0'
+AMOADD_W-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMAXU_D -mattr="+a" | FileCheck --check-prefix=AMOMAXU_D %s
+
+AMOMAXU_D:      ---
+AMOMAXU_D-NEXT: mode: latency
+AMOMAXU_D-NEXT: key:
+AMOMAXU_D-NEXT:   instructions:
+AMOMAXU_D-NEXT:     - 'AMOMAXU_D [[RE03:X[0-9]+]] X10 [[RE03:X[0-9]+]]'
+AMOMAXU_D-NEXT: config: ''
+AMOMAXU_D-NEXT: register_initial_values:
+AMOMAXU_D-NEXT: - '[[RE03:X[0-9]+]]=0x0'
+AMOMAXU_D-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMIN_W -mattr="+a" | FileCheck --check-prefix=AMOMIN_W %s
+
+AMOMIN_W:      ---
+AMOMIN_W-NEXT: mode: latency
+AMOMIN_W-NEXT: key:
+AMOMIN_W-NEXT:   instructions:
+AMOMIN_W-NEXT:     - 'AMOMIN_W [[RE04:X[0-9]+]] X10 [[RE04:X[0-9]+]]'
+AMOMIN_W-NEXT: config: ''
+AMOMIN_W-NEXT: register_initial_values:
+AMOMIN_W-NEXT: - '[[RE04:X[0-9]+]]=0x0'
+AMOMIN_W-LAST: ...
+
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOXOR_D -mattr="+a" | FileCheck --check-prefix=AMOXOR_D %s
+
+AMOXOR_D:      ---
+AMOXOR_D-NEXT: mode: latency
+AMOXOR_D-NEXT: key:
+AMOXOR_D-NEXT:   instructions:
+AMOXOR_D-NEXT:     - 'AMOXOR_D [[RE05:X[0-9]+]] X10 [[RE05:X[0-9]+]]'
+AMOXOR_D-NEXT: config: ''
+AMOXOR_D-NEXT: register_initial_values:
+AMOXOR_D-NEXT: - '[[RE05:X[0-9]+]]=0x0'
+AMOXOR_D-LAST: ...
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
index e22ddc2d769554..108e1cb411d61b 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
@@ -1,65 +1,65 @@
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ADDI -mattr=+c | FileCheck --check-prefix=TEST1 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_ADDI -mattr=+c | FileCheck --check-prefix=C_ADDI %s
 
-TEST1:      ---
-TEST1-NEXT: mode: latency
-TEST1-NEXT: key:
-TEST1-NEXT:   instructions:
-TEST1-NEXT:     - 'C_ADDI [[REG01:X[0-9]+]] [[RE02:X[0-9]+]] [[IMM0:i_0x[0-9]+]]'
+C_ADDI:      ---
+C_ADDI-NEXT: mode: latency
+C_ADDI-NEXT: key:
+C_ADDI-NEXT:   instructions:
+C_ADDI-NEXT:     - 'C_ADDI [[REG01:X[0-9]+]] [[RE02:X[0-9]+]] [[IMM0:i_0x[0-9]+]]'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ADDIW -mattr=+c | FileCheck --check-prefix=TEST2 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_ADDIW -mattr=+c | FileCheck --check-prefix=C_ADDIW %s
 
-TEST2:      ---
-TEST2-NEXT: mode: latency
-TEST2-NEXT: key:
-TEST2-NEXT:   instructions:
-TEST2-NEXT:     - 'C_ADDIW [[REG11:X[0-9]+]] [[RE12:X[0-9]+]] [[IMM1:i_0x[0-9]+]]'
+C_ADDIW:      ---
+C_ADDIW-NEXT: mode: latency
+C_ADDIW-NEXT: key:
+C_ADDIW-NEXT:   instructions:
+C_ADDIW-NEXT:     - 'C_ADDIW [[REG11:X[0-9]+]] [[RE12:X[0-9]+]] [[IMM1:i_0x[0-9]+]]'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_ANDI -mattr=+c | FileCheck --check-prefix=TEST3 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_ANDI -mattr=+c | FileCheck --check-prefix=C_ANDI %s
 
-TEST3:      ---
-TEST3-NEXT: mode: latency
-TEST3-NEXT: key:
-TEST3-NEXT:   instructions:
-TEST3-NEXT:     - 'C_ANDI [[REG31:X[0-9]+]] [[REG32:X[0-9]+]] [[IMM3:i_0x[0-9]+]]'
+C_ANDI:      ---
+C_ANDI-NEXT: mode: latency
+C_ANDI-NEXT: key:
+C_ANDI-NEXT:   instructions:
+C_ANDI-NEXT:     - 'C_ANDI [[REG31:X[0-9]+]] [[REG32:X[0-9]+]] [[IMM3:i_0x[0-9]+]]'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SLLI -mattr=+c | FileCheck --check-prefix=TEST4 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_SLLI -mattr=+c | FileCheck --check-prefix=C_SLLI %s
 
-TEST4:      ---
-TEST4-NEXT: mode: latency
-TEST4-NEXT: key:
-TEST4-NEXT:   instructions:
-TEST4-NEXT:     - 'C_SLLI [[REG81:X[0-9]+]] [[REG82:X[0-9]+]] [[IMM8:i_0x[0-9]+]]'
+C_SLLI:      ---
+C_SLLI-NEXT: mode: latency
+C_SLLI-NEXT: key:
+C_SLLI-NEXT:   instructions:
+C_SLLI-NEXT:     - 'C_SLLI [[REG81:X[0-9]+]] [[REG82:X[0-9]+]] [[IMM8:i_0x[0-9]+]]'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SRAI -mattr=+c | FileCheck --check-prefix=TEST5 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_SRAI -mattr=+c | FileCheck --check-prefix=C_SRAI %s
 
-TEST5:      ---
-TEST5-NEXT: mode: latency
-TEST5-NEXT: key:
-TEST5-NEXT:   instructions:
-TEST5-NEXT:     - 'C_SRAI [[REG91:X[0-9]+]] [[REG92:X[0-9]+]] [[IMM9:i_0x[0-9]+]]'
+C_SRAI:      ---
+C_SRAI-NEXT: mode: latency
+C_SRAI-NEXT: key:
+C_SRAI-NEXT:   instructions:
+C_SRAI-NEXT:     - 'C_SRAI [[REG91:X[0-9]+]] [[REG92:X[0-9]+]] [[IMM9:i_0x[0-9]+]]'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_SRLI -mattr=+c | FileCheck --check-prefix=TEST6 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_SRLI -mattr=+c | FileCheck --check-prefix=C_SRLI %s
 
-TEST6:      ---
-TEST6-NEXT: mode: latency
-TEST6-NEXT: key:
-TEST6-NEXT:   instructions:
-TEST6-NEXT:     - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]'
-TEST6-LAST: ...
+C_SRLI:      ---
+C_SRLI-NEXT: mode: latency
+C_SRLI-NEXT: key:
+C_SRLI-NEXT:   instructions:
+C_SRLI-NEXT:     - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]'
+C_SRLI-LAST: ...
 
 
-# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=TEST7 %s
+# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=C_LD %s
 
-TEST7:      ---
-TEST7-NEXT: mode: latency
-TEST7-NEXT: key:
-TEST7-NEXT:   instructions:
-TEST7-NEXT:     - 'C_LD [[REG61:X[0-9]+]] [[REG62:X[0-9]+]] [[IMM6:i_0x[0-9]+]]'
+C_LD:      ---
+C_LD-NEXT: mode: latency
+C_LD-NEXT: key:
+C_LD-NEXT:   instructions:
+C_LD-NEXT:     - 'C_LD [[REG61:X[0-9]+]] [[REG62:X[0-9]+]] [[IMM6:i_0x[0-9]+]]'
 
-# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=C_LW -mattr=+c | FileCheck --check-prefix=TEST8 %s
+# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LW -mattr=+c | FileCheck --check-prefix=C_LW %s
 
-TEST8:      ---
-TEST8-NEXT: mode: latency
-TEST8-NEXT: key:
-TEST8-NEXT:   instructions:
-TEST8-NEXT:     - 'C_LW [[REG71:X[0-9]+]] [[REG72:X[0-9]+]] [[IMM7:i_0x[0-9]+]]'
+C_LW:      ---
+C_LW-NEXT: mode: latency
+C_LW-NEXT: key:
+C_LW-NEXT:   instructions:
+C_LW-NEXT:     - 'C_LW [[REG71:X[0-9]+]] [[REG72:X[0-9]+]] [[IMM7:i_0x[0-9]+]]'
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
index b685d8759c27c1..ba985e231e5ce0 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
@@ -1,60 +1,60 @@
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LD | FileCheck --check-prefix=TEST1 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LD | FileCheck --check-prefix=LD %s
 
-TEST1:      ---
-TEST1-NEXT: mode: latency
-TEST1-NEXT: key:
-TEST1-NEXT:   instructions:
-TEST1-NEXT:     - 'LD X10 X10 i_0x0'
+LD:      ---
+LD-NEXT: mode: latency
+LD-NEXT: key:
+LD-NEXT:   instructions:
+LD-NEXT:     - 'LD X10 X10 i_0x0'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LW | FileCheck --check-prefix=TEST2 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LW | FileCheck --check-prefix=LW %s
 
-TEST2:      ---
-TEST2-NEXT: mode: latency
-TEST2-NEXT: key:
-TEST2-NEXT:   instructions:
-TEST2-NEXT:     - 'LW X10 X10 i_0x0'
+LW:      ---
+LW-NEXT: mode: latency
+LW-NEXT: key:
+LW-NEXT:   instructions:
+LW-NEXT:     - 'LW X10 X10 i_0x0'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LH | FileCheck --check-prefix=TEST3 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LH | FileCheck --check-prefix=LH %s
 
-TEST3:      ---
-TEST3-NEXT: mode: latency
-TEST3-NEXT: key:
-TEST3-NEXT:   instructions:
-TEST3-NEXT:     - 'LH X10 X10 i_0x0'
+LH:      ---
+LH-NEXT: mode: latency
+LH-NEXT: key:
+LH-NEXT:   instructions:
+LH-NEXT:     - 'LH X10 X10 i_0x0'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LWU | FileCheck --check-prefix=TEST4 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LWU | FileCheck --check-prefix=LWU %s
 
-TEST4:      ---
-TEST4-NEXT: mode: latency
-TEST4-NEXT: key:
-TEST4-NEXT:   instructions:
-TEST4-NEXT:     - 'LWU X10 X10 i_0x0'
+LWU:      ---
+LWU-NEXT: mode: latency
+LWU-NEXT: key:
+LWU-NEXT:   instructions:
+LWU-NEXT:     - 'LWU X10 X10 i_0x0'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LBU | FileCheck --check-prefix=TEST5 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LBU | FileCheck --check-prefix=LBU %s
 
-TEST5:      ---
-TEST5-NEXT: mode: latency
-TEST5-NEXT: key:
-TEST5-NEXT:   instructions:
-TEST5-NEXT:     - 'LBU X10 X10 i_0x0'
+LBU:      ---
+LBU-NEXT: mode: latency
+LBU-NEXT: key:
+LBU-NEXT:   instructions:
+LBU-NEXT:     - 'LBU X10 X10 i_0x0'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LUI 2>&1 | FileCheck --check-prefix=TEST6 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LUI 2>&1 | FileCheck --check-prefix=LUI %s
 
-TEST6: LUI: No strategy found to make the execution serial
+LUI: LUI: No strategy found to make the execution serial
 
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=TEST7 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=LB %s
 
-TEST7:      ---
-TEST7-NEXT: mode: latency
-TEST7-NEXT: key:
-TEST7-NEXT:   instructions:
-TEST7-NEXT:     - 'LB X10 X10 i_0x0'
+LB:      ---
+LB-NEXT: mode: latency
+LB-NEXT: key:
+LB-NEXT:   instructions:
+LB-NEXT:     - 'LB X10 X10 i_0x0'
 
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --benchmark-phase=assemble-measured-code -opcode-name=LR_W_RL -mattr="+a" | FileCheck --check-prefix=TEST8 %s
+# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LR_W_RL -mattr="+a" | FileCheck --check-prefix=LR_W_RL %s
 
-TEST8:      ---
-TEST8-NEXT: mode: latency
-TEST8-NEXT: key:
-TEST8-NEXT:   instructions:
-TEST8-NEXT:     - 'LR_W_RL X10 X10'
+LR_W_RL:      ---
+LR_W_RL-NEXT: mode: latency
+LR_W_RL-NEXT: key:
+LR_W_RL-NEXT:   instructions:
+LR_W_RL-NEXT:     - 'LR_W_RL X10 X10'
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
index fd58bfb7c1a841..0a4cca1ffc1c18 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
@@ -1,4 +1,4 @@
-# RUN: llvm-exegesis -mtriple=riscv64-unknown-linux-gnu -mode=latency --benchmark-phase=assemble-measured-code -mattr=+d -opcode-name=FADD_D | FileCheck %s
+# RUN: llvm-exegesis -mtriple=riscv64-unknown-linux-gnu --mcpu=generic -mode=latency --benchmark-phase=assemble-measured-code -mattr=+d -opcode-name=FADD_D | FileCheck %s
 
 CHECK:      ---
 CHECK-NEXT: mode: latency
diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
index 1e2a324cc8fc68..13c8c2048a5c03 100644
--- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
@@ -168,15 +168,7 @@ void BasicBlockFiller::addInstruction(const MCInst &Inst, const DebugLoc &DL) {
     } else if (Op.isImm()) {
       Builder.addImm(Op.getImm());
     } else if (!Op.isValid()) {
-      std::string Message;
-      llvm::raw_string_ostream MessageOut(Message);
-      MessageOut << "Operand is not set: Instr: ";
-      Inst.dump_pretty(MessageOut, MCII->getName(Inst.getOpcode()));
-      MessageOut << "; OpIndex: " << OpIndex;
-      const MCOperandInfo &OperandInfo = MCID.operands()[OpIndex];
-      MessageOut << "; OpInfo.OperandType: "
-                 << static_cast<uint32_t>(OperandInfo.OperandType);
-      report_fatal_error(Twine(Message));
+      llvm_unreachable("Operand is not set");
     } else {
       llvm_unreachable("Not yet implemented");
     }
diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
index 713b09937d57a3..4c44c59286ccfb 100644
--- a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
+++ b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
@@ -45,12 +45,6 @@ Expected<LLVMState> LLVMState::Create(std::string TripleName,
   if (CpuName == "native")
     CpuName = std::string(sys::getHostCPUName());
 
-  if (CpuName.empty()) {
-    std::unique_ptr<MCSubtargetInfo> Empty_STI(
-        TheTarget->createMCSubtargetInfo(TripleName, "", ""));
-    CpuName = Empty_STI->getAllProcessorDescriptions().begin()->Key;
-  }
-
   std::unique_ptr<MCSubtargetInfo> STI(
       TheTarget->createMCSubtargetInfo(TripleName, CpuName, ""));
   assert(STI && "Unable to create subtarget info!");
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
index edc1a341b27cee..da84ce793eb02f 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
@@ -167,8 +167,8 @@ struct Instruction {
   const BitVector &AllDefRegs;  // The set of all aliased def registers.
   const BitVector &AllUseRegs;  // The set of all aliased use registers.
   const BitVector &MemoryRegs;  // The set of all aliased memory use registers.
-  const BitVector
-      &NotMemoryRegs; // The set of all aliased not memory use registers.
+  // The set of all aliased not memory use registers.
+  const BitVector &NotMemoryRegs;
 
 private:
   Instruction(const MCInstrDesc *Description, StringRef Name,
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 1e6e6d8dff904d..8dc4e4e1eec825 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -237,7 +237,7 @@ static cl::opt<std::string>
 static cl::opt<std::string>
     MCPU("mcpu",
          cl::desc("Target a specific cpu type (-mcpu=help for details)"),
-         cl::value_desc("cpu-name"), cl::cat(Options), cl::init(""));
+         cl::value_desc("cpu-name"), cl::cat(Options), cl::init("native"));
 
 static cl::opt<std::string>
     DumpObjectToDisk("dump-object-to-disk",

>From 3050772995d1cd118ca788cd05745aef1c6426fc Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Tue, 21 May 2024 19:16:19 +0300
Subject: [PATCH 04/37] Addressing review comments

---
 .../llvm-exegesis/lib/AArch64/Target.cpp      |  4 ----
 llvm/tools/llvm-exegesis/lib/BenchmarkCode.h  |  5 -----
 llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp |  5 +++--
 llvm/tools/llvm-exegesis/lib/CodeTemplate.h   |  4 ++--
 .../llvm-exegesis/lib/MCInstrDescView.cpp     | 21 ++++++++-----------
 .../tools/llvm-exegesis/lib/MCInstrDescView.h |  4 +---
 llvm/tools/llvm-exegesis/lib/Mips/Target.cpp  |  5 -----
 .../llvm-exegesis/lib/PowerPC/Target.cpp      |  7 -------
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp |  2 +-
 .../lib/SerialSnippetGenerator.cpp            |  2 +-
 llvm/tools/llvm-exegesis/lib/Target.cpp       |  4 ----
 llvm/tools/llvm-exegesis/lib/Target.h         |  4 +++-
 llvm/tools/llvm-exegesis/lib/X86/Target.cpp   |  6 ------
 13 files changed, 20 insertions(+), 53 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 6a3eba2459556d..51846862f0a734 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -45,10 +45,6 @@ class ExegesisAArch64Target : public ExegesisTarget {
       : ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}
 
 private:
-  unsigned findRegisterByName(const StringRef RegName) const override {
-    return AArch64::NoRegister;
-  }
-
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override {
     if (AArch64::GPR32RegClass.contains(Reg))
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
index 4d5fc241fde0d9..1db8472e99f7c9 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
@@ -17,11 +17,6 @@
 namespace llvm {
 namespace exegesis {
 
-struct ScratchMemoryStore {
-  unsigned Reg;
-  unsigned Offset;
-};
-
 // A collection of instructions that are to be assembled, executed and measured.
 struct BenchmarkCode {
   BenchmarkKey Key;
diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
index 9b5bfe3196dcda..74a78b0f1c56fb 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
@@ -57,11 +57,12 @@ const MCOperand &InstructionTemplate::getValueFor(const Operand &Op) const {
   return getValueFor(Instr->Variables[Op.getVariableIndex()]);
 }
 
-MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) {
+MCOperand &InstructionTemplate::getValueForOperandIdx(unsigned OpIdx) {
   return getValueFor(Instr->Variables[OpIdx]);
 }
 
-const MCOperand &InstructionTemplate::getValueFor(unsigned OpIdx) const {
+const MCOperand &
+InstructionTemplate::getValueForOperandIdx(unsigned OpIdx) const {
   return getValueFor(Instr->Variables[OpIdx]);
 }
 
diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
index 85fcb4e908f017..662fd90306a45e 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
@@ -35,8 +35,8 @@ struct InstructionTemplate {
   const MCOperand &getValueFor(const Variable &Var) const;
   MCOperand &getValueFor(const Operand &Op);
   const MCOperand &getValueFor(const Operand &Op) const;
-  MCOperand &getValueFor(unsigned OpIdx);
-  const MCOperand &getValueFor(unsigned OpIdx) const;
+  MCOperand &getValueForOperandIdx(unsigned OpIdx);
+  const MCOperand &getValueForOperandIdx(unsigned OpIdx) const;
   bool hasImmediateVariables() const;
   const Instruction &getInstr() const { return *Instr; }
   ArrayRef<MCOperand> getVariableValues() const { return VariableValues; }
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
index 7705d9af4057e8..f9b3666d36f788 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
@@ -89,17 +89,18 @@ const BitVector *BitVectorCache::getUnique(BitVector &&BV) const {
   return Entry.get();
 }
 
-Instruction::Instruction(
-    const MCInstrDesc *Description, StringRef Name,
-    SmallVector<Operand, 8> Operands, SmallVector<Variable, 4> Variables,
-    const BitVector *ImplDefRegs, const BitVector *ImplUseRegs,
-    const BitVector *AllDefRegs, const BitVector *AllUseRegs,
-    const BitVector *MemoryRegs, const BitVector *NotMemoryRegs)
+Instruction::Instruction(const MCInstrDesc *Description, StringRef Name,
+                         SmallVector<Operand, 8> Operands,
+                         SmallVector<Variable, 4> Variables,
+                         const BitVector *ImplDefRegs,
+                         const BitVector *ImplUseRegs,
+                         const BitVector *AllDefRegs,
+                         const BitVector *AllUseRegs,
+                         const BitVector *NotMemoryRegs)
     : Description(*Description), Name(Name), Operands(std::move(Operands)),
       Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs),
       ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs),
-      AllUseRegs(*AllUseRegs), MemoryRegs(*MemoryRegs),
-      NotMemoryRegs(*NotMemoryRegs) {}
+      AllUseRegs(*AllUseRegs), NotMemoryRegs(*NotMemoryRegs) {}
 
 std::unique_ptr<Instruction>
 Instruction::create(const MCInstrInfo &InstrInfo,
@@ -166,7 +167,6 @@ Instruction::create(const MCInstrInfo &InstrInfo,
   BitVector ImplUseRegs = RATC.emptyRegisters();
   BitVector AllDefRegs = RATC.emptyRegisters();
   BitVector AllUseRegs = RATC.emptyRegisters();
-  BitVector MemoryRegs = RATC.emptyRegisters();
   BitVector NotMemoryRegs = RATC.emptyRegisters();
 
   for (const auto &Op : Operands) {
@@ -180,8 +180,6 @@ Instruction::create(const MCInstrInfo &InstrInfo,
         ImplDefRegs |= AliasingBits;
       if (Op.isUse() && Op.isImplicit())
         ImplUseRegs |= AliasingBits;
-      if (Op.isUse() && Op.isMemory())
-        MemoryRegs |= AliasingBits;
       if (Op.isUse() && !Op.isMemory())
         NotMemoryRegs |= AliasingBits;
     }
@@ -193,7 +191,6 @@ Instruction::create(const MCInstrInfo &InstrInfo,
       BVC.getUnique(std::move(ImplUseRegs)),
       BVC.getUnique(std::move(AllDefRegs)),
       BVC.getUnique(std::move(AllUseRegs)),
-      BVC.getUnique(std::move(MemoryRegs)),
       BVC.getUnique(std::move(NotMemoryRegs))));
 }
 
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
index da84ce793eb02f..c6f47a438ad495 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
@@ -166,7 +166,6 @@ struct Instruction {
   const BitVector &ImplUseRegs; // The set of aliased implicit use registers.
   const BitVector &AllDefRegs;  // The set of all aliased def registers.
   const BitVector &AllUseRegs;  // The set of all aliased use registers.
-  const BitVector &MemoryRegs;  // The set of all aliased memory use registers.
   // The set of all aliased not memory use registers.
   const BitVector &NotMemoryRegs;
 
@@ -175,8 +174,7 @@ struct Instruction {
               SmallVector<Operand, 8> Operands,
               SmallVector<Variable, 4> Variables, const BitVector *ImplDefRegs,
               const BitVector *ImplUseRegs, const BitVector *AllDefRegs,
-              const BitVector *AllUseRegs, const BitVector *MemoryRegs,
-              const BitVector *NotMemoryRegs);
+              const BitVector *AllUseRegs, const BitVector *NotMemoryRegs);
 };
 
 // Instructions are expensive to instantiate. This class provides a cache of
diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
index 917c055e29d8f5..6231c971fadb9b 100644
--- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
@@ -62,7 +62,6 @@ class ExegesisMipsTarget : public ExegesisTarget {
   unsigned getMaxMemoryAccessSize() const override { return 64; }
   void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
                           unsigned Offset) const override;
-  unsigned findRegisterByName(const StringRef RegName) const override;
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override;
   bool matchesArch(Triple::ArchType Arch) const override {
@@ -148,10 +147,6 @@ void ExegesisMipsTarget::fillMemoryOperands(InstructionTemplate &IT,
   setMemOp(IT, 2, MCOperand::createImm(Offset)); // Disp
 }
 
-unsigned ExegesisMipsTarget::findRegisterByName(const StringRef RegName) const {
-  return Mips::NoRegister;
-}
-
 std::vector<MCInst> ExegesisMipsTarget::setRegTo(const MCSubtargetInfo &STI,
                                                  unsigned Reg,
                                                  const APInt &Value) const {
diff --git a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
index 0031fb89118ddf..5c944c90384e3e 100644
--- a/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
@@ -33,8 +33,6 @@ class ExegesisPowerPCTarget : public ExegesisTarget {
       : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {}
 
 private:
-  unsigned findRegisterByName(const StringRef RegName) const override;
-
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override;
   bool matchesArch(Triple::ArchType Arch) const override {
@@ -94,11 +92,6 @@ void ExegesisPowerPCTarget::fillMemoryOperands(InstructionTemplate &IT,
   setMemOp(IT, MemOpIdx + 2, MCOperand::createReg(Reg));   // BaseReg
 }
 
-unsigned
-ExegesisPowerPCTarget::findRegisterByName(const StringRef RegName) const {
-  return PPC::NoRegister;
-}
-
 std::vector<MCInst> ExegesisPowerPCTarget::setRegTo(const MCSubtargetInfo &STI,
                                                     unsigned Reg,
                                                     const APInt &Value) const {
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 0909c4d3250f77..2583365a3945b9 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -371,7 +371,7 @@ Error ExegesisRISCVTarget::randomizeTargetMCOperand(
 // explicitly for each instruction according to RVC spec.
 void ExegesisRISCVTarget::processInstructionReservedRegs(
     InstructionTemplate &IT) const {
-  MCOperand &AssignedValue = IT.getValueFor(0);
+  MCOperand &AssignedValue = IT.getValueForOperandIdx(0);
 
   switch (IT.getOpcode()) {
   case RISCV::C_ADDI16SP:
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 9739b48b2b97ee..1f1e3983d30143 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -125,7 +125,7 @@ static void appendCodeTemplates(const LLVMState &State,
       if (DefOpIt == I.Operands.end())
         return;
 
-      auto &DefOp = *DefOpIt;
+      const Operand &DefOp = *DefOpIt;
       auto &ET = State.getExegesisTarget();
       auto ScratchMemoryRegister = ET.getScratchMemoryRegister(
           State.getTargetMachine().getTargetTriple());
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 533f709147eb62..29e58692f0e92b 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -212,10 +212,6 @@ class ExegesisDefaultTarget : public ExegesisTarget {
   ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {}
 
 private:
-  unsigned findRegisterByName(const StringRef RegName) const override {
-    llvm_unreachable("Not yet implemented");
-  }
-
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override {
     llvm_unreachable("Not yet implemented");
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index e8dd2757f64c03..2302400800de23 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -92,7 +92,9 @@ class ExegesisTarget {
   }
 
   // Find register by name, NoRegister if not found.
-  virtual unsigned findRegisterByName(const StringRef RegName) const = 0;
+  virtual unsigned findRegisterByName(const StringRef RegName) const {
+    return MCRegister::NoRegister;
+  }
 
   // Targets can use this to add target-specific passes in assembleToStream();
   virtual void addTargetSpecificPasses(PassManagerBase &PM) const {}
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 92cfc64e4173ea..3c3bff76fb6812 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -747,8 +747,6 @@ class ExegesisX86Target : public ExegesisTarget {
                                    const MCInstrInfo &MII,
                                    unsigned LoopRegister) const override;
 
-  unsigned findRegisterByName(const StringRef RegName) const override;
-
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override;
 
@@ -1022,10 +1020,6 @@ static std::vector<MCInst> loadImmediateSegmentRegister(unsigned Reg,
 #endif // defined(__x86_64__) && defined(__linux__)
 }
 
-unsigned ExegesisX86Target::findRegisterByName(const StringRef RegName) const {
-  return X86::NoRegister;
-}
-
 std::vector<MCInst> ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI,
                                                 unsigned Reg,
                                                 const APInt &Value) const {

>From 9c289b8f5f9cb51ae9ec6f08fac3d326dbe64fd9 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 23 May 2024 20:59:19 +0300
Subject: [PATCH 05/37] Fixed tests

---
 .../tools/llvm-exegesis/RISCV/latency-by-extension-A.s | 10 +++++-----
 .../tools/llvm-exegesis/RISCV/latency-by-extension-C.s |  2 +-
 .../RISCV/latency-by-opcode-name-FADD_D.s              |  2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
index a0b5932e834674..bdc02d4af21551 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-A.s
@@ -8,7 +8,7 @@ AMOAND_D-NEXT:     - 'AMOAND_D [[RE01:X[0-9]+]] X10 [[RE01:X[0-9]+]]'
 AMOAND_D-NEXT: config: ''
 AMOAND_D-NEXT: register_initial_values:
 AMOAND_D-NEXT: - '[[RE01:X[0-9]+]]=0x0'
-AMOAND_D-LAST: ...
+AMOAND_D-DAG: ...
 
 # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOADD_W -mattr="+a" | FileCheck --check-prefix=AMOADD_W %s
 
@@ -20,7 +20,7 @@ AMOADD_W-NEXT:     - 'AMOADD_W [[RE02:X[0-9]+]] X10 [[RE02:X[0-9]+]]'
 AMOADD_W-NEXT: config: ''
 AMOADD_W-NEXT: register_initial_values:
 AMOADD_W-NEXT: - '[[RE02:X[0-9]+]]=0x0'
-AMOADD_W-LAST: ...
+AMOADD_W-DAG: ...
 
 # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMAXU_D -mattr="+a" | FileCheck --check-prefix=AMOMAXU_D %s
 
@@ -32,7 +32,7 @@ AMOMAXU_D-NEXT:     - 'AMOMAXU_D [[RE03:X[0-9]+]] X10 [[RE03:X[0-9]+]]'
 AMOMAXU_D-NEXT: config: ''
 AMOMAXU_D-NEXT: register_initial_values:
 AMOMAXU_D-NEXT: - '[[RE03:X[0-9]+]]=0x0'
-AMOMAXU_D-LAST: ...
+AMOMAXU_D-DAG: ...
 
 # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOMIN_W -mattr="+a" | FileCheck --check-prefix=AMOMIN_W %s
 
@@ -44,7 +44,7 @@ AMOMIN_W-NEXT:     - 'AMOMIN_W [[RE04:X[0-9]+]] X10 [[RE04:X[0-9]+]]'
 AMOMIN_W-NEXT: config: ''
 AMOMIN_W-NEXT: register_initial_values:
 AMOMIN_W-NEXT: - '[[RE04:X[0-9]+]]=0x0'
-AMOMIN_W-LAST: ...
+AMOMIN_W-DAG: ...
 
 # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=AMOXOR_D -mattr="+a" | FileCheck --check-prefix=AMOXOR_D %s
 
@@ -56,4 +56,4 @@ AMOXOR_D-NEXT:     - 'AMOXOR_D [[RE05:X[0-9]+]] X10 [[RE05:X[0-9]+]]'
 AMOXOR_D-NEXT: config: ''
 AMOXOR_D-NEXT: register_initial_values:
 AMOXOR_D-NEXT: - '[[RE05:X[0-9]+]]=0x0'
-AMOXOR_D-LAST: ...
+AMOXOR_D-DAG: ...
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
index 108e1cb411d61b..00bd79729539f0 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
@@ -45,7 +45,7 @@ C_SRLI-NEXT: mode: latency
 C_SRLI-NEXT: key:
 C_SRLI-NEXT:   instructions:
 C_SRLI-NEXT:     - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]'
-C_SRLI-LAST: ...
+C_SRLI-DAG: ...
 
 
 # RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=C_LD %s
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
index 0a4cca1ffc1c18..2dea89cca4d7e9 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-opcode-name-FADD_D.s
@@ -8,4 +8,4 @@ CHECK-NEXT:     - 'FADD_D [[REG1:F[0-9]+_D]] [[REG2:F[0-9]+_D]] [[REG3:F[0-9]+_D
 CHECK-NEXT: config: ''
 CHECK-NEXT: register_initial_values:
 CHECK-DAG: - '[[REG1]]=0x0'
-CHECK-LAST: ...
+CHECK-DAG: ...

>From 1277beb7fc2ce9f8febf2a75378d6817ebd4d45a Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Fri, 24 May 2024 18:35:05 +0300
Subject: [PATCH 06/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 7 +++++++
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp        | 6 +++---
 llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp    | 1 -
 llvm/tools/llvm-exegesis/lib/Target.h                | 2 +-
 4 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index 1d421b3c31c36e..a9d207fa3d1579 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -5,6 +5,10 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+//
+// This file defines RISC-V perf counters.
+//
+//===----------------------------------------------------------------------===//
 
 #include "RISCVCounters.h"
 
@@ -45,6 +49,9 @@ RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
   StartValue = getRISCVCpuCyclesCount();
   EndValue = getRISCVCpuCyclesCount();
   MeasurementCycles = EndValue - StartValue;
+  // If values of two calls CpuCyclesCounters don`t differ
+  // it means that counters don`t configured properly, report error.
+  // MeasurementCycles the smallest interval between two counter calls.
   if (MeasurementCycles == 0) {
     report_fatal_error("MeasurementCycles == 0, "
                        "performance counters are not configured.");
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 2583365a3945b9..77365c5ccadf1a 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -60,7 +60,7 @@ class ExegesisRISCVTarget : public ExegesisTarget {
   bool checkOpcodeSupported(int Opcode,
                             const MCSubtargetInfo &SI) const override;
 
-  unsigned findRegisterByName(const StringRef RegName) const override;
+  MCRegister findRegisterByName(const StringRef RegName) const override;
 
   bool matchesArch(Triple::ArchType Arch) const override;
 
@@ -123,9 +123,9 @@ bool ExegesisRISCVTarget::checkOpcodeSupported(
 #define GET_REGISTER_MATCHER
 #include "RISCVGenAsmMatcher.inc"
 
-unsigned
+MCRegister
 ExegesisRISCVTarget::findRegisterByName(const StringRef RegName) const {
-  unsigned Reg;
+  MCRegister Reg;
   if ((Reg = MatchRegisterName(RegName)))
     return Reg;
   if ((Reg = MatchRegisterAltName(RegName)))
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
index 8eaf83044e0dd1..48357d443f713e 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
@@ -211,7 +211,6 @@ static void setRegisterOperandValue(const RegisterOperandAssignment &ROV,
     if (AssignedValue.isValid()) {
       // TODO don't re-assign register operands which are already "locked"
       //  by Target in corresponding InstructionTemplate
-      // assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg);
       return;
     }
     AssignedValue = MCOperand::createReg(ROV.Reg);
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 2302400800de23..f4edec300e440a 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -92,7 +92,7 @@ class ExegesisTarget {
   }
 
   // Find register by name, NoRegister if not found.
-  virtual unsigned findRegisterByName(const StringRef RegName) const {
+  virtual MCRegister findRegisterByName(const StringRef RegName) const {
     return MCRegister::NoRegister;
   }
 

>From 712aa9dec764912ec746c3fce7d62634a0bcf6d4 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Fri, 31 May 2024 19:03:43 +0300
Subject: [PATCH 07/37] Addressing review comments

---
 llvm/lib/Target/RISCV/CMakeLists.txt          |  1 +
 llvm/lib/Target/RISCV/RISCV.td                |  6 ++
 llvm/lib/Target/RISCV/RISCVPfmCounters.td     | 18 ++++
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 18 +---
 llvm/tools/llvm-exegesis/lib/SnippetFile.cpp  |  1 +
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp    | 92 ++++++++++++-------
 .../llvm-project-overlay/llvm/BUILD.bazel     |  1 +
 7 files changed, 89 insertions(+), 48 deletions(-)
 create mode 100644 llvm/lib/Target/RISCV/RISCVPfmCounters.td

diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index fd049d1a57860e..4727e0ca22428a 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -15,6 +15,7 @@ tablegen(LLVM RISCVGenRegisterBank.inc -gen-register-bank)
 tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info)
 tablegen(LLVM RISCVGenSearchableTables.inc -gen-searchable-tables)
 tablegen(LLVM RISCVGenSubtargetInfo.inc -gen-subtarget)
+tablegen(LLVM RISCVGenExegesis.inc -gen-exegesis)
 
 set(LLVM_TARGET_DEFINITIONS RISCVGISel.td)
 tablegen(LLVM RISCVGenGlobalISel.inc -gen-global-isel)
diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td
index 00c3d702e12a22..38086e8efe340c 100644
--- a/llvm/lib/Target/RISCV/RISCV.td
+++ b/llvm/lib/Target/RISCV/RISCV.td
@@ -84,3 +84,9 @@ def RISCV : Target {
   let AssemblyWriters = [RISCVAsmWriter];
   let AllowRegisterRenaming = 1;
 }
+
+//===----------------------------------------------------------------------===//
+// Pfm Counters
+//===----------------------------------------------------------------------===//
+
+include "RISCVPfmCounters.td"
diff --git a/llvm/lib/Target/RISCV/RISCVPfmCounters.td b/llvm/lib/Target/RISCV/RISCVPfmCounters.td
new file mode 100644
index 00000000000000..33650dc5b0017c
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVPfmCounters.td
@@ -0,0 +1,18 @@
+//===-- RISCVPfmCounters.td - RISC-V Hardware Counters -----*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This describes the available hardware counters for RISC-V.
+//
+//===----------------------------------------------------------------------===//
+
+def CpuCyclesPfmCounter : PfmCounter<"CPU_CYCLES">;
+
+def DefaultPfmCounters : ProcPfmCounters {
+  let CycleCounter = CpuCyclesPfmCounter;
+}
+def : PfmCountersDefaultBinding<DefaultPfmCounters>;
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 77365c5ccadf1a..84634db285ba6d 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -31,22 +31,7 @@ namespace exegesis {
 
 namespace {
 
-// TODO move perf counter data to td files (although it looks like an overkill
-// of sorts)
-
-static const char *RISCVPfmCounterNames[] = {
-    "CPU_CYCLES", // 0
-};
-
-static const PfmCountersInfo RISCVDefaultPfmCounters = {
-    RISCVPfmCounterNames[0], // Cycle counter
-    nullptr,                 // No uops counter.
-    nullptr,                 // No issue counters.
-    0};
-
-static const CpuAndPfmCounters RISCVCpuPfmCounters[] = {
-    {"", &RISCVDefaultPfmCounters},
-};
+#include "RISCVGenExegesis.inc"
 
 class ExegesisRISCVTarget : public ExegesisTarget {
 public:
@@ -102,6 +87,7 @@ Expected<std::unique_ptr<pfm::CounterGroup>> ExegesisRISCVTarget::createCounter(
     StringRef CounterName, const LLVMState &State,
     ArrayRef<const char *> ValidationCounters, const pid_t ProcessID) const {
   if (CounterName == RISCVPfmCounterNames[0]) {
+    // TODO add support for Linux perf counters
     return createRISCVCpuCyclesCounter(pfm::PerfEvent(CounterName));
   }
   return make_error<Failure>(Twine("Unsupported performance counter '")
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index d674b87a425cd4..f38b233a95d4a1 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -209,6 +209,7 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
                     Align ByteAlignment, SMLoc Loc) override {}
 
   unsigned findRegisterByName(const StringRef RegName) const {
+    // TODO make use of RegNameToRegNo map
     if (unsigned Reg = Target.findRegisterByName(RegName))
       return Reg;
     std::optional<MCRegister> RegisterNumber =
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 8dc4e4e1eec825..c4236820c1462e 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -50,17 +50,27 @@
 namespace llvm {
 namespace exegesis {
 
+struct OpcodeNameParser
+    : public cl::parser<std::vector<std::pair<StringRef, StringRef>>> {
+  OpcodeNameParser(cl::Option &O)
+      : cl::parser<std::vector<std::pair<StringRef, StringRef>>>(O) {}
+  bool parse(cl::Option &O, StringRef ArgName, const StringRef ArgValue,
+             std::vector<std::pair<StringRef, StringRef>> &Val);
+};
+
 static cl::opt<int> OpcodeIndex(
     "opcode-index",
     cl::desc("opcode to measure, by index, or -1 to measure all opcodes"),
     cl::cat(BenchmarkOptions), cl::init(0));
 
-static cl::opt<std::string>
+static cl::opt<std::vector<std::pair<StringRef, StringRef>>, false,
+               OpcodeNameParser>
     OpcodeNames("opcode-name",
                 cl::desc("comma-separated list of opcodes to measure, "
                          "each item is either opcode name ('OP') "
                          "or opcode range ('OP1..OP2', ends are inclusive)"),
-                cl::cat(BenchmarkOptions), cl::init(""));
+                cl::cat(BenchmarkOptions),
+                cl::init(std::vector<std::pair<StringRef, StringRef>>()));
 
 static cl::opt<std::string> SnippetsFile("snippets-file",
                                          cl::desc("code snippets to measure"),
@@ -318,6 +328,27 @@ static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) {
   return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr;
 }
 
+bool OpcodeNameParser::parse(
+    cl::Option &O, StringRef ArgName, const StringRef OpcodeNames,
+    std::vector<std::pair<StringRef, StringRef>> &Val) {
+  SmallVector<StringRef, 2> Pieces;
+  StringRef(OpcodeNames)
+      .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false);
+  for (const StringRef &OpcodeName : Pieces) {
+    size_t DotDotPos = OpcodeName.find("..");
+    if (DotDotPos == StringRef::npos) {
+      Val.push_back(std::make_pair(OpcodeName, OpcodeName));
+      continue;
+    }
+    StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos);
+    StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2);
+    Val.push_back(std::make_pair(BeginOpcodeName, EndOpcodeName));
+  }
+  if (Val.empty())
+    return O.error("No matching opcode names");
+  return false;
+}
+
 // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided,
 // and returns the opcode indices or {} if snippets should be read from
 // `SnippetsFile`.
@@ -356,37 +387,34 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) {
       return I->getSecond();
     return 0u;
   };
-  SmallVector<StringRef, 2> Pieces;
-  StringRef(OpcodeNames.getValue())
-      .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false);
+
   std::vector<unsigned> Result;
-  Result.reserve(Pieces.size());
-  for (const StringRef &OpcodeName : Pieces) {
-    if (unsigned Opcode = ResolveName(OpcodeName)) {
-      Result.push_back(Opcode);
-      continue;
-    }
-    // Not a known opcode name; should be an opcode name range.
-    size_t DotDotPos = OpcodeName.find("..");
-    if (DotDotPos == StringRef::npos) {
-      ExitWithError(Twine("unknown opcode ").concat(OpcodeName));
-    }
-    StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos);
-    unsigned BeginOpcode =
-        BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName);
-    if (BeginOpcode == 0) {
-      ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName));
-    }
-    StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2);
-    unsigned EndOpcode = EndOpcodeName.empty()
-                             ? State.getInstrInfo().getNumOpcodes() - 1
-                             : ResolveName(EndOpcodeName);
-    if (EndOpcode == 0) {
-      ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName));
-    }
-    for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) {
-      if (!isIgnoredOpcode(State, I))
-        Result.push_back(I);
+  for (const std::pair<StringRef, StringRef> &OpcodeName : OpcodeNames) {
+    if (OpcodeName.first == OpcodeName.second) {
+      if (unsigned Opcode = ResolveName(OpcodeName.first)) {
+        Result.push_back(Opcode);
+        continue;
+      } else {
+        ExitWithError(Twine("unknown opcode ").concat(OpcodeName.first));
+      }
+    } else {
+      StringRef BeginOpcodeName = OpcodeName.first;
+      unsigned BeginOpcode =
+          BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName);
+      if (BeginOpcode == 0) {
+        ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName));
+      }
+      StringRef EndOpcodeName = OpcodeName.second;
+      unsigned EndOpcode = EndOpcodeName.empty()
+                               ? State.getInstrInfo().getNumOpcodes() - 1
+                               : ResolveName(EndOpcodeName);
+      if (EndOpcode == 0) {
+        ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName));
+      }
+      for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) {
+        if (!isIgnoredOpcode(State, I))
+          Result.push_back(I);
+      }
     }
   }
   return Result;
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index b3c7108d840d38..d3447b62bb2392 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -2262,6 +2262,7 @@ llvm_target_lib_list = [lib for lib in [
             ("-gen-register-info", "lib/Target/RISCV/RISCVGenRegisterInfo.inc"),
             ("-gen-subtarget", "lib/Target/RISCV/RISCVGenSubtargetInfo.inc"),
             ("-gen-searchable-tables", "lib/Target/RISCV/RISCVGenSearchableTables.inc"),
+	    ("-gen-exegesis", "lib/Target/RISCV/RISCVGenExegesis.inc"),
         ],
         "tbl_deps": [
             ":riscv_isel_target_gen",

>From 84db7ebf5b94ce0a04ad093bb93707e199cf5f22 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 13 Jun 2024 17:32:29 +0300
Subject: [PATCH 08/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/Mips/Target.cpp  |  1 +
 .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 20 ++++++++++++++++---
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
index 6231c971fadb9b..731e037c240df0 100644
--- a/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
@@ -62,6 +62,7 @@ class ExegesisMipsTarget : public ExegesisTarget {
   unsigned getMaxMemoryAccessSize() const override { return 64; }
   void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
                           unsigned Offset) const override;
+
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
                                const APInt &Value) const override;
   bool matchesArch(Triple::ArchType Arch) const override {
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index a9d207fa3d1579..02a459ad56f6c5 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -20,9 +20,23 @@ namespace exegesis {
 
 inline uint64_t getRISCVCpuCyclesCount() {
 #ifdef __riscv
-  uint64_t Counter;
-  asm("csrr %0, cycle" : "=r"(Counter)::"memory");
-  return Counter;
+#if __riscv_xlen == 32
+  uint32_t cycles_lo, cycles_hi0, cycles_hi1;
+  asm volatile("rdtimeh %0\n"
+               "rdtime %1\n"
+               "rdtimeh %2\n"
+               "sub %0, %0, %2\n"
+               "seqz %0, %0\n"
+               "sub %0, zero, %0\n"
+               "and %1, %1, %0\n"
+               : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1));
+  return static_cast<uint64_t>((static_cast<uint64_t>(cycles_hi1) << 32) |
+                               cycles_lo);
+#else
+  uint64_t cycles;
+  asm volatile("rdtime %0" : "=r"(cycles));
+  return static_cast<uint64_t>(cycles);
+#endif
 #else
   return 0;
 #endif

>From 99bccddd8e6a84f6521918e957d46c3a1f13a9e5 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Tue, 18 Jun 2024 19:23:55 +0300
Subject: [PATCH 09/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index 02a459ad56f6c5..9d094f9494f4c9 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -22,9 +22,9 @@ inline uint64_t getRISCVCpuCyclesCount() {
 #ifdef __riscv
 #if __riscv_xlen == 32
   uint32_t cycles_lo, cycles_hi0, cycles_hi1;
-  asm volatile("rdtimeh %0\n"
-               "rdtime %1\n"
-               "rdtimeh %2\n"
+  asm volatile("rdcycleh %0\n"
+               "rdcycle %1\n"
+               "rdcycleh %2\n"
                "sub %0, %0, %2\n"
                "seqz %0, %0\n"
                "sub %0, zero, %0\n"
@@ -34,7 +34,7 @@ inline uint64_t getRISCVCpuCyclesCount() {
                                cycles_lo);
 #else
   uint64_t cycles;
-  asm volatile("rdtime %0" : "=r"(cycles));
+  asm volatile("rdcycle %0" : "=r"(cycles));
   return static_cast<uint64_t>(cycles);
 #endif
 #else

>From 9352f6dbba0901146c1098d458d0bf048ae00381 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Fri, 28 Jun 2024 16:12:20 +0300
Subject: [PATCH 10/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt    |  1 +
 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 10 +++++++++-
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
index ea0ced1786a0cc..78eec178a456a3 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
@@ -4,6 +4,7 @@ include_directories(
 )
 
 set(LLVM_LINK_COMPONENTS
+  CodeGen
   RISCV
   Exegesis
   Core
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index 9d094f9494f4c9..48e619c762eb4e 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -11,6 +11,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "RISCVCounters.h"
+#include <linux/sysctl.h>
+#include <sys/types.h>
 
 namespace llvm {
 namespace exegesis {
@@ -19,7 +21,13 @@ namespace exegesis {
 // and provides manual implementation of performance counters.
 
 inline uint64_t getRISCVCpuCyclesCount() {
-#ifdef __riscv
+#if defined(__riscv) && defined(__linux__)
+  uint32_t Cycle;
+  size_t Length = sizeof(Cycle);
+  if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) ||
+      Cycle != 1)
+    report_fatal_error(
+        "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'");
 #if __riscv_xlen == 32
   uint32_t cycles_lo, cycles_hi0, cycles_hi1;
   asm volatile("rdcycleh %0\n"

>From d52ddc85ddf31767d9adfe6ba71c5408d3768561 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Fri, 28 Jun 2024 16:56:13 +0300
Subject: [PATCH 11/37] Addressing review comments

---
 .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp      | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index 48e619c762eb4e..bcda7da2721fed 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -22,12 +22,6 @@ namespace exegesis {
 
 inline uint64_t getRISCVCpuCyclesCount() {
 #if defined(__riscv) && defined(__linux__)
-  uint32_t Cycle;
-  size_t Length = sizeof(Cycle);
-  if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) ||
-      Cycle != 1)
-    report_fatal_error(
-        "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'");
 #if __riscv_xlen == 32
   uint32_t cycles_lo, cycles_hi0, cycles_hi1;
   asm volatile("rdcycleh %0\n"
@@ -68,6 +62,14 @@ class RISCVCpuCyclesCounter : public pfm::CounterGroup {
 
 RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
     : CounterGroup(std::move(Event), {}) {
+  #if defined(__riscv) && defined(__linux__)
+  uint32_t Cycle;
+  size_t Length = sizeof(Cycle);
+  if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) ||
+      Cycle != 1)
+    report_fatal_error(
+        "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'");
+  #endif
   StartValue = getRISCVCpuCyclesCount();
   EndValue = getRISCVCpuCyclesCount();
   MeasurementCycles = EndValue - StartValue;

>From 49cd4633de1625132c281a70aecdd2569c382a3c Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Wed, 10 Jul 2024 14:15:51 +0300
Subject: [PATCH 12/37] Addressing review comments

---
 .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp      | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index bcda7da2721fed..57c311bb967b12 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -11,8 +11,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "RISCVCounters.h"
-#include <linux/sysctl.h>
-#include <sys/types.h>
 
 namespace llvm {
 namespace exegesis {
@@ -63,12 +61,16 @@ class RISCVCpuCyclesCounter : public pfm::CounterGroup {
 RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
     : CounterGroup(std::move(Event), {}) {
   #if defined(__riscv) && defined(__linux__)
-  uint32_t Cycle;
-  size_t Length = sizeof(Cycle);
-  if (!sysctlbyname("kernel.perf_user_access", &Cycle, &Length, NULL, 0) ||
-      Cycle != 1)
+  char Value[2] = "0";
+  int File = 0;
+  std::error_code FileError = sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File);
+  sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File);
+  Expected<size_t> ReadBytes = sys::fs::readNativeFile(FileNative, Value);
+
+  if (FileError || !ReadBytes || strcmp(Value, "1") != 0) {
     report_fatal_error(
         "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'");
+  }
   #endif
   StartValue = getRISCVCpuCyclesCount();
   EndValue = getRISCVCpuCyclesCount();

>From 4004b8a348c4e45c6d56f246238f19f3658f30a6 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Wed, 10 Jul 2024 14:24:30 +0300
Subject: [PATCH 13/37] Fix code format

---
 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index 57c311bb967b12..6851c1037a4613 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -60,10 +60,11 @@ class RISCVCpuCyclesCounter : public pfm::CounterGroup {
 
 RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
     : CounterGroup(std::move(Event), {}) {
-  #if defined(__riscv) && defined(__linux__)
+#if defined(__riscv) && defined(__linux__)
   char Value[2] = "0";
   int File = 0;
-  std::error_code FileError = sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File);
+  std::error_code FileError =
+      sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File);
   sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File);
   Expected<size_t> ReadBytes = sys::fs::readNativeFile(FileNative, Value);
 
@@ -71,7 +72,7 @@ RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
     report_fatal_error(
         "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'");
   }
-  #endif
+#endif
   StartValue = getRISCVCpuCyclesCount();
   EndValue = getRISCVCpuCyclesCount();
   MeasurementCycles = EndValue - StartValue;

>From 5c2b1adbda6e79c22dc08be7a727a5aad6eaa02f Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Wed, 10 Jul 2024 17:35:08 +0300
Subject: [PATCH 14/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index 6851c1037a4613..3ca8d742c85ed3 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -64,7 +64,7 @@ RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
   char Value[2] = "0";
   int File = 0;
   std::error_code FileError =
-      sys::fs::openFileForRead("/proc/sys/kernel/watchdog", File);
+      sys::fs::openFileForRead("/proc/sys/kernel/perf_user_access", File);
   sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File);
   Expected<size_t> ReadBytes = sys::fs::readNativeFile(FileNative, Value);
 

>From 321f0499c2166d2d4fc8d45f5365f3f0d1bd3a80 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Wed, 17 Jul 2024 15:03:13 +0300
Subject: [PATCH 15/37] Addressing review comments

---
 .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp  | 18 ++++++++----------
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp  |  2 +-
 .../lib/SerialSnippetGenerator.cpp             |  2 +-
 llvm/tools/llvm-exegesis/lib/Target.h          |  2 +-
 4 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
index 3ca8d742c85ed3..8688343036483f 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
@@ -21,17 +21,15 @@ namespace exegesis {
 inline uint64_t getRISCVCpuCyclesCount() {
 #if defined(__riscv) && defined(__linux__)
 #if __riscv_xlen == 32
-  uint32_t cycles_lo, cycles_hi0, cycles_hi1;
-  asm volatile("rdcycleh %0\n"
-               "rdcycle %1\n"
+  uint32_t cycles_x3, cycles_x2, cycles_x4;
+  asm volatile("again:\n"
+               "rdcycleh %1\n"
+               "rdcycle %0\n"
                "rdcycleh %2\n"
-               "sub %0, %0, %2\n"
-               "seqz %0, %0\n"
-               "sub %0, zero, %0\n"
-               "and %1, %1, %0\n"
-               : "=r"(cycles_hi0), "=r"(cycles_lo), "=r"(cycles_hi1));
-  return static_cast<uint64_t>((static_cast<uint64_t>(cycles_hi1) << 32) |
-                               cycles_lo);
+               "bne %1, %2, again\n"
+               : "=r"(cycles_x2), "=r"(cycles_x3), "=r"(cycles_x4));
+  return static_cast<uint64_t>((static_cast<uint64_t>(cycles_x3) << 32) |
+                               cycles_x2);
 #else
   uint64_t cycles;
   asm volatile("rdcycle %0" : "=r"(cycles));
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 84634db285ba6d..71eda40ff2e603 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -103,7 +103,7 @@ bool ExegesisRISCVTarget::checkOpcodeSupported(
   FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode);
   FeatureBitset MissingFeatures =
       (AvailableFeatures & RequiredFeatures) ^ RequiredFeatures;
-  return MissingFeatures.none();
+  return !(MissingFeatures.none());
 }
 
 #define GET_REGISTER_MATCHER
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 1f1e3983d30143..ffceb6ac82faca 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -52,7 +52,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
       continue;
     if (OtherOpcode == Instr->Description.getOpcode())
       continue;
-    if (!State.getExegesisTarget().checkOpcodeSupported(
+    if (State.getExegesisTarget().checkOpcodeSupported(
             OtherOpcode, State.getSubtargetInfo()))
       continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index f4edec300e440a..1dcef5e51f4e51 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -88,7 +88,7 @@ class ExegesisTarget {
 
   virtual bool checkOpcodeSupported(int Opcode,
                                     const MCSubtargetInfo &SI) const {
-    return true;
+    return false;
   }
 
   // Find register by name, NoRegister if not found.

>From 78d6a0e9da5f83421ff14ebcce76de793cd7e7e2 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Wed, 17 Jul 2024 18:53:28 +0300
Subject: [PATCH 16/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp           | 5 ++---
 llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 2 +-
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 71eda40ff2e603..dcc4895e077f76 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -101,9 +101,8 @@ bool ExegesisRISCVTarget::checkOpcodeSupported(
   FeatureBitset AvailableFeatures =
       RISCV_MC::computeAvailableFeatures(Features);
   FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode);
-  FeatureBitset MissingFeatures =
-      (AvailableFeatures & RequiredFeatures) ^ RequiredFeatures;
-  return !(MissingFeatures.none());
+  FeatureBitset MissingFeatures = RequiredFeatures & ~AvailableFeatures;
+  return MissingFeatures.none();
 }
 
 #define GET_REGISTER_MATCHER
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index ffceb6ac82faca..1f1e3983d30143 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -52,7 +52,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
       continue;
     if (OtherOpcode == Instr->Description.getOpcode())
       continue;
-    if (State.getExegesisTarget().checkOpcodeSupported(
+    if (!State.getExegesisTarget().checkOpcodeSupported(
             OtherOpcode, State.getSubtargetInfo()))
       continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);

>From a650063a1ae8ca35c473d1d50d6ca2cc3bac5f7e Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Fri, 19 Jul 2024 15:33:27 +0300
Subject: [PATCH 17/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 1f1e3983d30143..ffceb6ac82faca 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -52,7 +52,7 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
       continue;
     if (OtherOpcode == Instr->Description.getOpcode())
       continue;
-    if (!State.getExegesisTarget().checkOpcodeSupported(
+    if (State.getExegesisTarget().checkOpcodeSupported(
             OtherOpcode, State.getSubtargetInfo()))
       continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);

>From f35809bfe73b8e67ed7ebdb7ab93ef2afc988f9c Mon Sep 17 00:00:00 2001
From: Dmitry Bushev <dmitry.bushev at syntacore.com>
Date: Fri, 16 Aug 2024 15:45:32 +0300
Subject: [PATCH 18/37] Remove performance counters initial support

---
 llvm/lib/Target/RISCV/CMakeLists.txt          |  1 -
 llvm/lib/Target/RISCV/RISCV.td                |  6 --
 llvm/lib/Target/RISCV/RISCVInstrInfo.td       |  4 +-
 llvm/lib/Target/RISCV/RISCVPfmCounters.td     | 18 ----
 .../llvm-exegesis/lib/RISCV/CMakeLists.txt    |  1 -
 .../llvm-exegesis/lib/RISCV/RISCVCounters.cpp | 98 -------------------
 .../llvm-exegesis/lib/RISCV/RISCVCounters.h   | 31 ------
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 31 ++----
 .../llvm-project-overlay/llvm/BUILD.bazel     |  1 -
 9 files changed, 8 insertions(+), 183 deletions(-)
 delete mode 100644 llvm/lib/Target/RISCV/RISCVPfmCounters.td
 delete mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
 delete mode 100644 llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h

diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index 4727e0ca22428a..fd049d1a57860e 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -15,7 +15,6 @@ tablegen(LLVM RISCVGenRegisterBank.inc -gen-register-bank)
 tablegen(LLVM RISCVGenRegisterInfo.inc -gen-register-info)
 tablegen(LLVM RISCVGenSearchableTables.inc -gen-searchable-tables)
 tablegen(LLVM RISCVGenSubtargetInfo.inc -gen-subtarget)
-tablegen(LLVM RISCVGenExegesis.inc -gen-exegesis)
 
 set(LLVM_TARGET_DEFINITIONS RISCVGISel.td)
 tablegen(LLVM RISCVGenGlobalISel.inc -gen-global-isel)
diff --git a/llvm/lib/Target/RISCV/RISCV.td b/llvm/lib/Target/RISCV/RISCV.td
index 38086e8efe340c..00c3d702e12a22 100644
--- a/llvm/lib/Target/RISCV/RISCV.td
+++ b/llvm/lib/Target/RISCV/RISCV.td
@@ -84,9 +84,3 @@ def RISCV : Target {
   let AssemblyWriters = [RISCVAsmWriter];
   let AllowRegisterRenaming = 1;
 }
-
-//===----------------------------------------------------------------------===//
-// Pfm Counters
-//===----------------------------------------------------------------------===//
-
-include "RISCVPfmCounters.td"
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index e558d3e15a7a01..5747f05ffafd47 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -524,7 +524,7 @@ class BranchCC_rri<bits<3> funct3, string opcodestr>
   let isTerminator = 1;
 }
 
-let hasSideEffects = 0, mayLoad = 1, mayStore = 0, UseNamedOperandTable = 1 in {
+let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
 class Load_ri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>
     : RVInstI<funct3, OPC_LOAD, (outs rty:$rd), (ins GPRMem:$rs1, simm12:$imm12),
               opcodestr, "$rd, ${imm12}(${rs1})">;
@@ -539,7 +539,7 @@ class HLoad_r<bits<7> funct7, bits<5> funct5, string opcodestr>
 // Operands for stores are in the order srcreg, base, offset rather than
 // reflecting the order these fields are specified in the instruction
 // encoding.
-let hasSideEffects = 0, mayLoad = 0, mayStore = 1, UseNamedOperandTable = 1 in {
+let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
 class Store_rri<bits<3> funct3, string opcodestr, DAGOperand rty = GPR>
     : RVInstS<funct3, OPC_STORE, (outs),
               (ins rty:$rs2, GPRMem:$rs1, simm12:$imm12),
diff --git a/llvm/lib/Target/RISCV/RISCVPfmCounters.td b/llvm/lib/Target/RISCV/RISCVPfmCounters.td
deleted file mode 100644
index 33650dc5b0017c..00000000000000
--- a/llvm/lib/Target/RISCV/RISCVPfmCounters.td
+++ /dev/null
@@ -1,18 +0,0 @@
-//===-- RISCVPfmCounters.td - RISC-V Hardware Counters -----*- tablegen -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This describes the available hardware counters for RISC-V.
-//
-//===----------------------------------------------------------------------===//
-
-def CpuCyclesPfmCounter : PfmCounter<"CPU_CYCLES">;
-
-def DefaultPfmCounters : ProcPfmCounters {
-  let CycleCounter = CpuCyclesPfmCounter;
-}
-def : PfmCountersDefaultBinding<DefaultPfmCounters>;
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
index 78eec178a456a3..489ac6d6e34b33 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/CMakeLists.txt
@@ -15,7 +15,6 @@ add_llvm_library(LLVMExegesisRISCV
   DISABLE_LLVM_LINK_LLVM_DYLIB
   STATIC
   Target.cpp
-  RISCVCounters.cpp
 
   DEPENDS
   intrinsics_gen
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
deleted file mode 100644
index 8688343036483f..00000000000000
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.cpp
+++ /dev/null
@@ -1,98 +0,0 @@
-//===-- RISCVCounters.cpp ---------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines RISC-V perf counters.
-//
-//===----------------------------------------------------------------------===//
-
-#include "RISCVCounters.h"
-
-namespace llvm {
-namespace exegesis {
-
-// This implementation of RISCV target for Exegesis doesn't use libpfm
-// and provides manual implementation of performance counters.
-
-inline uint64_t getRISCVCpuCyclesCount() {
-#if defined(__riscv) && defined(__linux__)
-#if __riscv_xlen == 32
-  uint32_t cycles_x3, cycles_x2, cycles_x4;
-  asm volatile("again:\n"
-               "rdcycleh %1\n"
-               "rdcycle %0\n"
-               "rdcycleh %2\n"
-               "bne %1, %2, again\n"
-               : "=r"(cycles_x2), "=r"(cycles_x3), "=r"(cycles_x4));
-  return static_cast<uint64_t>((static_cast<uint64_t>(cycles_x3) << 32) |
-                               cycles_x2);
-#else
-  uint64_t cycles;
-  asm volatile("rdcycle %0" : "=r"(cycles));
-  return static_cast<uint64_t>(cycles);
-#endif
-#else
-  return 0;
-#endif
-}
-
-class RISCVCpuCyclesCounter : public pfm::CounterGroup {
-  uint64_t StartValue;
-  uint64_t EndValue;
-  uint64_t MeasurementCycles;
-
-public:
-  explicit RISCVCpuCyclesCounter(pfm::PerfEvent &&Event);
-
-  void start() override { StartValue = getRISCVCpuCyclesCount(); }
-
-  void stop() override { EndValue = getRISCVCpuCyclesCount(); }
-
-  Expected<llvm::SmallVector<int64_t, 4>>
-  readOrError(StringRef FunctionBytes) const override;
-};
-
-RISCVCpuCyclesCounter::RISCVCpuCyclesCounter(pfm::PerfEvent &&Event)
-    : CounterGroup(std::move(Event), {}) {
-#if defined(__riscv) && defined(__linux__)
-  char Value[2] = "0";
-  int File = 0;
-  std::error_code FileError =
-      sys::fs::openFileForRead("/proc/sys/kernel/perf_user_access", File);
-  sys::fs::file_t FileNative = sys::fs::convertFDToNativeFile(File);
-  Expected<size_t> ReadBytes = sys::fs::readNativeFile(FileNative, Value);
-
-  if (FileError || !ReadBytes || strcmp(Value, "1") != 0) {
-    report_fatal_error(
-        "Please write 'sudo echo 1 > /proc/sys/kernel/perf_user_access'");
-  }
-#endif
-  StartValue = getRISCVCpuCyclesCount();
-  EndValue = getRISCVCpuCyclesCount();
-  MeasurementCycles = EndValue - StartValue;
-  // If values of two calls CpuCyclesCounters don`t differ
-  // it means that counters don`t configured properly, report error.
-  // MeasurementCycles the smallest interval between two counter calls.
-  if (MeasurementCycles == 0) {
-    report_fatal_error("MeasurementCycles == 0, "
-                       "performance counters are not configured.");
-  }
-  StartValue = EndValue = 0;
-}
-
-Expected<SmallVector<int64_t, 4>>
-RISCVCpuCyclesCounter::readOrError(StringRef FunctionBytes) const {
-  uint64_t Counter = EndValue - StartValue - MeasurementCycles;
-  return SmallVector<int64_t, 4>({static_cast<int64_t>(Counter)});
-}
-std::unique_ptr<pfm::CounterGroup>
-createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event) {
-  return std::make_unique<RISCVCpuCyclesCounter>(std::move(Event));
-}
-
-} // namespace exegesis
-} // namespace llvm
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h b/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h
deleted file mode 100644
index 203f6af76aaaf8..00000000000000
--- a/llvm/tools/llvm-exegesis/lib/RISCV/RISCVCounters.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===-- RISCVCounters.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// RISC-V perf counters.
-///
-/// More info at: https://lwn.net/Articles/680985
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H
-#define LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H
-
-#include "../PerfHelper.h"
-#include "../Target.h"
-#include <memory>
-
-namespace llvm {
-namespace exegesis {
-
-std::unique_ptr<pfm::CounterGroup>
-createRISCVCpuCyclesCounter(pfm::PerfEvent &&Event);
-
-} // namespace exegesis
-} // namespace llvm
-
-#endif // LLVM_TOOLS_LLVM_EXEGESIS_LIB_RISCV_RISCVCOUNTERS_H
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index dcc4895e077f76..fc6a1e945c67be 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -8,8 +8,6 @@
 
 #include "../Target.h"
 
-#include "RISCVCounters.h"
-
 #include "MCTargetDesc/RISCVBaseInfo.h"
 #include "MCTargetDesc/RISCVMCTargetDesc.h"
 #include "MCTargetDesc/RISCVMatInt.h"
@@ -31,17 +29,10 @@ namespace exegesis {
 
 namespace {
 
-#include "RISCVGenExegesis.inc"
-
 class ExegesisRISCVTarget : public ExegesisTarget {
 public:
   ExegesisRISCVTarget();
 
-  Expected<std::unique_ptr<pfm::CounterGroup>>
-  createCounter(StringRef CounterName, const LLVMState &State,
-                ArrayRef<const char *> ValidationCounters,
-                const pid_t ProcessID) const override;
-
   bool checkOpcodeSupported(int Opcode,
                             const MCSubtargetInfo &SI) const override;
 
@@ -81,19 +72,8 @@ class ExegesisRISCVTarget : public ExegesisTarget {
 };
 
 ExegesisRISCVTarget::ExegesisRISCVTarget()
-    : ExegesisTarget(RISCVCpuPfmCounters, RISCV_MC::isOpcodeAvailable) {}
-
-Expected<std::unique_ptr<pfm::CounterGroup>> ExegesisRISCVTarget::createCounter(
-    StringRef CounterName, const LLVMState &State,
-    ArrayRef<const char *> ValidationCounters, const pid_t ProcessID) const {
-  if (CounterName == RISCVPfmCounterNames[0]) {
-    // TODO add support for Linux perf counters
-    return createRISCVCpuCyclesCounter(pfm::PerfEvent(CounterName));
-  }
-  return make_error<Failure>(Twine("Unsupported performance counter '")
-                                 .concat(CounterName)
-                                 .concat("'"));
-}
+    : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{},
+                     RISCV_MC::isOpcodeAvailable) {}
 
 bool ExegesisRISCVTarget::checkOpcodeSupported(
     int Opcode, const MCSubtargetInfo &SI) const {
@@ -135,11 +115,12 @@ static std::vector<MCInst> loadIntReg(const MCSubtargetInfo &STI, unsigned Reg,
   for (const RISCVMatInt::Inst &Inst : InstSeq) {
     switch (Inst.getOpndKind()) {
     case RISCVMatInt::Imm:
-      MatIntInstrs.push_back(
-          MCInstBuilder(RISCV::LUI).addReg(DestReg).addImm(Inst.getImm()));
+      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
+                                 .addReg(DestReg)
+                                 .addImm(Inst.getImm()));
       break;
     case RISCVMatInt::RegX0:
-      MatIntInstrs.push_back(MCInstBuilder(RISCV::ADD_UW)
+      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
                                  .addReg(DestReg)
                                  .addReg(SrcReg)
                                  .addReg(RISCV::X0));
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index d3447b62bb2392..b3c7108d840d38 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -2262,7 +2262,6 @@ llvm_target_lib_list = [lib for lib in [
             ("-gen-register-info", "lib/Target/RISCV/RISCVGenRegisterInfo.inc"),
             ("-gen-subtarget", "lib/Target/RISCV/RISCVGenSubtargetInfo.inc"),
             ("-gen-searchable-tables", "lib/Target/RISCV/RISCVGenSearchableTables.inc"),
-	    ("-gen-exegesis", "lib/Target/RISCV/RISCVGenExegesis.inc"),
         ],
         "tbl_deps": [
             ":riscv_isel_target_gen",

>From 6b6c0af00b7bea04b9c1830d747cb060ad7ff642 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Fri, 27 Sep 2024 17:32:06 +0300
Subject: [PATCH 19/37] Addressing review comments

---
 .../test/tools/llvm-exegesis/RISCV/latency-by-load.s |  1 -
 llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp     | 12 ++++++------
 llvm/tools/llvm-exegesis/lib/MCInstrDescView.h       |  4 ++--
 llvm/tools/llvm-exegesis/lib/PerfHelper.h            |  2 +-
 4 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
index ba985e231e5ce0..c73c0155ddfa23 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
@@ -42,7 +42,6 @@ LBU-NEXT:     - 'LBU X10 X10 i_0x0'
 
 LUI: LUI: No strategy found to make the execution serial
 
-
 # RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=LB %s
 
 LB:      ---
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
index f9b3666d36f788..c9225e51213e59 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
@@ -96,11 +96,11 @@ Instruction::Instruction(const MCInstrDesc *Description, StringRef Name,
                          const BitVector *ImplUseRegs,
                          const BitVector *AllDefRegs,
                          const BitVector *AllUseRegs,
-                         const BitVector *NotMemoryRegs)
+                         const BitVector *NonMemoryRegs)
     : Description(*Description), Name(Name), Operands(std::move(Operands)),
       Variables(std::move(Variables)), ImplDefRegs(*ImplDefRegs),
       ImplUseRegs(*ImplUseRegs), AllDefRegs(*AllDefRegs),
-      AllUseRegs(*AllUseRegs), NotMemoryRegs(*NotMemoryRegs) {}
+      AllUseRegs(*AllUseRegs), NonMemoryRegs(*NonMemoryRegs) {}
 
 std::unique_ptr<Instruction>
 Instruction::create(const MCInstrInfo &InstrInfo,
@@ -167,7 +167,7 @@ Instruction::create(const MCInstrInfo &InstrInfo,
   BitVector ImplUseRegs = RATC.emptyRegisters();
   BitVector AllDefRegs = RATC.emptyRegisters();
   BitVector AllUseRegs = RATC.emptyRegisters();
-  BitVector NotMemoryRegs = RATC.emptyRegisters();
+  BitVector NonMemoryRegs = RATC.emptyRegisters();
 
   for (const auto &Op : Operands) {
     if (Op.isReg()) {
@@ -181,7 +181,7 @@ Instruction::create(const MCInstrInfo &InstrInfo,
       if (Op.isUse() && Op.isImplicit())
         ImplUseRegs |= AliasingBits;
       if (Op.isUse() && !Op.isMemory())
-        NotMemoryRegs |= AliasingBits;
+        NonMemoryRegs |= AliasingBits;
     }
   }
   // Can't use make_unique because constructor is private.
@@ -191,7 +191,7 @@ Instruction::create(const MCInstrInfo &InstrInfo,
       BVC.getUnique(std::move(ImplUseRegs)),
       BVC.getUnique(std::move(AllDefRegs)),
       BVC.getUnique(std::move(AllUseRegs)),
-      BVC.getUnique(std::move(NotMemoryRegs))));
+      BVC.getUnique(std::move(NonMemoryRegs))));
 }
 
 const Operand &Instruction::getPrimaryOperand(const Variable &Var) const {
@@ -248,7 +248,7 @@ bool Instruction::hasAliasingRegisters(
 
 bool Instruction::hasAliasingNotMemoryRegisters(
     const BitVector &ForbiddenRegisters) const {
-  return anyCommonExcludingForbidden(AllDefRegs, NotMemoryRegs,
+  return anyCommonExcludingForbidden(AllDefRegs, NonMemoryRegs,
                                      ForbiddenRegisters);
 }
 
diff --git a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
index c6f47a438ad495..d7712e21c32c1c 100644
--- a/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
+++ b/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
@@ -167,14 +167,14 @@ struct Instruction {
   const BitVector &AllDefRegs;  // The set of all aliased def registers.
   const BitVector &AllUseRegs;  // The set of all aliased use registers.
   // The set of all aliased not memory use registers.
-  const BitVector &NotMemoryRegs;
+  const BitVector &NonMemoryRegs;
 
 private:
   Instruction(const MCInstrDesc *Description, StringRef Name,
               SmallVector<Operand, 8> Operands,
               SmallVector<Variable, 4> Variables, const BitVector *ImplDefRegs,
               const BitVector *ImplUseRegs, const BitVector *AllDefRegs,
-              const BitVector *AllUseRegs, const BitVector *NotMemoryRegs);
+              const BitVector *AllUseRegs, const BitVector *NonMemoryRegs);
 };
 
 // Instructions are expensive to instantiate. This class provides a cache of
diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
index 1e0fca73808630..4a825b293b7169 100644
--- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h
+++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
@@ -119,7 +119,7 @@ class CounterGroup {
   virtual void start();
 
   /// Stops the measurement of the event.
-  virtual void stop();
+  void stop();
 
   /// Returns the current value of the counter or error if it cannot be read.
   /// FunctionBytes: The benchmark function being executed.

>From c4244038d3cf53568bb49d33fead0277f4666fae Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Mon, 7 Oct 2024 18:16:26 +0300
Subject: [PATCH 20/37] Fix code format

---
 llvm/tools/llvm-exegesis/lib/SnippetFile.cpp | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index f38b233a95d4a1..8534637626f7d5 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -37,11 +37,10 @@ namespace {
 // An MCStreamer that reads a BenchmarkCode definition from a file.
 class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
 public:
-  explicit BenchmarkCodeStreamer(
-      const ExegesisTarget &Target, MCContext *Context,
-      const LLVMState &State, BenchmarkCode *Result)
-      : MCStreamer(*Context), Target(Target), State(State),
-        Result(Result) {}
+  explicit BenchmarkCodeStreamer(const ExegesisTarget &Target,
+                                 MCContext *Context, const LLVMState &State,
+                                 BenchmarkCode *Result)
+      : MCStreamer(*Context), Target(Target), State(State), Result(Result) {}
   // Implementation of the MCStreamer interface. We only care about
   // instructions.
   void emitInstruction(const MCInst &Instruction,
@@ -256,7 +255,8 @@ Expected<std::vector<BenchmarkCode>> readSnippets(const LLVMState &State,
       TM.getTarget().createMCObjectFileInfo(Context, /*PIC=*/false));
   Context.setObjectFileInfo(ObjectFileInfo.get());
   Context.initInlineSourceManager();
-  BenchmarkCodeStreamer Streamer(State.getExegesisTarget(), &Context, State, &Result);
+  BenchmarkCodeStreamer Streamer(State.getExegesisTarget(), &Context, State,
+                                 &Result);
 
   std::string Error;
   raw_string_ostream ErrorStream(Error);

>From 68006e5dbc200239f862d2424e887445f368e107 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Tue, 8 Oct 2024 21:47:35 +0300
Subject: [PATCH 21/37] Addressing review comments

---
 .../lib/SerialSnippetGenerator.cpp            | 46 +------------------
 llvm/tools/llvm-exegesis/lib/SnippetFile.cpp  |  3 --
 2 files changed, 1 insertion(+), 48 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index ffceb6ac82faca..08d5cd12f0a6d3 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -109,51 +109,7 @@ static void appendCodeTemplates(const LLVMState &State,
   }
   case ExecutionMode::SERIAL_VIA_MEMORY_INSTR: {
     // Select back-to-back memory instruction.
-
-    auto &I = Variant.getInstr();
-    if (I.Description.mayLoad()) {
-      // If instruction is load, we can self-alias it in case when instruction
-      // overrides whole address register. For that we use provided scratch
-      // memory.
-
-      // TODO: now it is not checked if load writes the whole register.
-
-      auto DefOpIt = find_if(I.Operands, [](Operand const &op) {
-        return op.isDef() && op.isReg();
-      });
-
-      if (DefOpIt == I.Operands.end())
-        return;
-
-      const Operand &DefOp = *DefOpIt;
-      auto &ET = State.getExegesisTarget();
-      auto ScratchMemoryRegister = ET.getScratchMemoryRegister(
-          State.getTargetMachine().getTargetTriple());
-      auto &RegClass =
-          State.getTargetMachine().getMCRegisterInfo()->getRegClass(
-              DefOp.getExplicitOperandInfo().RegClass);
-
-      // Register classes of def operand and memory operand must be the same
-      // to perform aliasing.
-      if (!RegClass.contains(ScratchMemoryRegister))
-        return;
-
-      ET.fillMemoryOperands(Variant, ScratchMemoryRegister, 0);
-      Variant.getValueFor(DefOp) = MCOperand::createReg(ScratchMemoryRegister);
-
-      CodeTemplate CT;
-      CT.Execution = ExecutionModeBit;
-      if (CT.ScratchSpacePointerInReg == 0)
-        CT.ScratchSpacePointerInReg = ScratchMemoryRegister;
-
-      CT.Info = std::string(ExecutionClassDescription);
-      CT.Instructions.push_back(std::move(Variant));
-      CT.PreinitScratchMemory.emplace_back(ScratchMemoryRegister,
-                                           /* Offset */ 0);
-      CodeTemplates.push_back(std::move(CT));
-    }
-
-    // TODO: implement more cases
+    // TODO: Implement me.
     return;
   }
   case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: {
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index 8534637626f7d5..282bc8ca912492 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -208,9 +208,6 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
                     Align ByteAlignment, SMLoc Loc) override {}
 
   unsigned findRegisterByName(const StringRef RegName) const {
-    // TODO make use of RegNameToRegNo map
-    if (unsigned Reg = Target.findRegisterByName(RegName))
-      return Reg;
     std::optional<MCRegister> RegisterNumber =
         State.getRegisterNumberFromName(RegName);
     if (!RegisterNumber.has_value()) {

>From 2fbe7b923f0313a4d5821e088084de29bbb40419 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Mon, 28 Oct 2024 14:48:20 +0300
Subject: [PATCH 22/37] Fixed consequences of PR
 https://github.com/llvm/llvm-project/pull/112314. Removed support for load

---
 .../RISCV/latency-by-extension-C.s            | 17 ------
 .../llvm-exegesis/RISCV/latency-by-load.s     | 59 -------------------
 llvm/tools/llvm-exegesis/lib/CodeTemplate.h   |  4 --
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp |  2 +-
 4 files changed, 1 insertion(+), 81 deletions(-)
 delete mode 100644 llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s

diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
index 00bd79729539f0..9e94f024ed1162 100644
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
+++ b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-extension-C.s
@@ -46,20 +46,3 @@ C_SRLI-NEXT: key:
 C_SRLI-NEXT:   instructions:
 C_SRLI-NEXT:     - 'C_SRLI [[REG101:X[0-9]+]] [[REG102:X[0-9]+]] [[IMM10:i_0x[0-9]+]]'
 C_SRLI-DAG: ...
-
-
-# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LD -mattr=+c | FileCheck --check-prefix=C_LD %s
-
-C_LD:      ---
-C_LD-NEXT: mode: latency
-C_LD-NEXT: key:
-C_LD-NEXT:   instructions:
-C_LD-NEXT:     - 'C_LD [[REG61:X[0-9]+]] [[REG62:X[0-9]+]] [[IMM6:i_0x[0-9]+]]'
-
-# RUN: llvm-exegesis  -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=C_LW -mattr=+c | FileCheck --check-prefix=C_LW %s
-
-C_LW:      ---
-C_LW-NEXT: mode: latency
-C_LW-NEXT: key:
-C_LW-NEXT:   instructions:
-C_LW-NEXT:     - 'C_LW [[REG71:X[0-9]+]] [[REG72:X[0-9]+]] [[IMM7:i_0x[0-9]+]]'
diff --git a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s b/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
deleted file mode 100644
index c73c0155ddfa23..00000000000000
--- a/llvm/test/tools/llvm-exegesis/RISCV/latency-by-load.s
+++ /dev/null
@@ -1,59 +0,0 @@
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LD | FileCheck --check-prefix=LD %s
-
-LD:      ---
-LD-NEXT: mode: latency
-LD-NEXT: key:
-LD-NEXT:   instructions:
-LD-NEXT:     - 'LD X10 X10 i_0x0'
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LW | FileCheck --check-prefix=LW %s
-
-LW:      ---
-LW-NEXT: mode: latency
-LW-NEXT: key:
-LW-NEXT:   instructions:
-LW-NEXT:     - 'LW X10 X10 i_0x0'
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LH | FileCheck --check-prefix=LH %s
-
-LH:      ---
-LH-NEXT: mode: latency
-LH-NEXT: key:
-LH-NEXT:   instructions:
-LH-NEXT:     - 'LH X10 X10 i_0x0'
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LWU | FileCheck --check-prefix=LWU %s
-
-LWU:      ---
-LWU-NEXT: mode: latency
-LWU-NEXT: key:
-LWU-NEXT:   instructions:
-LWU-NEXT:     - 'LWU X10 X10 i_0x0'
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LBU | FileCheck --check-prefix=LBU %s
-
-LBU:      ---
-LBU-NEXT: mode: latency
-LBU-NEXT: key:
-LBU-NEXT:   instructions:
-LBU-NEXT:     - 'LBU X10 X10 i_0x0'
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LUI 2>&1 | FileCheck --check-prefix=LUI %s
-
-LUI: LUI: No strategy found to make the execution serial
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LB | FileCheck --check-prefix=LB %s
-
-LB:      ---
-LB-NEXT: mode: latency
-LB-NEXT: key:
-LB-NEXT:   instructions:
-LB-NEXT:     - 'LB X10 X10 i_0x0'
-
-# RUN: llvm-exegesis -mode=latency -mtriple=riscv64-unknown-linux-gnu --mcpu=generic --benchmark-phase=assemble-measured-code -opcode-name=LR_W_RL -mattr="+a" | FileCheck --check-prefix=LR_W_RL %s
-
-LR_W_RL:      ---
-LR_W_RL-NEXT: mode: latency
-LR_W_RL-NEXT: key:
-LR_W_RL-NEXT:   instructions:
-LR_W_RL-NEXT:     - 'LR_W_RL X10 X10'
diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
index 662fd90306a45e..f565d3d0f1640e 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
@@ -135,10 +135,6 @@ struct CodeTemplate {
   // the pointer to this memory is passed in to the function.
   unsigned ScratchSpacePointerInReg = 0;
 
-  // Require to pre-store value of a given register (fisrt)
-  // to scratch memory with given offset (second)
-  SmallVector<std::pair<unsigned, unsigned>, 2> PreinitScratchMemory;
-
 #if defined(__GNUC__) && (defined(__clang__) || LLVM_GNUC_PREREQ(8, 0, 0))
   // FIXME: GCC7 bug workaround. Drop #if after GCC7 no longer supported.
 private:
diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index fc6a1e945c67be..1768a263c52e43 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -344,7 +344,7 @@ void ExegesisRISCVTarget::processInstructionReservedRegs(
   case RISCV::C_ADDI4SPN:
     AssignedValue = MCOperand::createReg(RISCV::X2);
     break;
-  case RISCV::C_ADDI_NOP:
+  case RISCV::C_NOP:
   case RISCV::C_LI_HINT:
   case RISCV::C_LUI_HINT:
   case RISCV::C_MV_HINT:

>From e4fdd4b28bfee99bba525249c1437e41e2cc58be Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 31 Oct 2024 19:54:12 +0300
Subject: [PATCH 23/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 32 -------------------
 .../lib/SerialSnippetGenerator.cpp            |  3 --
 llvm/tools/llvm-exegesis/lib/Target.h         | 13 --------
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp    |  6 ++--
 4 files changed, 3 insertions(+), 51 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 1768a263c52e43..80c025ed3fd27a 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -33,9 +33,6 @@ class ExegesisRISCVTarget : public ExegesisTarget {
 public:
   ExegesisRISCVTarget();
 
-  bool checkOpcodeSupported(int Opcode,
-                            const MCSubtargetInfo &SI) const override;
-
   MCRegister findRegisterByName(const StringRef RegName) const override;
 
   bool matchesArch(Triple::ArchType Arch) const override;
@@ -55,9 +52,6 @@ class ExegesisRISCVTarget : public ExegesisTarget {
   void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
                           unsigned Offset) const override;
 
-  virtual std::vector<MCInst>
-  storeRegValueToScratch(const MCSubtargetInfo &STI, unsigned Reg,
-                         unsigned Offset) const override;
   ArrayRef<unsigned> getUnavailableRegisters() const override;
 
   Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var,
@@ -75,16 +69,6 @@ ExegesisRISCVTarget::ExegesisRISCVTarget()
     : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{},
                      RISCV_MC::isOpcodeAvailable) {}
 
-bool ExegesisRISCVTarget::checkOpcodeSupported(
-    int Opcode, const MCSubtargetInfo &SI) const {
-  auto Features = SI.getFeatureBits();
-  FeatureBitset AvailableFeatures =
-      RISCV_MC::computeAvailableFeatures(Features);
-  FeatureBitset RequiredFeatures = RISCV_MC::computeRequiredFeatures(Opcode);
-  FeatureBitset MissingFeatures = RequiredFeatures & ~AvailableFeatures;
-  return MissingFeatures.none();
-}
-
 #define GET_REGISTER_MATCHER
 #include "RISCVGenAsmMatcher.inc"
 
@@ -281,22 +265,6 @@ void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT,
   IT.getValueFor(MemOp) = MCOperand::createReg(Reg);
 }
 
-std::vector<MCInst> ExegesisRISCVTarget::storeRegValueToScratch(
-    const MCSubtargetInfo &STI, unsigned Reg, unsigned Offset) const {
-  std::vector<MCInst> Ret;
-
-  if (RISCV::GPRRegClass.contains(Reg)) {
-    Ret.push_back(MCInstBuilder(RISCV::SW)
-                      .addReg(Reg)
-                      .addReg(ScratchMemoryReg)
-                      .addImm(Offset));
-    return Ret;
-  }
-
-  errs() << "Failed to store value of " << Reg << " register to scratch memory";
-  return {nop()};
-}
-
 const unsigned UnavailableRegisters[4] = {RISCV::X0, DefaultLoopCounterReg,
                                           ScratchIntReg, ScratchMemoryReg};
 
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 08d5cd12f0a6d3..9b74e3ecdd2b80 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -52,9 +52,6 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
       continue;
     if (OtherOpcode == Instr->Description.getOpcode())
       continue;
-    if (State.getExegesisTarget().checkOpcodeSupported(
-            OtherOpcode, State.getSubtargetInfo()))
-      continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
     const MCInstrDesc &OtherInstrDesc = OtherInstr.Description;
     if (OtherInstr.hasMemoryOperands())
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 1dcef5e51f4e51..94a5672ab3cb7d 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -86,11 +86,6 @@ class ExegesisTarget {
                 ArrayRef<const char *> ValidationCounters,
                 const pid_t ProcessID = 0) const;
 
-  virtual bool checkOpcodeSupported(int Opcode,
-                                    const MCSubtargetInfo &SI) const {
-    return false;
-  }
-
   // Find register by name, NoRegister if not found.
   virtual MCRegister findRegisterByName(const StringRef RegName) const {
     return MCRegister::NoRegister;
@@ -211,14 +206,6 @@ class ExegesisTarget {
         "fillMemoryOperands() requires getScratchMemoryRegister() > 0");
   }
 
-  // Generates code to store register into scratch memory with offset.
-  virtual std::vector<MCInst> storeRegValueToScratch(const MCSubtargetInfo &STI,
-                                                     unsigned Reg,
-                                                     unsigned Offset) const {
-    llvm_unreachable(
-        "storeRegValueToScratch() requires getScratchMemoryRegister() > 0");
-  }
-
   // Returns a counter usable as a loop counter.
   virtual unsigned getDefaultLoopCounterRegister(const Triple &) const {
     return 0;
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index c4236820c1462e..7eaa0bb763be05 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -333,16 +333,16 @@ bool OpcodeNameParser::parse(
     std::vector<std::pair<StringRef, StringRef>> &Val) {
   SmallVector<StringRef, 2> Pieces;
   StringRef(OpcodeNames)
-      .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false);
+      .split(Pieces, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
   for (const StringRef &OpcodeName : Pieces) {
     size_t DotDotPos = OpcodeName.find("..");
     if (DotDotPos == StringRef::npos) {
-      Val.push_back(std::make_pair(OpcodeName, OpcodeName));
+      Val.emplace_back(std::make_pair(OpcodeName, OpcodeName));
       continue;
     }
     StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos);
     StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2);
-    Val.push_back(std::make_pair(BeginOpcodeName, EndOpcodeName));
+    Val.emplace_back(std::make_pair(BeginOpcodeName, EndOpcodeName));
   }
   if (Val.empty())
     return O.error("No matching opcode names");

>From c2b189edff1075e8f59580e3e7f5b8f272ceec9e Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 31 Oct 2024 20:35:02 +0300
Subject: [PATCH 24/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 7eaa0bb763be05..0875155d7120f5 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -337,12 +337,12 @@ bool OpcodeNameParser::parse(
   for (const StringRef &OpcodeName : Pieces) {
     size_t DotDotPos = OpcodeName.find("..");
     if (DotDotPos == StringRef::npos) {
-      Val.emplace_back(std::make_pair(OpcodeName, OpcodeName));
+      Val.emplace_back(OpcodeName, OpcodeName);
       continue;
     }
     StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos);
     StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2);
-    Val.emplace_back(std::make_pair(BeginOpcodeName, EndOpcodeName));
+    Val.emplace_back(BeginOpcodeName, EndOpcodeName);
   }
   if (Val.empty())
     return O.error("No matching opcode names");

>From f36c7e8ce2bdf87ad5e134a4d08f7540f6911f9a Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 31 Oct 2024 21:07:27 +0300
Subject: [PATCH 25/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 80c025ed3fd27a..7e2b0410be89a3 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -18,7 +18,6 @@
 #define GET_AVAILABLE_OPCODE_CHECKER
 #include "RISCVGenInstrInfo.inc"
 #undef GET_COMPUTE_FEATURES
-#undef GET_AVAILABLE_OPCODE_CHECKER
 
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 
@@ -254,11 +253,11 @@ void ExegesisRISCVTarget::fillMemoryOperands(InstructionTemplate &IT,
   auto &I = IT.getInstr();
 
   auto MemOpIt =
-      find_if(I.Operands, [](Operand const &Op) { return Op.isMemory(); });
+      find_if(I.Operands, [](const Operand &Op) { return Op.isMemory(); });
   assert(MemOpIt != I.Operands.end() &&
          "Instruction must have memory operands");
 
-  auto &MemOp = *MemOpIt;
+  const Operand &MemOp = *MemOpIt;
 
   assert(MemOp.isReg() && "Memory operand expected to be register");
 
@@ -269,7 +268,7 @@ const unsigned UnavailableRegisters[4] = {RISCV::X0, DefaultLoopCounterReg,
                                           ScratchIntReg, ScratchMemoryReg};
 
 ArrayRef<unsigned> ExegesisRISCVTarget::getUnavailableRegisters() const {
-  return ArrayRef(UnavailableRegisters);
+  return UnavailableRegisters;
 }
 
 Error ExegesisRISCVTarget::randomizeTargetMCOperand(
@@ -329,11 +328,10 @@ std::vector<InstructionTemplate>
 ExegesisRISCVTarget::generateInstructionVariants(
     const Instruction &Instr, unsigned int MaxConfigsPerOpcode) const {
   InstructionTemplate IT{&Instr};
-  for (const Operand &Op : Instr.Operands) {
+  for (const Operand &Op : Instr.Operands)
     if (Op.isMemory()) {
       IT.getValueFor(Op) = MCOperand::createReg(ScratchMemoryReg);
     }
-  }
   return {IT};
 }
 

>From eb3bd6f9ea789b3683f4fdb5f9f3cbf8befd1b6b Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Mon, 18 Nov 2024 16:24:40 +0300
Subject: [PATCH 26/37] Deleted processInstructionReservedRegs

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 30 -------------------
 .../lib/SerialSnippetGenerator.cpp            |  1 -
 llvm/tools/llvm-exegesis/lib/Target.h         |  3 --
 3 files changed, 34 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 7e2b0410be89a3..70894c04b76efb 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -57,8 +57,6 @@ class ExegesisRISCVTarget : public ExegesisTarget {
                                  MCOperand &AssignedValue,
                                  const BitVector &ForbiddenRegs) const override;
 
-  void processInstructionReservedRegs(InstructionTemplate &IT) const override;
-
   std::vector<InstructionTemplate>
   generateInstructionVariants(const Instruction &Instr,
                               unsigned MaxConfigsPerOpcode) const override;
@@ -296,34 +294,6 @@ Error ExegesisRISCVTarget::randomizeTargetMCOperand(
   return Error::success();
 }
 
-// Process instructions that used ReservedRegisters.
-// We must not create instructions that used rd=x0. But for some of them in C
-// extension we use registers in which we are really not going to write to.
-// Registers were reserved in RISCVRegisterInfo.cpp using markSuperRegs function
-// and should not be redeclared. Thus we must set appropriate register
-// explicitly for each instruction according to RVC spec.
-void ExegesisRISCVTarget::processInstructionReservedRegs(
-    InstructionTemplate &IT) const {
-  MCOperand &AssignedValue = IT.getValueForOperandIdx(0);
-
-  switch (IT.getOpcode()) {
-  case RISCV::C_ADDI16SP:
-  case RISCV::C_ADDI4SPN:
-    AssignedValue = MCOperand::createReg(RISCV::X2);
-    break;
-  case RISCV::C_NOP:
-  case RISCV::C_LI_HINT:
-  case RISCV::C_LUI_HINT:
-  case RISCV::C_MV_HINT:
-  case RISCV::C_ADD_HINT:
-  case RISCV::C_SLLI_HINT:
-    AssignedValue = MCOperand::createReg(RISCV::X0);
-    break;
-  default:
-    break;
-  }
-}
-
 std::vector<InstructionTemplate>
 ExegesisRISCVTarget::generateInstructionVariants(
     const Instruction &Instr, unsigned int MaxConfigsPerOpcode) const {
diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 9b74e3ecdd2b80..9573e2242ad3f7 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -96,7 +96,6 @@ static void appendCodeTemplates(const LLVMState &State,
   case ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS: {
     // Picking whatever value for the tied variable will make the instruction
     // serial.
-    State.getExegesisTarget().processInstructionReservedRegs(Variant);
     CodeTemplate CT;
     CT.Execution = ExecutionModeBit;
     CT.Info = std::string(ExecutionClassDescription);
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 94a5672ab3cb7d..c46eb3e1b8aaac 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -243,9 +243,6 @@ class ExegesisTarget {
         "targets with target-specific operands should implement this");
   }
 
-  // Process instructions that used reserved registers.
-  virtual void processInstructionReservedRegs(InstructionTemplate &IT) const {}
-
   // Returns true if this instruction is supported as a back-to-back
   // instructions.
   // FIXME: Eventually we should discover this dynamically.

>From 70541d3be755eaa89c91b1536a992cfc78f07263 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Mon, 18 Nov 2024 16:26:58 +0300
Subject: [PATCH 27/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 70894c04b76efb..84e5e3458bb849 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -139,7 +139,7 @@ static std::vector<MCInst> loadFPRegBits(const MCSubtargetInfo &STI,
 }
 
 // main idea is:
-// we support APInt only if (represented as double) it have zero fractional
+// we support APInt only if (represented as double) it has zero fractional
 // part: 1.0, 2.0, 3.0, etc... then we can do the trick: write int to tmp reg t5
 // and then do FCVT this is only reliable thing in 32-bit mode, otherwise we
 // need to use __floatsidf
@@ -198,8 +198,7 @@ std::vector<MCInst> ExegesisRISCVTarget::setRegTo(const MCSubtargetInfo &STI,
   if (RISCV::FPR64RegClass.contains(Reg)) {
     if (STI.hasFeature(RISCV::Feature64Bit))
       return loadFPRegBits(STI, Reg, Value, RISCV::FMV_D_X);
-    else
-      return loadFP64RegBits32(STI, Reg, Value);
+    return loadFP64RegBits32(STI, Reg, Value);
   }
   if (Reg == RISCV::FRM || Reg == RISCV::VL || Reg == RISCV::VLENB ||
       Reg == RISCV::VTYPE || RISCV::GPRPairRegClass.contains(Reg) ||

>From 570fee5113abdc4192258fa762ede58da87ac4c0 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Tue, 19 Nov 2024 01:01:03 +0300
Subject: [PATCH 28/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp | 9 ---------
 llvm/tools/llvm-exegesis/lib/CodeTemplate.h   | 2 --
 2 files changed, 11 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
index 74a78b0f1c56fb..fd156ee01e7ce5 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
@@ -57,15 +57,6 @@ const MCOperand &InstructionTemplate::getValueFor(const Operand &Op) const {
   return getValueFor(Instr->Variables[Op.getVariableIndex()]);
 }
 
-MCOperand &InstructionTemplate::getValueForOperandIdx(unsigned OpIdx) {
-  return getValueFor(Instr->Variables[OpIdx]);
-}
-
-const MCOperand &
-InstructionTemplate::getValueForOperandIdx(unsigned OpIdx) const {
-  return getValueFor(Instr->Variables[OpIdx]);
-}
-
 bool InstructionTemplate::hasImmediateVariables() const {
   return any_of(Instr->Variables, [this](const Variable &Var) {
     return Instr->getPrimaryOperand(Var).isImmediate();
diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
index f565d3d0f1640e..7aca224302a1ff 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
@@ -35,8 +35,6 @@ struct InstructionTemplate {
   const MCOperand &getValueFor(const Variable &Var) const;
   MCOperand &getValueFor(const Operand &Op);
   const MCOperand &getValueFor(const Operand &Op) const;
-  MCOperand &getValueForOperandIdx(unsigned OpIdx);
-  const MCOperand &getValueForOperandIdx(unsigned OpIdx) const;
   bool hasImmediateVariables() const;
   const Instruction &getInstr() const { return *Instr; }
   ArrayRef<MCOperand> getVariableValues() const { return VariableValues; }

>From c56a94b5af1df3846028f8dd1ae12668083cbd2c Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Thu, 21 Nov 2024 22:46:11 +0300
Subject: [PATCH 29/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 43 +++----------------
 1 file changed, 6 insertions(+), 37 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 84e5e3458bb849..0c27edf032ad30 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -86,44 +86,13 @@ bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const {
 // Stores constant value to a general-purpose (integer) register.
 static std::vector<MCInst> loadIntReg(const MCSubtargetInfo &STI, unsigned Reg,
                                       const APInt &Value) {
-  RISCVMatInt::InstSeq InstSeq =
-      RISCVMatInt::generateInstSeq(Value.getSExtValue(), STI);
-  // First instruction has form 'Op DestReg, X0, Imm'
-  MCRegister SrcReg = RISCV::X0;
-  MCRegister DestReg = Reg;
+  SmallVector<MCInst, 8> MCInstSeq;
   std::vector<MCInst> MatIntInstrs;
-  MatIntInstrs.reserve(InstSeq.size());
-  for (const RISCVMatInt::Inst &Inst : InstSeq) {
-    switch (Inst.getOpndKind()) {
-    case RISCVMatInt::Imm:
-      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
-                                 .addReg(DestReg)
-                                 .addImm(Inst.getImm()));
-      break;
-    case RISCVMatInt::RegX0:
-      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
-                                 .addReg(DestReg)
-                                 .addReg(SrcReg)
-                                 .addReg(RISCV::X0));
-      break;
-    case RISCVMatInt::RegReg:
-      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
-                                 .addReg(DestReg)
-                                 .addReg(SrcReg)
-                                 .addReg(SrcReg));
-      break;
-    case RISCVMatInt::RegImm:
-      MatIntInstrs.push_back(MCInstBuilder(Inst.getOpcode())
-                                 .addReg(DestReg)
-                                 .addReg(SrcReg)
-                                 .addImm(Inst.getImm()));
-      break;
-    default:
-      llvm_unreachable("Unexpected kind!");
-    }
-    // Further instructions have form 'Op DestReg, DestReg, Imm'
-    SrcReg = DestReg;
-  }
+  MCRegister DestReg = Reg;
+
+  RISCVMatInt::generateMCInstSeq(Value.getSExtValue(), STI, DestReg, MCInstSeq);
+  std::copy(MCInstSeq.begin(), MCInstSeq.end(), MatIntInstrs.begin());
+
   return MatIntInstrs;
 }
 

>From a0130eab5937bd3ebdb5bc682222090301c87877 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Mon, 25 Nov 2024 17:40:50 +0300
Subject: [PATCH 30/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 0c27edf032ad30..e280c5dd784f62 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -91,6 +91,7 @@ static std::vector<MCInst> loadIntReg(const MCSubtargetInfo &STI, unsigned Reg,
   MCRegister DestReg = Reg;
 
   RISCVMatInt::generateMCInstSeq(Value.getSExtValue(), STI, DestReg, MCInstSeq);
+  MatIntInstrs.resize(MCInstSeq.size());
   std::copy(MCInstSeq.begin(), MCInstSeq.end(), MatIntInstrs.begin());
 
   return MatIntInstrs;

>From 9859fb6f378798d98a16849b8b5377d461758c48 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Tue, 3 Dec 2024 18:52:37 +0300
Subject: [PATCH 31/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 100 ++++++++----------
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp    |  75 +++----------
 2 files changed, 55 insertions(+), 120 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index e280c5dd784f62..891818b625fe14 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -14,10 +14,8 @@
 #include "RISCVInstrInfo.h"
 
 // include computeAvailableFeatures and computeRequiredFeatures.
-#define GET_COMPUTE_FEATURES
 #define GET_AVAILABLE_OPCODE_CHECKER
 #include "RISCVGenInstrInfo.inc"
-#undef GET_COMPUTE_FEATURES
 
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 
@@ -28,61 +26,6 @@ namespace exegesis {
 
 namespace {
 
-class ExegesisRISCVTarget : public ExegesisTarget {
-public:
-  ExegesisRISCVTarget();
-
-  MCRegister findRegisterByName(const StringRef RegName) const override;
-
-  bool matchesArch(Triple::ArchType Arch) const override;
-
-  std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
-                               const APInt &Value) const override;
-
-  unsigned getDefaultLoopCounterRegister(const Triple &) const override;
-
-  void decrementLoopCounterAndJump(MachineBasicBlock &MBB,
-                                   MachineBasicBlock &TargetMBB,
-                                   const MCInstrInfo &MII,
-                                   unsigned LoopRegister) const override;
-
-  unsigned getScratchMemoryRegister(const Triple &TT) const override;
-
-  void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
-                          unsigned Offset) const override;
-
-  ArrayRef<unsigned> getUnavailableRegisters() const override;
-
-  Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var,
-                                 MCOperand &AssignedValue,
-                                 const BitVector &ForbiddenRegs) const override;
-
-  std::vector<InstructionTemplate>
-  generateInstructionVariants(const Instruction &Instr,
-                              unsigned MaxConfigsPerOpcode) const override;
-};
-
-ExegesisRISCVTarget::ExegesisRISCVTarget()
-    : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{},
-                     RISCV_MC::isOpcodeAvailable) {}
-
-#define GET_REGISTER_MATCHER
-#include "RISCVGenAsmMatcher.inc"
-
-MCRegister
-ExegesisRISCVTarget::findRegisterByName(const StringRef RegName) const {
-  MCRegister Reg;
-  if ((Reg = MatchRegisterName(RegName)))
-    return Reg;
-  if ((Reg = MatchRegisterAltName(RegName)))
-    return Reg;
-  return RISCV::NoRegister;
-}
-
-bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const {
-  return Arch == Triple::riscv32 || Arch == Triple::riscv64;
-}
-
 // Stores constant value to a general-purpose (integer) register.
 static std::vector<MCInst> loadIntReg(const MCSubtargetInfo &STI, unsigned Reg,
                                       const APInt &Value) {
@@ -156,6 +99,49 @@ static bool isVectorRegList(unsigned Reg) {
          RISCV::VRN8M1RegClass.contains(Reg);
 }
 
+class ExegesisRISCVTarget : public ExegesisTarget {
+public:
+  ExegesisRISCVTarget();
+
+  bool matchesArch(Triple::ArchType Arch) const override;
+
+  std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
+                               const APInt &Value) const override;
+
+  unsigned getDefaultLoopCounterRegister(const Triple &) const override;
+
+  void decrementLoopCounterAndJump(MachineBasicBlock &MBB,
+                                   MachineBasicBlock &TargetMBB,
+                                   const MCInstrInfo &MII,
+                                   unsigned LoopRegister) const override;
+
+  unsigned getScratchMemoryRegister(const Triple &TT) const override;
+
+  void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg,
+                          unsigned Offset) const override;
+
+  ArrayRef<unsigned> getUnavailableRegisters() const override;
+
+  Error randomizeTargetMCOperand(const Instruction &Instr, const Variable &Var,
+                                 MCOperand &AssignedValue,
+                                 const BitVector &ForbiddenRegs) const override;
+
+  std::vector<InstructionTemplate>
+  generateInstructionVariants(const Instruction &Instr,
+                              unsigned MaxConfigsPerOpcode) const override;
+};
+
+ExegesisRISCVTarget::ExegesisRISCVTarget()
+    : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{},
+                     RISCV_MC::isOpcodeAvailable) {}
+
+#define GET_REGISTER_MATCHER
+#include "RISCVGenAsmMatcher.inc"
+
+bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const {
+  return Arch == Triple::riscv32 || Arch == Triple::riscv64;
+}
+
 std::vector<MCInst> ExegesisRISCVTarget::setRegTo(const MCSubtargetInfo &STI,
                                                   unsigned Reg,
                                                   const APInt &Value) const {
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 0875155d7120f5..fe0b8a0bfda854 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -50,27 +50,15 @@
 namespace llvm {
 namespace exegesis {
 
-struct OpcodeNameParser
-    : public cl::parser<std::vector<std::pair<StringRef, StringRef>>> {
-  OpcodeNameParser(cl::Option &O)
-      : cl::parser<std::vector<std::pair<StringRef, StringRef>>>(O) {}
-  bool parse(cl::Option &O, StringRef ArgName, const StringRef ArgValue,
-             std::vector<std::pair<StringRef, StringRef>> &Val);
-};
-
 static cl::opt<int> OpcodeIndex(
     "opcode-index",
     cl::desc("opcode to measure, by index, or -1 to measure all opcodes"),
     cl::cat(BenchmarkOptions), cl::init(0));
 
-static cl::opt<std::vector<std::pair<StringRef, StringRef>>, false,
-               OpcodeNameParser>
+static cl::opt<std::string>
     OpcodeNames("opcode-name",
-                cl::desc("comma-separated list of opcodes to measure, "
-                         "each item is either opcode name ('OP') "
-                         "or opcode range ('OP1..OP2', ends are inclusive)"),
-                cl::cat(BenchmarkOptions),
-                cl::init(std::vector<std::pair<StringRef, StringRef>>()));
+                cl::desc("comma-separated list of opcodes to measure, by name"),
+                cl::cat(BenchmarkOptions), cl::init(""));
 
 static cl::opt<std::string> SnippetsFile("snippets-file",
                                          cl::desc("code snippets to measure"),
@@ -328,27 +316,6 @@ static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) {
   return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr;
 }
 
-bool OpcodeNameParser::parse(
-    cl::Option &O, StringRef ArgName, const StringRef OpcodeNames,
-    std::vector<std::pair<StringRef, StringRef>> &Val) {
-  SmallVector<StringRef, 2> Pieces;
-  StringRef(OpcodeNames)
-      .split(Pieces, ",", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
-  for (const StringRef &OpcodeName : Pieces) {
-    size_t DotDotPos = OpcodeName.find("..");
-    if (DotDotPos == StringRef::npos) {
-      Val.emplace_back(OpcodeName, OpcodeName);
-      continue;
-    }
-    StringRef BeginOpcodeName = OpcodeName.substr(0, DotDotPos);
-    StringRef EndOpcodeName = OpcodeName.substr(DotDotPos + 2);
-    Val.emplace_back(BeginOpcodeName, EndOpcodeName);
-  }
-  if (Val.empty())
-    return O.error("No matching opcode names");
-  return false;
-}
-
 // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided,
 // and returns the opcode indices or {} if snippets should be read from
 // `SnippetsFile`.
@@ -388,34 +355,16 @@ static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) {
     return 0u;
   };
 
+  SmallVector<StringRef, 2> Pieces;
+  StringRef(OpcodeNames.getValue())
+      .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false);
   std::vector<unsigned> Result;
-  for (const std::pair<StringRef, StringRef> &OpcodeName : OpcodeNames) {
-    if (OpcodeName.first == OpcodeName.second) {
-      if (unsigned Opcode = ResolveName(OpcodeName.first)) {
-        Result.push_back(Opcode);
-        continue;
-      } else {
-        ExitWithError(Twine("unknown opcode ").concat(OpcodeName.first));
-      }
-    } else {
-      StringRef BeginOpcodeName = OpcodeName.first;
-      unsigned BeginOpcode =
-          BeginOpcodeName.empty() ? 1 : ResolveName(BeginOpcodeName);
-      if (BeginOpcode == 0) {
-        ExitWithError(Twine("unknown opcode ").concat(BeginOpcodeName));
-      }
-      StringRef EndOpcodeName = OpcodeName.second;
-      unsigned EndOpcode = EndOpcodeName.empty()
-                               ? State.getInstrInfo().getNumOpcodes() - 1
-                               : ResolveName(EndOpcodeName);
-      if (EndOpcode == 0) {
-        ExitWithError(Twine("unknown opcode ").concat(EndOpcodeName));
-      }
-      for (unsigned I = BeginOpcode; I <= EndOpcode; ++I) {
-        if (!isIgnoredOpcode(State, I))
-          Result.push_back(I);
-      }
-    }
+  Result.reserve(Pieces.size());
+  for (const StringRef &OpcodeName : Pieces) {
+    if (unsigned Opcode = ResolveName(OpcodeName))
+      Result.push_back(Opcode);
+    else
+      ExitWithError(Twine("unknown opcode ").concat(OpcodeName));
   }
   return Result;
 }

>From c84e814ffb0d5d1d80718b200e5dfddc628ad906 Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Tue, 3 Dec 2024 19:26:21 +0300
Subject: [PATCH 32/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/lib/Target.h | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index c46eb3e1b8aaac..92cc1cb248a1c0 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -86,11 +86,6 @@ class ExegesisTarget {
                 ArrayRef<const char *> ValidationCounters,
                 const pid_t ProcessID = 0) const;
 
-  // Find register by name, NoRegister if not found.
-  virtual MCRegister findRegisterByName(const StringRef RegName) const {
-    return MCRegister::NoRegister;
-  }
-
   // Targets can use this to add target-specific passes in assembleToStream();
   virtual void addTargetSpecificPasses(PassManagerBase &PM) const {}
 

>From 2a8281752eb01d78c88d0890f2f1c0350669a6bf Mon Sep 17 00:00:00 2001
From: Anastasiya Chernikova <anastasiya.chernikova at syntacore.com>
Date: Sun, 15 Dec 2024 20:01:40 +0300
Subject: [PATCH 33/37] Addressing review comments

---
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index fe0b8a0bfda854..fa37e05956be8c 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -312,10 +312,6 @@ static const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,
   return nullptr;
 }
 
-static bool isIgnoredOpcode(const LLVMState &State, unsigned Opcode) {
-  return getIgnoredOpcodeReasonOrNull(State, Opcode) != nullptr;
-}
-
 // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided,
 // and returns the opcode indices or {} if snippets should be read from
 // `SnippetsFile`.

>From 3030011291f0eafc0ee2b6eb0f3c3301ce16041a Mon Sep 17 00:00:00 2001
From: Dmitry Bushev <dmitry.bushev at syntacore.com>
Date: Wed, 18 Dec 2024 15:46:50 +0300
Subject: [PATCH 34/37] append lit cofig for RISCV tests

---
 llvm/test/tools/llvm-exegesis/RISCV/lit.local.cfg | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 llvm/test/tools/llvm-exegesis/RISCV/lit.local.cfg

diff --git a/llvm/test/tools/llvm-exegesis/RISCV/lit.local.cfg b/llvm/test/tools/llvm-exegesis/RISCV/lit.local.cfg
new file mode 100644
index 00000000000000..466ccc26e78e1b
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/RISCV/lit.local.cfg
@@ -0,0 +1,3 @@
+if not ("RISCV" in config.root.targets):
+    # We need support for RISCV.
+    config.unsupported = True

>From 1dc0a79dcc5689e10fe6759424b3a59981e4e889 Mon Sep 17 00:00:00 2001
From: Dmitry Bushev <dmitry.bushev at syntacore.com>
Date: Wed, 18 Dec 2024 16:22:00 +0300
Subject: [PATCH 35/37] Fix [unused-private-field] error

---
 llvm/tools/llvm-exegesis/lib/SnippetFile.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index 282bc8ca912492..b37999ab017f59 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -37,10 +37,10 @@ namespace {
 // An MCStreamer that reads a BenchmarkCode definition from a file.
 class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
 public:
-  explicit BenchmarkCodeStreamer(const ExegesisTarget &Target,
-                                 MCContext *Context, const LLVMState &State,
+  explicit BenchmarkCodeStreamer(MCContext *Context, const LLVMState &State,
                                  BenchmarkCode *Result)
-      : MCStreamer(*Context), Target(Target), State(State), Result(Result) {}
+      : MCStreamer(*Context), State(State), Result(Result) {}
+
   // Implementation of the MCStreamer interface. We only care about
   // instructions.
   void emitInstruction(const MCInst &Instruction,
@@ -218,7 +218,6 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
     return *RegisterNumber;
   }
 
-  const ExegesisTarget &Target;
   const LLVMState &State;
   BenchmarkCode *const Result;
   unsigned InvalidComments = 0;
@@ -252,8 +251,7 @@ Expected<std::vector<BenchmarkCode>> readSnippets(const LLVMState &State,
       TM.getTarget().createMCObjectFileInfo(Context, /*PIC=*/false));
   Context.setObjectFileInfo(ObjectFileInfo.get());
   Context.initInlineSourceManager();
-  BenchmarkCodeStreamer Streamer(State.getExegesisTarget(), &Context, State,
-                                 &Result);
+  BenchmarkCodeStreamer Streamer(&Context, State, &Result);
 
   std::string Error;
   raw_string_ostream ErrorStream(Error);

>From 22754e3ec865b53bcb14de3afcaa54b7f5336dd1 Mon Sep 17 00:00:00 2001
From: Dmitry Bushev <dmitry.bushev at syntacore.com>
Date: Wed, 18 Dec 2024 16:27:48 +0300
Subject: [PATCH 36/37] Remove unsued variable

---
 llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 9573e2242ad3f7..25cdf1ce66d449 100644
--- a/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -53,7 +53,6 @@ computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
     if (OtherOpcode == Instr->Description.getOpcode())
       continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
-    const MCInstrDesc &OtherInstrDesc = OtherInstr.Description;
     if (OtherInstr.hasMemoryOperands())
       continue;
     if (!ET.allowAsBackToBack(OtherInstr))

>From 86f59cc5912e6431dcd693ce18c141f753189583 Mon Sep 17 00:00:00 2001
From: Dmitry Bushev <dmitry.bushev at syntacore.com>
Date: Wed, 18 Dec 2024 22:56:27 +0300
Subject: [PATCH 37/37] Remove no more used includes.

authored-by: Kazu Hirata <kazu at google.com>
---
 llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
index 891818b625fe14..41d361532908ca 100644
--- a/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/RISCV/Target.cpp
@@ -135,9 +135,6 @@ ExegesisRISCVTarget::ExegesisRISCVTarget()
     : ExegesisTarget(ArrayRef<CpuAndPfmCounters>{},
                      RISCV_MC::isOpcodeAvailable) {}
 
-#define GET_REGISTER_MATCHER
-#include "RISCVGenAsmMatcher.inc"
-
 bool ExegesisRISCVTarget::matchesArch(Triple::ArchType Arch) const {
   return Arch == Triple::riscv32 || Arch == Triple::riscv64;
 }



More information about the llvm-commits mailing list