[llvm] f0655b0 - [llvm-exegesis] Add memory annotation parsing
Aiden Grossman via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 26 22:31:45 PDT 2023
Author: Aiden Grossman
Date: 2023-06-27T05:30:54Z
New Revision: f0655b0d06129330f710b3cb9955cec7e778bfd0
URL: https://github.com/llvm/llvm-project/commit/f0655b0d06129330f710b3cb9955cec7e778bfd0
DIFF: https://github.com/llvm/llvm-project/commit/f0655b0d06129330f710b3cb9955cec7e778bfd0.diff
LOG: [llvm-exegesis] Add memory annotation parsing
This patch adds memory annotation parsing to llvm-exegesis. The memory
annotations cannot be used currently, but this allows for using parsed
memory annotations within a FunctionExecutorImpl to set up a specified
execution environment.
Added:
llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-unsupported.s
Modified:
llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
llvm/tools/llvm-exegesis/lib/SnippetFile.h
llvm/tools/llvm-exegesis/llvm-exegesis.cpp
llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-unsupported.s b/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-unsupported.s
new file mode 100644
index 0000000000000..5d06a0ceff5c7
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/X86/latency/memory-annotations-unsupported.s
@@ -0,0 +1,9 @@
+# REQUIRES: exegesis-can-measure-latency, x86_64-linux
+
+# RUN: not llvm-exegesis -mtriple=x86_64-unknown-unknown -snippets-file=%s -mode=latency 2>&1 | FileCheck %s
+
+# CHECK: llvm-exegesis error: Memory annotations are only supported in subprocess execution mode
+
+# LLVM-EXEGESIS-MEM-DEF test1 4096 ff
+
+movq $0, %rax
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index eb3b839ea09fb..77e0994fe0208 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -64,6 +64,11 @@ struct BenchmarkKey {
std::vector<MCInst> Instructions;
// The initial values of the registers.
std::vector<RegisterValue> RegisterInitialValues;
+ // The memory values that can be mapped into the execution context of the
+ // snippet.
+ std::unordered_map<std::string, MemoryValue> MemoryValues;
+ // The memory mappings that the snippet can access.
+ std::vector<MemoryMapping> MemoryMappings;
// An opaque configuration, that can be used to separate several benchmarks of
// the same instruction under
diff erent configurations.
std::string Config;
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index 0b69a79b02cc7..d85a9f190655a 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "SnippetFile.h"
+#include "BenchmarkRunner.h"
#include "Error.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCInstPrinter.h"
@@ -82,6 +83,54 @@ class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
}
return;
}
+ if (CommentText.consume_front("MEM-DEF")) {
+ // LLVM-EXEGESIS-MEM-DEF <name> <size> <value>
+ SmallVector<StringRef, 3> Parts;
+ CommentText.split(Parts, ' ', -1, false);
+ if (Parts.size() != 3) {
+ errs() << "invalid comment 'LLVM-EXEGESIS-MEM-DEF " << CommentText
+ << "', expected three parameters <NAME> <SIZE> <VALUE>";
+ ++InvalidComments;
+ return;
+ }
+ const StringRef HexValue = Parts[2].trim();
+ MemoryValue MemVal;
+ MemVal.SizeBytes = std::stol(Parts[1].trim().str());
+ if (HexValue.size() % 2 != 0) {
+ errs() << "invalid comment 'LLVM-EXEGESIS-MEM-DEF " << CommentText
+ << "', expected <VALUE> to contain a whole number of bytes";
+ }
+ MemVal.Value = APInt(HexValue.size() * 4, HexValue, 16);
+ MemVal.Index = Result->Key.MemoryValues.size();
+ Result->Key.MemoryValues[Parts[0].trim().str()] = MemVal;
+ return;
+ }
+ if (CommentText.consume_front("MEM-MAP")) {
+ // LLVM-EXEGESIS-MEM-MAP <value name> <address>
+ SmallVector<StringRef, 2> Parts;
+ CommentText.split(Parts, ' ', -1, false);
+ if (Parts.size() != 2) {
+ errs() << "invalid comment 'LLVM-EXEGESIS-MEM-MAP " << CommentText
+ << "', expected two parameters <VALUE NAME> <ADDRESS>";
+ ++InvalidComments;
+ return;
+ }
+ MemoryMapping MemMap;
+ MemMap.MemoryValueName = Parts[0].trim().str();
+ MemMap.Address = std::stol(Parts[1].trim().str());
+ // validate that the annotation refers to an already existing memory
+ // definition
+ auto MemValIT = Result->Key.MemoryValues.find(Parts[0].trim().str());
+ if (MemValIT == Result->Key.MemoryValues.end()) {
+ errs() << "invalid comment 'LLVM-EXEGESIS-MEM-MAP " << CommentText
+ << "', expected <VALUE NAME> to contain the name of an already "
+ "specified memory definition";
+ ++InvalidComments;
+ return;
+ }
+ Result->Key.MemoryMappings.push_back(std::move(MemMap));
+ return;
+ }
}
unsigned numInvalidComments() const { return InvalidComments; }
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetFile.h b/llvm/tools/llvm-exegesis/lib/SnippetFile.h
index c346a047bf41f..74f918d0e60f4 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetFile.h
+++ b/llvm/tools/llvm-exegesis/lib/SnippetFile.h
@@ -17,6 +17,7 @@
#define LLVM_TOOLS_LLVM_EXEGESIS_SNIPPETFILE_H
#include "BenchmarkCode.h"
+#include "BenchmarkRunner.h"
#include "LlvmState.h"
#include "llvm/Support/Error.h"
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 82df07c6a83bb..ff868e756338a 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -15,6 +15,7 @@
#include "lib/BenchmarkResult.h"
#include "lib/BenchmarkRunner.h"
#include "lib/Clustering.h"
+#include "lib/CodeTemplate.h"
#include "lib/Error.h"
#include "lib/LlvmState.h"
#include "lib/PerfHelper.h"
@@ -521,6 +522,13 @@ void benchmarkMain() {
}
} else {
Configurations = ExitOnErr(readSnippets(State, SnippetsFile));
+ for (const auto &Configuration : Configurations) {
+ if (ExecutionMode != BenchmarkRunner::ExecutionModeE::SubProcess &&
+ (Configuration.Key.MemoryMappings.size() != 0 ||
+ Configuration.Key.MemoryValues.size() != 0))
+ ExitWithError("Memory annotations are only supported in subprocess "
+ "execution mode");
+ }
}
if (NumRepetitions == 0) {
diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp
index b868b696c0114..c754d60de3dda 100644
--- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp
+++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetFileTest.cpp
@@ -34,6 +34,7 @@ using testing::Eq;
using testing::Field;
using testing::Property;
using testing::SizeIs;
+using testing::UnorderedElementsAre;
using llvm::unittest::TempDir;
@@ -69,6 +70,27 @@ MATCHER_P2(RegisterInitialValueIs, Reg, Val, "") {
return false;
}
+MATCHER_P3(MemoryDefinitionIs, Name, Value, Size, "") {
+ if (arg.second.Value.getLimitedValue() == static_cast<uint64_t>(Value) &&
+ arg.second.SizeBytes == static_cast<size_t>(Size) && arg.first == Name)
+ return true;
+ *result_listener << "expected: {" << Name << ", " << Value << ", " << Size
+ << "} ";
+ *result_listener << "actual: {" << arg.first << ", "
+ << arg.second.Value.getLimitedValue() << ", "
+ << arg.second.SizeBytes << "}";
+ return false;
+}
+
+MATCHER_P2(MemoryMappingIs, Address, Name, "") {
+ if (arg.Address == Address && arg.MemoryValueName == Name)
+ return true;
+ *result_listener << "expected: {" << Address << ", " << Name << "} ";
+ *result_listener << "actual: {" << arg.Address << ", " << arg.MemoryValueName
+ << "}";
+ return false;
+}
+
TEST_F(X86SnippetFileTest, Works) {
auto Snippets = TestCommon(R"(
# LLVM-EXEGESIS-DEFREG RAX 0f
@@ -124,6 +146,80 @@ TEST_F(X86SnippetFileTest, NoAsmStreamer) {
EXPECT_FALSE((bool)Snippets.takeError());
}
+TEST_F(X86SnippetFileTest, MemoryDefinitionTestSingleDef) {
+ auto Snippets = TestCommon(R"(
+ # LLVM-EXEGESIS-MEM-DEF test1 4096 ff
+ # LLVM-EXEGESIS-MEM-MAP test1 8192
+ # LLVM-EXEGESIS-MEM-MAP test1 16384
+ movq $8192, %r10
+ movq (%r10), %r11
+ )");
+ EXPECT_FALSE((bool)Snippets.takeError());
+ ASSERT_THAT(*Snippets, SizeIs(1));
+ const auto &Snippet = (*Snippets)[0];
+ ASSERT_THAT(Snippet.Key.MemoryValues,
+ UnorderedElementsAre(MemoryDefinitionIs("test1", 255, 4096)));
+ ASSERT_THAT(Snippet.Key.MemoryMappings,
+ ElementsAre(MemoryMappingIs(8192, "test1"),
+ MemoryMappingIs(16384, "test1")));
+}
+
+TEST_F(X86SnippetFileTest, MemoryDefinitionsTestTwoDef) {
+ auto Snippets = TestCommon(R"(
+ # LLVM-EXEGESIS-MEM-DEF test1 4096 ff
+ # LLVM-EXEGESIS-MEM-DEF test2 4096 100
+ # LLVM-EXEGESIS-MEM-MAP test1 8192
+ # LLVM-EXEGESIS-MEM-MAP test2 16384
+ movq $8192, %r10
+ movq (%r10), %r11
+ )");
+ EXPECT_FALSE((bool)Snippets.takeError());
+ ASSERT_THAT(*Snippets, SizeIs(1));
+ const auto &Snippet = (*Snippets)[0];
+ ASSERT_THAT(Snippet.Key.MemoryValues,
+ UnorderedElementsAre(MemoryDefinitionIs("test1", 255, 4096),
+ MemoryDefinitionIs("test2", 256, 4096)));
+ ASSERT_THAT(Snippet.Key.MemoryMappings,
+ ElementsAre(MemoryMappingIs(8192, "test1"),
+ MemoryMappingIs(16384, "test2")));
+}
+
+TEST_F(X86SnippetFileTest, MemoryDefinitionMissingParameter) {
+ auto Error = TestCommon(R"(
+ # LLVM-EXEGESIS-MEM-DEF test1 4096
+ )")
+ .takeError();
+ EXPECT_TRUE((bool)Error);
+ consumeError(std::move(Error));
+}
+
+TEST_F(X86SnippetFileTest, MemoryMappingMissingParameters) {
+ auto Error = TestCommon(R"(
+ # LLVM-EXEGESIS-MEM-MAP test1
+ )")
+ .takeError();
+ EXPECT_TRUE((bool)Error);
+ consumeError(std::move(Error));
+}
+
+TEST_F(X86SnippetFileTest, MemoryMappingNoDefinition) {
+ auto Error = TestCommon(R"(
+ # LLVM-EXEGESIS-MEM-MAP test1 4096
+ )")
+ .takeError();
+ EXPECT_TRUE((bool)Error);
+ consumeError(std::move(Error));
+}
+
+TEST_F(X86SnippetFileTest, IncompatibleExecutorMode) {
+ auto Error = TestCommon(R"(
+ # LLVM-EXEGESIS-MEM-MAP test1 4096
+ )")
+ .takeError();
+ EXPECT_TRUE((bool)Error);
+ consumeError(std::move(Error));
+}
+
} // namespace
} // namespace exegesis
} // namespace llvm
More information about the llvm-commits
mailing list