242 lines · cpp
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-exception6//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 {26namespace {27 28using testing::ElementsAre;29using testing::Eq;30using testing::Property;31using testing::SizeIs;32using testing::UnorderedElementsAre;33 34using llvm::unittest::TempDir;35 36class X86SnippetFileTest : public X86TestBase {37protected:38 Expected<std::vector<BenchmarkCode>> TestCommon(StringRef Contents) {39 TempDir TestDirectory("SnippetFileTestDir", /*Unique*/ true);40 SmallString<64> Filename(TestDirectory.path());41 sys::path::append(Filename, "snippet.s");42 errs() << Filename << "-------\n";43 {44 std::error_code EC;45 raw_fd_ostream FOS(Filename, EC);46 FOS << Contents;47 EXPECT_FALSE(EC);48 }49 return readSnippets(State, Filename);50 }51};52 53// FIXME: Refactor these to ../Common/Matchers.h54static auto HasOpcode = [](unsigned Opcode) {55 return Property(&MCInst::getOpcode, Eq(Opcode));56};57 58MATCHER_P2(RegisterInitialValueIs, Reg, Val, "") {59 if (arg.Register == Reg &&60 arg.Value.getLimitedValue() == static_cast<uint64_t>(Val))61 return true;62 *result_listener << "expected: {" << Reg << ", " << Val << "} ";63 *result_listener << "actual: {" << arg.Register << ", "64 << arg.Value.getLimitedValue() << "}";65 return false;66}67 68MATCHER_P3(MemoryDefinitionIs, Name, Value, Size, "") {69 if (arg.second.Value.getLimitedValue() == static_cast<uint64_t>(Value) &&70 arg.second.SizeBytes == static_cast<size_t>(Size) && arg.first == Name)71 return true;72 *result_listener << "expected: {" << Name << ", " << Value << ", " << Size73 << "} ";74 *result_listener << "actual: {" << arg.first << ", "75 << arg.second.Value.getLimitedValue() << ", "76 << arg.second.SizeBytes << "}";77 return false;78}79 80MATCHER_P2(MemoryMappingIs, Address, Name, "") {81 if (arg.Address == static_cast<uintptr_t>(Address) &&82 arg.MemoryValueName == Name)83 return true;84 *result_listener << "expected: {" << Address << ", " << Name << "} ";85 *result_listener << "actual: {" << arg.Address << ", " << arg.MemoryValueName86 << "}";87 return false;88}89 90TEST_F(X86SnippetFileTest, Works) {91 auto Snippets = TestCommon(R"(92 # LLVM-EXEGESIS-DEFREG RAX 0f93 # LLVM-EXEGESIS-DEFREG SIL 094 # LLVM-EXEGESIS-LIVEIN RDI95 # LLVM-EXEGESIS-LIVEIN DL96 incq %rax97 )");98 EXPECT_FALSE((bool)Snippets.takeError());99 ASSERT_THAT(*Snippets, SizeIs(1));100 const auto &Snippet = (*Snippets)[0];101 ASSERT_THAT(Snippet.Key.Instructions, ElementsAre(HasOpcode(X86::INC64r)));102 ASSERT_THAT(Snippet.Key.RegisterInitialValues,103 ElementsAre(RegisterInitialValueIs(X86::RAX, 15),104 RegisterInitialValueIs(X86::SIL, 0)));105 ASSERT_THAT(Snippet.LiveIns, ElementsAre(X86::RDI, X86::DL));106}107 108TEST_F(X86SnippetFileTest, BadDefregParam) {109 auto Error = TestCommon(R"(110 # LLVM-EXEGESIS-DEFREG DOESNOEXIST 0111 incq %rax112 )")113 .takeError();114 EXPECT_TRUE((bool)Error);115 consumeError(std::move(Error));116}117 118TEST_F(X86SnippetFileTest, NoDefregValue) {119 auto Error = TestCommon(R"(120 # LLVM-EXEGESIS-DEFREG RAX121 incq %rax122 )")123 .takeError();124 EXPECT_TRUE((bool)Error);125 consumeError(std::move(Error));126}127 128TEST_F(X86SnippetFileTest, MissingParam) {129 auto Error = TestCommon(R"(130 # LLVM-EXEGESIS-LIVEIN131 incq %rax132 )")133 .takeError();134 EXPECT_TRUE((bool)Error);135 consumeError(std::move(Error));136}137 138TEST_F(X86SnippetFileTest, NoAsmStreamer) {139 auto Snippets = TestCommon(R"(140 .cv_fpo_proc foo 4141 )");142 EXPECT_FALSE((bool)Snippets.takeError());143}144 145TEST_F(X86SnippetFileTest, MemoryDefinitionTestSingleDef) {146 auto Snippets = TestCommon(R"(147 # LLVM-EXEGESIS-MEM-DEF test1 4096 ff148 # LLVM-EXEGESIS-MEM-MAP test1 65536149 # LLVM-EXEGESIS-MEM-MAP test1 131072150 movq $8192, %r10151 movq (%r10), %r11152 )");153 EXPECT_FALSE((bool)Snippets.takeError());154 ASSERT_THAT(*Snippets, SizeIs(1));155 const auto &Snippet = (*Snippets)[0];156 ASSERT_THAT(Snippet.Key.MemoryValues,157 UnorderedElementsAre(MemoryDefinitionIs("test1", 255, 4096)));158 ASSERT_THAT(Snippet.Key.MemoryMappings,159 ElementsAre(MemoryMappingIs(65536, "test1"),160 MemoryMappingIs(131072, "test1")));161}162 163TEST_F(X86SnippetFileTest, MemoryDefinitionsTestTwoDef) {164 auto Snippets = TestCommon(R"(165 # LLVM-EXEGESIS-MEM-DEF test1 4096 ff166 # LLVM-EXEGESIS-MEM-DEF test2 4096 100167 # LLVM-EXEGESIS-MEM-MAP test1 65536168 # LLVM-EXEGESIS-MEM-MAP test2 131072169 movq $8192, %r10170 movq (%r10), %r11171 )");172 EXPECT_FALSE((bool)Snippets.takeError());173 ASSERT_THAT(*Snippets, SizeIs(1));174 const auto &Snippet = (*Snippets)[0];175 ASSERT_THAT(Snippet.Key.MemoryValues,176 UnorderedElementsAre(MemoryDefinitionIs("test1", 255, 4096),177 MemoryDefinitionIs("test2", 256, 4096)));178 ASSERT_THAT(Snippet.Key.MemoryMappings,179 ElementsAre(MemoryMappingIs(65536, "test1"),180 MemoryMappingIs(131072, "test2")));181}182 183TEST_F(X86SnippetFileTest, MemoryDefinitionMissingParameter) {184 auto Error = TestCommon(R"(185 # LLVM-EXEGESIS-MEM-DEF test1 4096186 )")187 .takeError();188 EXPECT_TRUE((bool)Error);189 consumeError(std::move(Error));190}191 192TEST_F(X86SnippetFileTest, MemoryMappingMissingParameters) {193 auto Error = TestCommon(R"(194 # LLVM-EXEGESIS-MEM-MAP test1195 )")196 .takeError();197 EXPECT_TRUE((bool)Error);198 consumeError(std::move(Error));199}200 201TEST_F(X86SnippetFileTest, MemoryMappingNoDefinition) {202 auto Error = TestCommon(R"(203 # LLVM-EXEGESIS-MEM-MAP test1 65536204 )")205 .takeError();206 EXPECT_TRUE((bool)Error);207 consumeError(std::move(Error));208}209 210TEST_F(X86SnippetFileTest, SnippetAddress) {211 auto Snippets = TestCommon(R"(212 # LLVM-EXEGESIS-SNIPPET-ADDRESS 10000213 )");214 ASSERT_TRUE(static_cast<bool>(Snippets));215 EXPECT_THAT(*Snippets, SizeIs(1));216 const auto &Snippet = (*Snippets)[0];217 EXPECT_EQ(Snippet.Key.SnippetAddress, static_cast<uintptr_t>(0x10000));218}219 220TEST_F(X86SnippetFileTest, LoopRegister) {221 auto Snippets = TestCommon(R"(222 # LLVM-EXEGESIS-LOOP-REGISTER R11223 )");224 ASSERT_TRUE(static_cast<bool>(Snippets));225 EXPECT_THAT(*Snippets, SizeIs(1));226 const auto &Snippet = (*Snippets)[0];227 EXPECT_EQ(Snippet.Key.LoopRegister, X86::R11);228}229 230TEST_F(X86SnippetFileTest, LoopRegisterInvalidRegister) {231 auto Error = TestCommon(R"(232 # LLVM-EXEGESIS-LOOP-REGISTER INVALID233 )")234 .takeError();235 EXPECT_TRUE(static_cast<bool>(Error));236 consumeError(std::move(Error));237}238 239} // namespace240} // namespace exegesis241} // namespace llvm242