[UpdateCCTestChecks] Detect function mangled name on separate line
[llvm-core.git] / tools / llvm-exegesis / lib / PerfHelper.cpp
blobe10b4e4a6803007abb621e6da4bd708b7aa40dc0
1 //===-- PerfHelper.cpp ------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "PerfHelper.h"
10 #include "llvm/Config/config.h"
11 #include "llvm/Support/raw_ostream.h"
12 #ifdef HAVE_LIBPFM
13 #include "perfmon/perf_event.h"
14 #include "perfmon/pfmlib.h"
15 #include "perfmon/pfmlib_perf_event.h"
16 #endif
17 #include <cassert>
19 namespace llvm {
20 namespace exegesis {
21 namespace pfm {
23 #ifdef HAVE_LIBPFM
24 static bool isPfmError(int Code) { return Code != PFM_SUCCESS; }
25 #endif
27 bool pfmInitialize() {
28 #ifdef HAVE_LIBPFM
29 return isPfmError(pfm_initialize());
30 #else
31 return true;
32 #endif
35 void pfmTerminate() {
36 #ifdef HAVE_LIBPFM
37 pfm_terminate();
38 #endif
41 PerfEvent::~PerfEvent() {
42 #ifdef HAVE_LIBPFM
43 delete Attr;
45 #endif
48 PerfEvent::PerfEvent(PerfEvent &&Other)
49 : EventString(std::move(Other.EventString)),
50 FullQualifiedEventString(std::move(Other.FullQualifiedEventString)),
51 Attr(Other.Attr) {
52 Other.Attr = nullptr;
55 PerfEvent::PerfEvent(llvm::StringRef PfmEventString)
56 : EventString(PfmEventString.str()), Attr(nullptr) {
57 #ifdef HAVE_LIBPFM
58 char *Fstr = nullptr;
59 pfm_perf_encode_arg_t Arg = {};
60 Attr = new perf_event_attr();
61 Arg.attr = Attr;
62 Arg.fstr = &Fstr;
63 Arg.size = sizeof(pfm_perf_encode_arg_t);
64 const int Result = pfm_get_os_event_encoding(EventString.c_str(), PFM_PLM3,
65 PFM_OS_PERF_EVENT, &Arg);
66 if (isPfmError(Result)) {
67 // We don't know beforehand which counters are available (e.g. 6 uops ports
68 // on Sandybridge but 8 on Haswell) so we report the missing counter without
69 // crashing.
70 llvm::errs() << pfm_strerror(Result) << " - cannot create event "
71 << EventString << "\n";
73 if (Fstr) {
74 FullQualifiedEventString = Fstr;
75 free(Fstr);
77 #endif
80 llvm::StringRef PerfEvent::name() const { return EventString; }
82 bool PerfEvent::valid() const { return !FullQualifiedEventString.empty(); }
84 const perf_event_attr *PerfEvent::attribute() const { return Attr; }
86 llvm::StringRef PerfEvent::getPfmEventString() const {
87 return FullQualifiedEventString;
90 #ifdef HAVE_LIBPFM
91 Counter::Counter(const PerfEvent &Event) {
92 assert(Event.valid());
93 const pid_t Pid = 0; // measure current process/thread.
94 const int Cpu = -1; // measure any processor.
95 const int GroupFd = -1; // no grouping of counters.
96 const uint32_t Flags = 0;
97 perf_event_attr AttrCopy = *Event.attribute();
98 FileDescriptor = perf_event_open(&AttrCopy, Pid, Cpu, GroupFd, Flags);
99 if (FileDescriptor == -1) {
100 llvm::errs() << "Unable to open event, make sure your kernel allows user "
101 "space perf monitoring.\nYou may want to try:\n$ sudo sh "
102 "-c 'echo -1 > /proc/sys/kernel/perf_event_paranoid'\n";
104 assert(FileDescriptor != -1 && "Unable to open event");
107 Counter::~Counter() { close(FileDescriptor); }
109 void Counter::start() { ioctl(FileDescriptor, PERF_EVENT_IOC_RESET, 0); }
111 void Counter::stop() { ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0); }
113 int64_t Counter::read() const {
114 int64_t Count = 0;
115 ssize_t ReadSize = ::read(FileDescriptor, &Count, sizeof(Count));
116 if (ReadSize != sizeof(Count)) {
117 Count = -1;
118 llvm::errs() << "Failed to read event counter\n";
120 return Count;
123 #else
125 Counter::Counter(const PerfEvent &Event) {}
127 Counter::~Counter() = default;
129 void Counter::start() {}
131 void Counter::stop() {}
133 int64_t Counter::read() const { return 42; }
135 #endif
137 } // namespace pfm
138 } // namespace exegesis
139 } // namespace llvm