[llvm-branch-commits] [libcxx] [libc++] Implements filebuf unbuffered. (PR #76629)

2023-12-30 Thread Mark de Wever via llvm-branch-commits

https://github.com/mordante created 
https://github.com/llvm/llvm-project/pull/76629

When calling setbuf(nullptr, 0) before performing file operations it should set 
the file to unbuffered mode. Currently the code avoids buffering internally, 
but the underlying stream still can buffer.

This is addressed by disabling the buffering of the underlying stream.

Fixes: https://github.com/llvm/llvm-project/issues/60509

>From a68f28e4b5e2ef7c2df9ce286a747931bbf0dfe7 Mon Sep 17 00:00:00 2001
From: Mark de Wever 
Date: Sat, 30 Dec 2023 20:33:25 +0100
Subject: [PATCH] [libc++] Implements filebuf unbuffered.

When calling setbuf(nullptr, 0) before performing file operations it
should set the file to unbuffered mode. Currently the code avoids
buffering internally, but the underlying stream still can buffer.

This is addressed by disabling the buffering of the underlying stream.

Fixes: https://github.com/llvm/llvm-project/issues/60509
---
 libcxx/include/fstream|  47 ++-
 .../fstreams/filebuf.virtuals/setbuf.pass.cpp | 118 ++
 2 files changed, 164 insertions(+), 1 deletion(-)
 create mode 100644 
libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp

diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 21fee202873e76..8a2df123486556 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -276,6 +276,30 @@ private:
   state_type __st_;
   state_type __st_last_;
   ios_base::openmode __om_;
+  // Used to track the currently used mode and track whether the output should
+  // be unbuffered.
+  // [filebuf.virtuals]/12
+  //   If setbuf(0, 0) is called on a stream before any I/O has occurred on
+  //   that stream, the stream becomes unbuffered. Otherwise the results are
+  //   implementation-defined.
+  // This allows calling setbuf(0, 0)
+  // - before opening a file,
+  // - after opening a file, before
+  //   - a read
+  //   - a write
+  //   - a seek.
+  // Note that opening a file with ios_base::ate does a seek operation.
+  // Normally underflow, overflow, and sync change this flag to
+  // ios_base::in, ios_base_out, or 0.
+  //
+  // The ios_base::trunc and ios_base::ate flags are used in the following way:
+  // - ios_base::trunc is set upon construction to indicate the unbuffered
+  //   state can be set. When requesting unbuffered output and the file is open
+  //   sets the mode. Else places a request by adding the ios_base::ate flag.
+  // - When a file is opened it checks whether both ios_base::trunc and
+  //   ios_base::ate are set. If so switches to unbuffered mode.
+  // - Using ase::ate in the open mode sets the flag to 0 so future calls to
+  //   setbuf no longer try to set the unbuffered mode.
   ios_base::openmode __cm_;
   bool __owns_eb_;
   bool __owns_ib_;
@@ -294,7 +318,10 @@ private:
   return nullptr;
 
 __om_ = __mode;
+   __try_set_unbuffered_mode();
+
 if (__mode & ios_base::ate) {
+  __cm_ = 0;
   if (fseek(__file_, 0, SEEK_END)) {
 fclose(__file_);
 __file_ = nullptr;
@@ -304,6 +331,23 @@ private:
 
 return this;
   }
+
+  _LIBCPP_HIDE_FROM_ABI void __try_set_unbuffered_mode() {
+if (__cm_ == (ios_base::trunc | ios_base::ate)) {
+  std::setbuf(__file_, nullptr);
+  __cm_ = 0;
+}
+  }
+  _LIBCPP_HIDE_FROM_ABI void __try_set_unbuffered_mode(char_type* __s, 
streamsize __n) {
+if (__cm_ == ios_base::trunc && __s == nullptr && __n == 0) {
+  if (__file_) {
+std::setbuf(__file_, nullptr);
+__cm_ = 0;
+  } else {
+__cm_ = ios_base::trunc | ios_base::ate;
+  }
+}
+  }
 };
 
 template 
@@ -319,7 +363,7 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf()
   __st_(),
   __st_last_(),
   __om_(0),
-  __cm_(0),
+  __cm_(ios_base::trunc),
   __owns_eb_(false),
   __owns_ib_(false),
   __always_noconv_(false) {
@@ -780,6 +824,7 @@ template 
 basic_streambuf<_CharT, _Traits>* basic_filebuf<_CharT, 
_Traits>::setbuf(char_type* __s, streamsize __n) {
   this->setg(nullptr, nullptr, nullptr);
   this->setp(nullptr, nullptr);
+  __try_set_unbuffered_mode(__s, __n);
   if (__owns_eb_)
 delete[] __extbuf_;
   if (__owns_ib_)
diff --git 
a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp
 
b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp
new file mode 100644
index 00..3f561170f5fb24
--- /dev/null
+++ 
b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp
@@ -0,0 +1,118 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+// 
+
+/

[llvm-branch-commits] [libcxx] [libc++] Implements filebuf unbuffered. (PR #76629)

2023-12-30 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)


Changes

When calling setbuf(nullptr, 0) before performing file operations it should set 
the file to unbuffered mode. Currently the code avoids buffering internally, 
but the underlying stream still can buffer.

This is addressed by disabling the buffering of the underlying stream.

Fixes: https://github.com/llvm/llvm-project/issues/60509

---
Full diff: https://github.com/llvm/llvm-project/pull/76629.diff


2 Files Affected:

- (modified) libcxx/include/fstream (+46-1) 
- (added) 
libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp
 (+118) 


``diff
diff --git a/libcxx/include/fstream b/libcxx/include/fstream
index 21fee202873e76..8a2df123486556 100644
--- a/libcxx/include/fstream
+++ b/libcxx/include/fstream
@@ -276,6 +276,30 @@ private:
   state_type __st_;
   state_type __st_last_;
   ios_base::openmode __om_;
+  // Used to track the currently used mode and track whether the output should
+  // be unbuffered.
+  // [filebuf.virtuals]/12
+  //   If setbuf(0, 0) is called on a stream before any I/O has occurred on
+  //   that stream, the stream becomes unbuffered. Otherwise the results are
+  //   implementation-defined.
+  // This allows calling setbuf(0, 0)
+  // - before opening a file,
+  // - after opening a file, before
+  //   - a read
+  //   - a write
+  //   - a seek.
+  // Note that opening a file with ios_base::ate does a seek operation.
+  // Normally underflow, overflow, and sync change this flag to
+  // ios_base::in, ios_base_out, or 0.
+  //
+  // The ios_base::trunc and ios_base::ate flags are used in the following way:
+  // - ios_base::trunc is set upon construction to indicate the unbuffered
+  //   state can be set. When requesting unbuffered output and the file is open
+  //   sets the mode. Else places a request by adding the ios_base::ate flag.
+  // - When a file is opened it checks whether both ios_base::trunc and
+  //   ios_base::ate are set. If so switches to unbuffered mode.
+  // - Using ase::ate in the open mode sets the flag to 0 so future calls to
+  //   setbuf no longer try to set the unbuffered mode.
   ios_base::openmode __cm_;
   bool __owns_eb_;
   bool __owns_ib_;
@@ -294,7 +318,10 @@ private:
   return nullptr;
 
 __om_ = __mode;
+   __try_set_unbuffered_mode();
+
 if (__mode & ios_base::ate) {
+  __cm_ = 0;
   if (fseek(__file_, 0, SEEK_END)) {
 fclose(__file_);
 __file_ = nullptr;
@@ -304,6 +331,23 @@ private:
 
 return this;
   }
+
+  _LIBCPP_HIDE_FROM_ABI void __try_set_unbuffered_mode() {
+if (__cm_ == (ios_base::trunc | ios_base::ate)) {
+  std::setbuf(__file_, nullptr);
+  __cm_ = 0;
+}
+  }
+  _LIBCPP_HIDE_FROM_ABI void __try_set_unbuffered_mode(char_type* __s, 
streamsize __n) {
+if (__cm_ == ios_base::trunc && __s == nullptr && __n == 0) {
+  if (__file_) {
+std::setbuf(__file_, nullptr);
+__cm_ = 0;
+  } else {
+__cm_ = ios_base::trunc | ios_base::ate;
+  }
+}
+  }
 };
 
 template 
@@ -319,7 +363,7 @@ basic_filebuf<_CharT, _Traits>::basic_filebuf()
   __st_(),
   __st_last_(),
   __om_(0),
-  __cm_(0),
+  __cm_(ios_base::trunc),
   __owns_eb_(false),
   __owns_ib_(false),
   __always_noconv_(false) {
@@ -780,6 +824,7 @@ template 
 basic_streambuf<_CharT, _Traits>* basic_filebuf<_CharT, 
_Traits>::setbuf(char_type* __s, streamsize __n) {
   this->setg(nullptr, nullptr, nullptr);
   this->setp(nullptr, nullptr);
+  __try_set_unbuffered_mode(__s, __n);
   if (__owns_eb_)
 delete[] __extbuf_;
   if (__owns_ib_)
diff --git 
a/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp
 
b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp
new file mode 100644
index 00..3f561170f5fb24
--- /dev/null
+++ 
b/libcxx/test/std/input.output/file.streams/fstreams/filebuf.virtuals/setbuf.pass.cpp
@@ -0,0 +1,118 @@
+//===--===//
+//
+// 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
+//
+//===--===//
+
+// 
+
+// basic_streambuf* setbuf(char_type* s, streamsize n) override;
+
+#include 
+#include 
+
+#include "test_macros.h"
+
+template 
+static std::size_t file_size(const char* filename) {
+  FILE* f = std::fopen(filename, "rb");
+  fseek(f, 0, SEEK_END);
+  long result = ftell(f);
+  fclose(f);
+  return result;
+}
+
+template 
+struct filebuf : public std::basic_filebuf {
+  CharT* base() { return this->pbase(); }
+  CharT* ptr() { return this->pptr(); }
+};
+
+template 
+static void buffered_request() {
+  filebuf buffer;
+
+  CharT b[10] = {0};
+  a

[llvm-branch-commits] [libcxx] [libc++] Implements filebuf unbuffered. (PR #76629)

2023-12-30 Thread Mark de Wever via llvm-branch-commits


@@ -276,6 +276,30 @@ private:
   state_type __st_;
   state_type __st_last_;
   ios_base::openmode __om_;
+  // Used to track the currently used mode and track whether the output should

mordante wrote:

Review note: It might be possible to use other fields to achieve the same goal. 
Unfortunately there's no implementation documentation for this class. This 
changes seems the simplest and the easiest to validate. 

https://github.com/llvm/llvm-project/pull/76629
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [llvm-exegesis] Add tablegen support for validation counters (PR #76652)

2023-12-30 Thread Aiden Grossman via llvm-branch-commits

https://github.com/boomanaiden154 created 
https://github.com/llvm/llvm-project/pull/76652

This patch adds support in the llvm-exegesis tablegen emitter for validation 
counters. Full support for validation counters in llvm-exegesis is added in a 
future patch.

>From 75261b9626878b92fa4bde2b4801815251238748 Mon Sep 17 00:00:00 2001
From: Aiden Grossman 
Date: Sat, 30 Dec 2023 17:03:59 -0800
Subject: [PATCH] [llvm-exegesis] Add tablegen support for validation counters

---
 llvm/include/llvm/Target/TargetPfmCounters.td | 19 +
 llvm/lib/Target/X86/X86PfmCounters.td |  6 
 llvm/tools/llvm-exegesis/lib/Target.cpp   | 13 +
 llvm/tools/llvm-exegesis/lib/Target.h | 11 
 llvm/utils/TableGen/ExegesisEmitter.cpp   | 28 +--
 5 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/Target/TargetPfmCounters.td 
b/llvm/include/llvm/Target/TargetPfmCounters.td
index b00f3e19c35f90..72f6b39f4878f4 100644
--- a/llvm/include/llvm/Target/TargetPfmCounters.td
+++ b/llvm/include/llvm/Target/TargetPfmCounters.td
@@ -28,6 +28,22 @@ class PfmIssueCounter
   string ResourceName = resource_name;
 }
 
+class ValidationEvent  {
+  int EventNumber = event_number;
+}
+
+def L1DCacheLoadMiss: ValidationEvent<0>;
+def InstructionRetired  : ValidationEvent<1>;
+def DataTLBLoadMiss : ValidationEvent<2>;
+def DataTLBStoreMiss: ValidationEvent<3>;
+
+// Validation counters can be tied to a specific event
+class PfmValidationCounter
+: PfmCounter {
+  // The name of the event that the validation counter detects.
+  ValidationEvent EventType = event_type;
+}
+
 def NoPfmCounter : PfmCounter <""> {}
 
 // Set of PfmCounters for measuring sched model characteristics.
@@ -38,6 +54,9 @@ class ProcPfmCounters {
   PfmCounter UopsCounter = NoPfmCounter;
   // Processors can define how to measure issued uops by defining 
IssueCounters.
   list IssueCounters = [];
+  // Processor can list mappings between validation events and real counters
+  // to measure the specified events.
+  list ValidationCounters = [];
 }
 
 // A binding of a set of counters to a CPU.
diff --git a/llvm/lib/Target/X86/X86PfmCounters.td 
b/llvm/lib/Target/X86/X86PfmCounters.td
index 49ef6efc6aecf2..99cac504f157d3 100644
--- a/llvm/lib/Target/X86/X86PfmCounters.td
+++ b/llvm/lib/Target/X86/X86PfmCounters.td
@@ -275,6 +275,9 @@ def ZnVer2PfmCounters : ProcPfmCounters {
 PfmIssueCounter<"Zn2AGU", "ls_dispatch:ld_st_dispatch + 
ls_dispatch:ld_dispatch + ls_dispatch:store_dispatch">,
 PfmIssueCounter<"Zn2Divider", "div_op_count">
   ];
+  let ValidationCounters = [
+PfmValidationCounter
+  ];
 }
 def : PfmCountersBinding<"znver2", ZnVer2PfmCounters>;
 
@@ -288,6 +291,9 @@ def ZnVer3PfmCounters : ProcPfmCounters {
 PfmIssueCounter<"Zn3Store", "ls_dispatch:store_dispatch">,
 PfmIssueCounter<"Zn3Divider", "div_op_count">
   ];
+  let ValidationCounters = [
+PfmValidationCounter
+  ];
 }
 def : PfmCountersBinding<"znver3", ZnVer3PfmCounters>;
 
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp 
b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 23c80e5b98953a..20b4afb9b8f676 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -147,13 +147,14 @@ std::unique_ptr 
ExegesisTarget::createUopsBenchmarkRunner(
ExecutionMode);
 }
 
-static_assert(std::is_trivial_v,
-  "We shouldn't have dynamic initialization here");
-const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
-  0u};
+const PfmCountersInfo PfmCountersInfo::Default = {
+nullptr, nullptr, nullptr, 0u, {}};
 const PfmCountersInfo PfmCountersInfo::Dummy = {
-pfm::PerfEvent::DummyEventString, pfm::PerfEvent::DummyEventString, 
nullptr,
-0u};
+pfm::PerfEvent::DummyEventString,
+pfm::PerfEvent::DummyEventString,
+nullptr,
+0u,
+{}};
 
 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const 
{
   assert(llvm::is_sorted(
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h 
b/llvm/tools/llvm-exegesis/lib/Target.h
index c37dd8b7082162..3956bc983181f6 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -32,6 +32,8 @@
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 
+#include 
+
 namespace llvm {
 namespace exegesis {
 
@@ -39,6 +41,13 @@ extern cl::OptionCategory Options;
 extern cl::OptionCategory BenchmarkOptions;
 extern cl::OptionCategory AnalysisOptions;
 
+enum ValidationEvent {
+  L1DCacheLoadMiss,
+  InstructionRetired,
+  DataTLBLoadMiss,
+  DataTLBStoreMiss
+};
+
 struct PfmCountersInfo {
   // An optional name of a performance counter that can be used to measure
   // cycles.
@@ -59,6 +68,8 @@ struct PfmCountersInfo {
   const IssueCounter *IssueCounters;
   unsigned NumIssueCoun

[llvm-branch-commits] [llvm] [llvm-exegesis] Add tablegen support for validation counters (PR #76652)

2023-12-30 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-backend-x86

Author: Aiden Grossman (boomanaiden154)


Changes

This patch adds support in the llvm-exegesis tablegen emitter for validation 
counters. Full support for validation counters in llvm-exegesis is added in a 
future patch.

---
Full diff: https://github.com/llvm/llvm-project/pull/76652.diff


5 Files Affected:

- (modified) llvm/include/llvm/Target/TargetPfmCounters.td (+19) 
- (modified) llvm/lib/Target/X86/X86PfmCounters.td (+6) 
- (modified) llvm/tools/llvm-exegesis/lib/Target.cpp (+7-6) 
- (modified) llvm/tools/llvm-exegesis/lib/Target.h (+11) 
- (modified) llvm/utils/TableGen/ExegesisEmitter.cpp (+26-2) 


``diff
diff --git a/llvm/include/llvm/Target/TargetPfmCounters.td 
b/llvm/include/llvm/Target/TargetPfmCounters.td
index b00f3e19c35f90..72f6b39f4878f4 100644
--- a/llvm/include/llvm/Target/TargetPfmCounters.td
+++ b/llvm/include/llvm/Target/TargetPfmCounters.td
@@ -28,6 +28,22 @@ class PfmIssueCounter
   string ResourceName = resource_name;
 }
 
+class ValidationEvent  {
+  int EventNumber = event_number;
+}
+
+def L1DCacheLoadMiss: ValidationEvent<0>;
+def InstructionRetired  : ValidationEvent<1>;
+def DataTLBLoadMiss : ValidationEvent<2>;
+def DataTLBStoreMiss: ValidationEvent<3>;
+
+// Validation counters can be tied to a specific event
+class PfmValidationCounter
+: PfmCounter {
+  // The name of the event that the validation counter detects.
+  ValidationEvent EventType = event_type;
+}
+
 def NoPfmCounter : PfmCounter <""> {}
 
 // Set of PfmCounters for measuring sched model characteristics.
@@ -38,6 +54,9 @@ class ProcPfmCounters {
   PfmCounter UopsCounter = NoPfmCounter;
   // Processors can define how to measure issued uops by defining 
IssueCounters.
   list IssueCounters = [];
+  // Processor can list mappings between validation events and real counters
+  // to measure the specified events.
+  list ValidationCounters = [];
 }
 
 // A binding of a set of counters to a CPU.
diff --git a/llvm/lib/Target/X86/X86PfmCounters.td 
b/llvm/lib/Target/X86/X86PfmCounters.td
index 49ef6efc6aecf2..99cac504f157d3 100644
--- a/llvm/lib/Target/X86/X86PfmCounters.td
+++ b/llvm/lib/Target/X86/X86PfmCounters.td
@@ -275,6 +275,9 @@ def ZnVer2PfmCounters : ProcPfmCounters {
 PfmIssueCounter<"Zn2AGU", "ls_dispatch:ld_st_dispatch + 
ls_dispatch:ld_dispatch + ls_dispatch:store_dispatch">,
 PfmIssueCounter<"Zn2Divider", "div_op_count">
   ];
+  let ValidationCounters = [
+PfmValidationCounter
+  ];
 }
 def : PfmCountersBinding<"znver2", ZnVer2PfmCounters>;
 
@@ -288,6 +291,9 @@ def ZnVer3PfmCounters : ProcPfmCounters {
 PfmIssueCounter<"Zn3Store", "ls_dispatch:store_dispatch">,
 PfmIssueCounter<"Zn3Divider", "div_op_count">
   ];
+  let ValidationCounters = [
+PfmValidationCounter
+  ];
 }
 def : PfmCountersBinding<"znver3", ZnVer3PfmCounters>;
 
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp 
b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 23c80e5b98953a..20b4afb9b8f676 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -147,13 +147,14 @@ std::unique_ptr 
ExegesisTarget::createUopsBenchmarkRunner(
ExecutionMode);
 }
 
-static_assert(std::is_trivial_v,
-  "We shouldn't have dynamic initialization here");
-const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
-  0u};
+const PfmCountersInfo PfmCountersInfo::Default = {
+nullptr, nullptr, nullptr, 0u, {}};
 const PfmCountersInfo PfmCountersInfo::Dummy = {
-pfm::PerfEvent::DummyEventString, pfm::PerfEvent::DummyEventString, 
nullptr,
-0u};
+pfm::PerfEvent::DummyEventString,
+pfm::PerfEvent::DummyEventString,
+nullptr,
+0u,
+{}};
 
 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const 
{
   assert(llvm::is_sorted(
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h 
b/llvm/tools/llvm-exegesis/lib/Target.h
index c37dd8b7082162..3956bc983181f6 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -32,6 +32,8 @@
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 
+#include 
+
 namespace llvm {
 namespace exegesis {
 
@@ -39,6 +41,13 @@ extern cl::OptionCategory Options;
 extern cl::OptionCategory BenchmarkOptions;
 extern cl::OptionCategory AnalysisOptions;
 
+enum ValidationEvent {
+  L1DCacheLoadMiss,
+  InstructionRetired,
+  DataTLBLoadMiss,
+  DataTLBStoreMiss
+};
+
 struct PfmCountersInfo {
   // An optional name of a performance counter that can be used to measure
   // cycles.
@@ -59,6 +68,8 @@ struct PfmCountersInfo {
   const IssueCounter *IssueCounters;
   unsigned NumIssueCounters;
 
+  std::unordered_map ValidationCounters;
+
   static const PfmCountersInfo Default;
   static const PfmCountersInfo Dummy;
 };
diff --git a/llvm/utils/Tab

[llvm-branch-commits] [llvm] [llvm-exegesis] Add support for validation counters (PR #76653)

2023-12-30 Thread Aiden Grossman via llvm-branch-commits

https://github.com/boomanaiden154 created 
https://github.com/llvm/llvm-project/pull/76653

This patch adds support for validation counters. Validation counters can be 
used to measure events that occur during snippet execution like cache misses to 
ensure that certain assumed invariants about the benchmark actually hold. 
Validation counters are setup within a perf event group, so are turned on and 
off at exactly the same time as the "group leader" counter that measures the 
desired value.

>From 76f199f4fc7244c3d972736595c685d7316c5203 Mon Sep 17 00:00:00 2001
From: Aiden Grossman 
Date: Sat, 30 Dec 2023 18:18:12 -0800
Subject: [PATCH] [llvm-exegesis] Add support for validation counters

This patch adds support for validation counters. Validation counters can
be used to measure events that occur during snippet execution like cache
misses to ensure that certain assumed invariants about the benchmark
actually hold. Validation counters are setup within a perf event group,
so are turned on and off at exactly the same time as the "group leader"
counter that measures the desired value.
---
 .../llvm-exegesis/lib/BenchmarkResult.cpp | 52 +++
 .../tools/llvm-exegesis/lib/BenchmarkResult.h | 15 +-
 .../llvm-exegesis/lib/BenchmarkRunner.cpp | 52 +--
 .../tools/llvm-exegesis/lib/BenchmarkRunner.h |  8 ++-
 .../lib/LatencyBenchmarkRunner.cpp| 46 
 .../lib/LatencyBenchmarkRunner.h  |  3 ++
 llvm/tools/llvm-exegesis/lib/PerfHelper.cpp   | 37 +++--
 llvm/tools/llvm-exegesis/lib/PerfHelper.h | 10 +++-
 llvm/tools/llvm-exegesis/lib/Target.cpp   | 35 +
 llvm/tools/llvm-exegesis/lib/Target.h | 13 ++---
 .../llvm-exegesis/lib/UopsBenchmarkRunner.cpp | 37 ++---
 .../llvm-exegesis/lib/UopsBenchmarkRunner.h   |  9 +++-
 llvm/tools/llvm-exegesis/lib/X86/Target.cpp   | 11 +++-
 .../llvm-exegesis/lib/X86/X86Counter.cpp  |  2 +-
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp| 18 ++-
 .../tools/llvm-exegesis/ClusteringTest.cpp| 36 ++---
 .../Mips/BenchmarkResultTest.cpp  | 12 ++---
 .../llvm-exegesis/X86/BenchmarkResultTest.cpp | 12 ++---
 18 files changed, 311 insertions(+), 97 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp 
b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
index 02c4da11e032d6..1079df24b457b8 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -192,6 +193,56 @@ template <> struct 
SequenceElementTraits {
   static const bool flow = false;
 };
 
+const char *validationEventToString(exegesis::ValidationEvent VE) {
+  switch (VE) {
+  case exegesis::ValidationEvent::L1DCacheLoadMiss:
+return "l1d-load-miss";
+  case exegesis::ValidationEvent::InstructionRetired:
+return "instructions-retired";
+  case exegesis::ValidationEvent::DataTLBLoadMiss:
+return "data-tlb-load-misses";
+  case exegesis::ValidationEvent::DataTLBStoreMiss:
+return "data-tlb-store-misses";
+  }
+}
+
+Expected stringToValidationEvent(StringRef Input) {
+  if (Input == "l1d-load-miss")
+return exegesis::ValidationEvent::L1DCacheLoadMiss;
+  else if (Input == "instructions-retired")
+return exegesis::ValidationEvent::InstructionRetired;
+  else if (Input == "data-tlb-load-misses")
+return exegesis::ValidationEvent::DataTLBLoadMiss;
+  else if (Input == "data-tlb-store-misses")
+return exegesis::ValidationEvent::DataTLBStoreMiss;
+  else
+return make_error("Invalid validation event string",
+   errc::invalid_argument);
+}
+
+template <>
+struct CustomMappingTraits<
+std::unordered_map> {
+  static void
+  inputOne(IO &Io, StringRef KeyStr,
+   std::unordered_map &VI) {
+Expected Key = stringToValidationEvent(KeyStr);
+if (!Key) {
+  Io.setError("Key is not a valid validation event");
+  return;
+}
+Io.mapRequired(KeyStr.str().c_str(), VI[*Key]);
+  }
+
+  static void
+  output(IO &Io, std::unordered_map &VI) {
+for (auto &IndividualVI : VI) {
+  Io.mapRequired(validationEventToString(IndividualVI.first),
+ IndividualVI.second);
+}
+  }
+};
+
 // exegesis::Measure is rendererd as a flow instead of a list.
 // e.g. { "key": "the key", "value": 0123 }
 template <> struct MappingTraits {
@@ -203,6 +254,7 @@ template <> struct 
MappingTraits {
 }
 Io.mapRequired("value", Obj.PerInstructionValue);
 Io.mapOptional("per_snippet_value", Obj.PerSnippetValue);
+Io.mapOptional("validation_counters", Obj.ValidationCounters);
   }
   static const bool flow = true;
 };
diff --git a/llvm/tools/llvm-exege

[llvm-branch-commits] [llvm] [llvm-exegesis] Add support for validation counters (PR #76653)

2023-12-30 Thread via llvm-branch-commits

llvmbot wrote:




@llvm/pr-subscribers-tools-llvm-exegesis

Author: Aiden Grossman (boomanaiden154)


Changes

This patch adds support for validation counters. Validation counters can be 
used to measure events that occur during snippet execution like cache misses to 
ensure that certain assumed invariants about the benchmark actually hold. 
Validation counters are setup within a perf event group, so are turned on and 
off at exactly the same time as the "group leader" counter that measures the 
desired value.

---

Patch is 40.60 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/76653.diff


18 Files Affected:

- (modified) llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp (+52) 
- (modified) llvm/tools/llvm-exegesis/lib/BenchmarkResult.h (+13-2) 
- (modified) llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp (+37-15) 
- (modified) llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h (+6-2) 
- (modified) llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp (+35-11) 
- (modified) llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h (+3) 
- (modified) llvm/tools/llvm-exegesis/lib/PerfHelper.cpp (+34-3) 
- (modified) llvm/tools/llvm-exegesis/lib/PerfHelper.h (+8-2) 
- (modified) llvm/tools/llvm-exegesis/lib/Target.cpp (+25-10) 
- (modified) llvm/tools/llvm-exegesis/lib/Target.h (+5-8) 
- (modified) llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.cpp (+31-6) 
- (modified) llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h (+7-2) 
- (modified) llvm/tools/llvm-exegesis/lib/X86/Target.cpp (+10-1) 
- (modified) llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp (+1-1) 
- (modified) llvm/tools/llvm-exegesis/llvm-exegesis.cpp (+17-1) 
- (modified) llvm/unittests/tools/llvm-exegesis/ClusteringTest.cpp (+15-21) 
- (modified) llvm/unittests/tools/llvm-exegesis/Mips/BenchmarkResultTest.cpp 
(+6-6) 
- (modified) llvm/unittests/tools/llvm-exegesis/X86/BenchmarkResultTest.cpp 
(+6-6) 


``diff
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp 
b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
index 02c4da11e032d6..1079df24b457b8 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -192,6 +193,56 @@ template <> struct 
SequenceElementTraits {
   static const bool flow = false;
 };
 
+const char *validationEventToString(exegesis::ValidationEvent VE) {
+  switch (VE) {
+  case exegesis::ValidationEvent::L1DCacheLoadMiss:
+return "l1d-load-miss";
+  case exegesis::ValidationEvent::InstructionRetired:
+return "instructions-retired";
+  case exegesis::ValidationEvent::DataTLBLoadMiss:
+return "data-tlb-load-misses";
+  case exegesis::ValidationEvent::DataTLBStoreMiss:
+return "data-tlb-store-misses";
+  }
+}
+
+Expected stringToValidationEvent(StringRef Input) {
+  if (Input == "l1d-load-miss")
+return exegesis::ValidationEvent::L1DCacheLoadMiss;
+  else if (Input == "instructions-retired")
+return exegesis::ValidationEvent::InstructionRetired;
+  else if (Input == "data-tlb-load-misses")
+return exegesis::ValidationEvent::DataTLBLoadMiss;
+  else if (Input == "data-tlb-store-misses")
+return exegesis::ValidationEvent::DataTLBStoreMiss;
+  else
+return make_error("Invalid validation event string",
+   errc::invalid_argument);
+}
+
+template <>
+struct CustomMappingTraits<
+std::unordered_map> {
+  static void
+  inputOne(IO &Io, StringRef KeyStr,
+   std::unordered_map &VI) {
+Expected Key = stringToValidationEvent(KeyStr);
+if (!Key) {
+  Io.setError("Key is not a valid validation event");
+  return;
+}
+Io.mapRequired(KeyStr.str().c_str(), VI[*Key]);
+  }
+
+  static void
+  output(IO &Io, std::unordered_map &VI) {
+for (auto &IndividualVI : VI) {
+  Io.mapRequired(validationEventToString(IndividualVI.first),
+ IndividualVI.second);
+}
+  }
+};
+
 // exegesis::Measure is rendererd as a flow instead of a list.
 // e.g. { "key": "the key", "value": 0123 }
 template <> struct MappingTraits {
@@ -203,6 +254,7 @@ template <> struct 
MappingTraits {
 }
 Io.mapRequired("value", Obj.PerInstructionValue);
 Io.mapOptional("per_snippet_value", Obj.PerSnippetValue);
+Io.mapOptional("validation_counters", Obj.ValidationCounters);
   }
   static const bool flow = true;
 };
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h 
b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index 0d08febae20cb3..f142da07e0a47d 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -32,6 +32,13 @@ class Error;
 
 namespace exegesis {
 
+enum ValidationEvent {
+ 

[llvm-branch-commits] [llvm] [llvm-exegesis] Add support for validation counters (PR #76653)

2023-12-30 Thread Aiden Grossman via llvm-branch-commits

https://github.com/boomanaiden154 updated 
https://github.com/llvm/llvm-project/pull/76653

>From 76f199f4fc7244c3d972736595c685d7316c5203 Mon Sep 17 00:00:00 2001
From: Aiden Grossman 
Date: Sat, 30 Dec 2023 18:18:12 -0800
Subject: [PATCH 1/2] [llvm-exegesis] Add support for validation counters

This patch adds support for validation counters. Validation counters can
be used to measure events that occur during snippet execution like cache
misses to ensure that certain assumed invariants about the benchmark
actually hold. Validation counters are setup within a perf event group,
so are turned on and off at exactly the same time as the "group leader"
counter that measures the desired value.
---
 .../llvm-exegesis/lib/BenchmarkResult.cpp | 52 +++
 .../tools/llvm-exegesis/lib/BenchmarkResult.h | 15 +-
 .../llvm-exegesis/lib/BenchmarkRunner.cpp | 52 +--
 .../tools/llvm-exegesis/lib/BenchmarkRunner.h |  8 ++-
 .../lib/LatencyBenchmarkRunner.cpp| 46 
 .../lib/LatencyBenchmarkRunner.h  |  3 ++
 llvm/tools/llvm-exegesis/lib/PerfHelper.cpp   | 37 +++--
 llvm/tools/llvm-exegesis/lib/PerfHelper.h | 10 +++-
 llvm/tools/llvm-exegesis/lib/Target.cpp   | 35 +
 llvm/tools/llvm-exegesis/lib/Target.h | 13 ++---
 .../llvm-exegesis/lib/UopsBenchmarkRunner.cpp | 37 ++---
 .../llvm-exegesis/lib/UopsBenchmarkRunner.h   |  9 +++-
 llvm/tools/llvm-exegesis/lib/X86/Target.cpp   | 11 +++-
 .../llvm-exegesis/lib/X86/X86Counter.cpp  |  2 +-
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp| 18 ++-
 .../tools/llvm-exegesis/ClusteringTest.cpp| 36 ++---
 .../Mips/BenchmarkResultTest.cpp  | 12 ++---
 .../llvm-exegesis/X86/BenchmarkResultTest.cpp | 12 ++---
 18 files changed, 311 insertions(+), 97 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp 
b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
index 02c4da11e032d6..1079df24b457b8 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -192,6 +193,56 @@ template <> struct 
SequenceElementTraits {
   static const bool flow = false;
 };
 
+const char *validationEventToString(exegesis::ValidationEvent VE) {
+  switch (VE) {
+  case exegesis::ValidationEvent::L1DCacheLoadMiss:
+return "l1d-load-miss";
+  case exegesis::ValidationEvent::InstructionRetired:
+return "instructions-retired";
+  case exegesis::ValidationEvent::DataTLBLoadMiss:
+return "data-tlb-load-misses";
+  case exegesis::ValidationEvent::DataTLBStoreMiss:
+return "data-tlb-store-misses";
+  }
+}
+
+Expected stringToValidationEvent(StringRef Input) {
+  if (Input == "l1d-load-miss")
+return exegesis::ValidationEvent::L1DCacheLoadMiss;
+  else if (Input == "instructions-retired")
+return exegesis::ValidationEvent::InstructionRetired;
+  else if (Input == "data-tlb-load-misses")
+return exegesis::ValidationEvent::DataTLBLoadMiss;
+  else if (Input == "data-tlb-store-misses")
+return exegesis::ValidationEvent::DataTLBStoreMiss;
+  else
+return make_error("Invalid validation event string",
+   errc::invalid_argument);
+}
+
+template <>
+struct CustomMappingTraits<
+std::unordered_map> {
+  static void
+  inputOne(IO &Io, StringRef KeyStr,
+   std::unordered_map &VI) {
+Expected Key = stringToValidationEvent(KeyStr);
+if (!Key) {
+  Io.setError("Key is not a valid validation event");
+  return;
+}
+Io.mapRequired(KeyStr.str().c_str(), VI[*Key]);
+  }
+
+  static void
+  output(IO &Io, std::unordered_map &VI) {
+for (auto &IndividualVI : VI) {
+  Io.mapRequired(validationEventToString(IndividualVI.first),
+ IndividualVI.second);
+}
+  }
+};
+
 // exegesis::Measure is rendererd as a flow instead of a list.
 // e.g. { "key": "the key", "value": 0123 }
 template <> struct MappingTraits {
@@ -203,6 +254,7 @@ template <> struct 
MappingTraits {
 }
 Io.mapRequired("value", Obj.PerInstructionValue);
 Io.mapOptional("per_snippet_value", Obj.PerSnippetValue);
+Io.mapOptional("validation_counters", Obj.ValidationCounters);
   }
   static const bool flow = true;
 };
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h 
b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index 0d08febae20cb3..f142da07e0a47d 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -32,6 +32,13 @@ class Error;
 
 namespace exegesis {
 
+enum ValidationEvent {
+  L1DCacheLoadMiss,
+  InstructionRetired,
+  DataTLBLoadMiss,
+  DataTLBStoreMiss
+};
+
 enu