[llvm] [Exegesis][RISCV] Add RISCV support for llvm-exegesis (PR #89047)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 11 07:06:43 PDT 2024


================
@@ -0,0 +1,100 @@
+//===-- 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_lo, cycles_hi0, cycles_hi1;
+  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"
+               "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("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);
----------------
dtcxzyw wrote:

> This is not going to be available in the future. Access to rdcycle, and allowing the kernel to configure userspace access, is deprecated, and will be removed.

Emm, we have to use libpfm to access cycle :(

See https://docs.kernel.org/admin-guide/sysctl/kernel.html#perf-user-access-arm64-and-riscv-only.

> When set to 0, user space access is disabled.
> The default value is 1, user space can read performance monitor counter registers through perf, any direct access without perf intervention will trigger an illegal instruction.
> When set to 2, which enables legacy mode (user space has direct access to cycle and insret CSRs only). Note that this legacy value is deprecated and will be removed once all user space applications are fixed.
> Note that the time CSR is always directly accessible to all modes.

> Try something with rdtime instead of rdcycle

The result may be affected by dynamic frequency scaling.


https://github.com/llvm/llvm-project/pull/89047


More information about the llvm-commits mailing list