llvm-project
243 строки · 7.3 Кб
1//===-- SnippetFileTest.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//===----------------------------------------------------------------------===//
8
9#include "SnippetFile.h"
10
11#include "LlvmState.h"
12#include "TestBase.h"
13#include "X86InstrInfo.h"
14#include "llvm/MC/TargetRegistry.h"
15#include "llvm/Support/Error.h"
16#include "llvm/Support/FileSystem.h"
17#include "llvm/Support/Path.h"
18#include "llvm/Support/TargetSelect.h"
19#include "llvm/Support/raw_ostream.h"
20#include "llvm/Testing/Support/SupportHelpers.h"
21#include "gmock/gmock.h"
22#include "gtest/gtest.h"
23
24namespace llvm {
25namespace exegesis {
26
27void InitializeX86ExegesisTarget();
28
29namespace {
30
31using testing::ElementsAre;
32using testing::Eq;
33using testing::Property;
34using testing::SizeIs;
35using testing::UnorderedElementsAre;
36
37using llvm::unittest::TempDir;
38
39class X86SnippetFileTest : public X86TestBase {
40protected:
41Expected<std::vector<BenchmarkCode>> TestCommon(StringRef Contents) {
42TempDir TestDirectory("SnippetFileTestDir", /*Unique*/ true);
43SmallString<64> Filename(TestDirectory.path());
44sys::path::append(Filename, "snippet.s");
45errs() << Filename << "-------\n";
46{
47std::error_code EC;
48raw_fd_ostream FOS(Filename, EC);
49FOS << Contents;
50EXPECT_FALSE(EC);
51}
52return readSnippets(State, Filename);
53}
54};
55
56// FIXME: Refactor these to ../Common/Matchers.h
57static auto HasOpcode = [](unsigned Opcode) {
58return Property(&MCInst::getOpcode, Eq(Opcode));
59};
60
61MATCHER_P2(RegisterInitialValueIs, Reg, Val, "") {
62if (arg.Register == Reg &&
63arg.Value.getLimitedValue() == static_cast<uint64_t>(Val))
64return true;
65*result_listener << "expected: {" << Reg << ", " << Val << "} ";
66*result_listener << "actual: {" << arg.Register << ", "
67<< arg.Value.getLimitedValue() << "}";
68return false;
69}
70
71MATCHER_P3(MemoryDefinitionIs, Name, Value, Size, "") {
72if (arg.second.Value.getLimitedValue() == static_cast<uint64_t>(Value) &&
73arg.second.SizeBytes == static_cast<size_t>(Size) && arg.first == Name)
74return true;
75*result_listener << "expected: {" << Name << ", " << Value << ", " << Size
76<< "} ";
77*result_listener << "actual: {" << arg.first << ", "
78<< arg.second.Value.getLimitedValue() << ", "
79<< arg.second.SizeBytes << "}";
80return false;
81}
82
83MATCHER_P2(MemoryMappingIs, Address, Name, "") {
84if (arg.Address == Address && arg.MemoryValueName == Name)
85return true;
86*result_listener << "expected: {" << Address << ", " << Name << "} ";
87*result_listener << "actual: {" << arg.Address << ", " << arg.MemoryValueName
88<< "}";
89return false;
90}
91
92TEST_F(X86SnippetFileTest, Works) {
93auto Snippets = TestCommon(R"(
94# LLVM-EXEGESIS-DEFREG RAX 0f
95# LLVM-EXEGESIS-DEFREG SIL 0
96# LLVM-EXEGESIS-LIVEIN RDI
97# LLVM-EXEGESIS-LIVEIN DL
98incq %rax
99)");
100EXPECT_FALSE((bool)Snippets.takeError());
101ASSERT_THAT(*Snippets, SizeIs(1));
102const auto &Snippet = (*Snippets)[0];
103ASSERT_THAT(Snippet.Key.Instructions, ElementsAre(HasOpcode(X86::INC64r)));
104ASSERT_THAT(Snippet.Key.RegisterInitialValues,
105ElementsAre(RegisterInitialValueIs(X86::RAX, 15),
106RegisterInitialValueIs(X86::SIL, 0)));
107ASSERT_THAT(Snippet.LiveIns, ElementsAre(X86::RDI, X86::DL));
108}
109
110TEST_F(X86SnippetFileTest, BadDefregParam) {
111auto Error = TestCommon(R"(
112# LLVM-EXEGESIS-DEFREG DOESNOEXIST 0
113incq %rax
114)")
115.takeError();
116EXPECT_TRUE((bool)Error);
117consumeError(std::move(Error));
118}
119
120TEST_F(X86SnippetFileTest, NoDefregValue) {
121auto Error = TestCommon(R"(
122# LLVM-EXEGESIS-DEFREG RAX
123incq %rax
124)")
125.takeError();
126EXPECT_TRUE((bool)Error);
127consumeError(std::move(Error));
128}
129
130TEST_F(X86SnippetFileTest, MissingParam) {
131auto Error = TestCommon(R"(
132# LLVM-EXEGESIS-LIVEIN
133incq %rax
134)")
135.takeError();
136EXPECT_TRUE((bool)Error);
137consumeError(std::move(Error));
138}
139
140TEST_F(X86SnippetFileTest, NoAsmStreamer) {
141auto Snippets = TestCommon(R"(
142.cv_fpo_proc foo 4
143)");
144EXPECT_FALSE((bool)Snippets.takeError());
145}
146
147TEST_F(X86SnippetFileTest, MemoryDefinitionTestSingleDef) {
148auto Snippets = TestCommon(R"(
149# LLVM-EXEGESIS-MEM-DEF test1 4096 ff
150# LLVM-EXEGESIS-MEM-MAP test1 65536
151# LLVM-EXEGESIS-MEM-MAP test1 131072
152movq $8192, %r10
153movq (%r10), %r11
154)");
155EXPECT_FALSE((bool)Snippets.takeError());
156ASSERT_THAT(*Snippets, SizeIs(1));
157const auto &Snippet = (*Snippets)[0];
158ASSERT_THAT(Snippet.Key.MemoryValues,
159UnorderedElementsAre(MemoryDefinitionIs("test1", 255, 4096)));
160ASSERT_THAT(Snippet.Key.MemoryMappings,
161ElementsAre(MemoryMappingIs(65536, "test1"),
162MemoryMappingIs(131072, "test1")));
163}
164
165TEST_F(X86SnippetFileTest, MemoryDefinitionsTestTwoDef) {
166auto Snippets = TestCommon(R"(
167# LLVM-EXEGESIS-MEM-DEF test1 4096 ff
168# LLVM-EXEGESIS-MEM-DEF test2 4096 100
169# LLVM-EXEGESIS-MEM-MAP test1 65536
170# LLVM-EXEGESIS-MEM-MAP test2 131072
171movq $8192, %r10
172movq (%r10), %r11
173)");
174EXPECT_FALSE((bool)Snippets.takeError());
175ASSERT_THAT(*Snippets, SizeIs(1));
176const auto &Snippet = (*Snippets)[0];
177ASSERT_THAT(Snippet.Key.MemoryValues,
178UnorderedElementsAre(MemoryDefinitionIs("test1", 255, 4096),
179MemoryDefinitionIs("test2", 256, 4096)));
180ASSERT_THAT(Snippet.Key.MemoryMappings,
181ElementsAre(MemoryMappingIs(65536, "test1"),
182MemoryMappingIs(131072, "test2")));
183}
184
185TEST_F(X86SnippetFileTest, MemoryDefinitionMissingParameter) {
186auto Error = TestCommon(R"(
187# LLVM-EXEGESIS-MEM-DEF test1 4096
188)")
189.takeError();
190EXPECT_TRUE((bool)Error);
191consumeError(std::move(Error));
192}
193
194TEST_F(X86SnippetFileTest, MemoryMappingMissingParameters) {
195auto Error = TestCommon(R"(
196# LLVM-EXEGESIS-MEM-MAP test1
197)")
198.takeError();
199EXPECT_TRUE((bool)Error);
200consumeError(std::move(Error));
201}
202
203TEST_F(X86SnippetFileTest, MemoryMappingNoDefinition) {
204auto Error = TestCommon(R"(
205# LLVM-EXEGESIS-MEM-MAP test1 65536
206)")
207.takeError();
208EXPECT_TRUE((bool)Error);
209consumeError(std::move(Error));
210}
211
212TEST_F(X86SnippetFileTest, SnippetAddress) {
213auto Snippets = TestCommon(R"(
214# LLVM-EXEGESIS-SNIPPET-ADDRESS 10000
215)");
216ASSERT_TRUE(static_cast<bool>(Snippets));
217EXPECT_THAT(*Snippets, SizeIs(1));
218const auto &Snippet = (*Snippets)[0];
219EXPECT_EQ(Snippet.Key.SnippetAddress, 0x10000);
220}
221
222TEST_F(X86SnippetFileTest, LoopRegister) {
223auto Snippets = TestCommon(R"(
224# LLVM-EXEGESIS-LOOP-REGISTER R11
225)");
226ASSERT_TRUE(static_cast<bool>(Snippets));
227EXPECT_THAT(*Snippets, SizeIs(1));
228const auto &Snippet = (*Snippets)[0];
229EXPECT_EQ(Snippet.Key.LoopRegister, X86::R11);
230}
231
232TEST_F(X86SnippetFileTest, LoopRegisterInvalidRegister) {
233auto Error = TestCommon(R"(
234# LLVM-EXEGESIS-LOOP-REGISTER INVALID
235)")
236.takeError();
237EXPECT_TRUE(static_cast<bool>(Error));
238consumeError(std::move(Error));
239}
240
241} // namespace
242} // namespace exegesis
243} // namespace llvm
244