llvm-project
175 строк · 5.9 Кб
1//===-- BenchmarkResultTest.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 "BenchmarkResult.h"10#include "X86InstrInfo.h"11#include "llvm/ADT/SmallString.h"12#include "llvm/MC/TargetRegistry.h"13#include "llvm/Support/Error.h"14#include "llvm/Support/FileSystem.h"15#include "llvm/Support/Path.h"16#include "llvm/Support/TargetSelect.h"17#include "llvm/Support/YAMLTraits.h"18#include "llvm/Support/raw_ostream.h"19#include "gmock/gmock.h"20#include "gtest/gtest.h"21
22using ::testing::AllOf;23using ::testing::Eq;24using ::testing::Field;25using ::testing::Pointwise;26
27namespace llvm {28namespace exegesis {29
30void InitializeX86ExegesisTarget();31
32static std::string Dump(const MCInst &McInst) {33std::string Buffer;34raw_string_ostream OS(Buffer);35McInst.print(OS);36return Buffer;37}
38
39MATCHER(EqMCInst, "") {40const std::string Lhs = Dump(get<0>(arg));41const std::string Rhs = Dump(get<1>(arg));42if (Lhs != Rhs) {43*result_listener << Lhs << " <=> " << Rhs;44return false;45}46return true;47}
48
49MATCHER(EqRegValue, "") {50const RegisterValue Lhs = get<0>(arg);51const RegisterValue Rhs = get<1>(arg);52if (Lhs.Register != Rhs.Register || Lhs.Value != Rhs.Value)53return false;54
55return true;56}
57
58namespace {59
60TEST(BenchmarkResultTest, WriteToAndReadFromDisk) {61LLVMInitializeX86TargetInfo();62LLVMInitializeX86Target();63LLVMInitializeX86TargetMC();64InitializeX86ExegesisTarget();65
66// Read benchmarks.67const LLVMState State =68cantFail(LLVMState::Create("x86_64-unknown-linux", "haswell"));69
70ExitOnError ExitOnErr;71
72Benchmark ToDisk;73
74ToDisk.Key.Instructions.push_back(MCInstBuilder(X86::XOR32rr)75.addReg(X86::AL)76.addReg(X86::AH)77.addImm(123)78.addDFPImm(bit_cast<uint64_t>(0.5)));79ToDisk.Key.Config = "config";80ToDisk.Key.RegisterInitialValues = {81RegisterValue{X86::AL, APInt(8, "-1", 10)},82RegisterValue{X86::AH, APInt(8, "123", 10)}};83ToDisk.Mode = Benchmark::Latency;84ToDisk.CpuName = "cpu_name";85ToDisk.LLVMTriple = "llvm_triple";86ToDisk.MinInstructions = 1;87ToDisk.Measurements.push_back(BenchmarkMeasure::Create("a", 1, {}));88ToDisk.Measurements.push_back(BenchmarkMeasure::Create("b", 2, {}));89ToDisk.Error = "error";90ToDisk.Info = "info";91
92SmallString<64> Filename;93std::error_code EC;94EC = sys::fs::createUniqueDirectory("BenchmarkResultTestDir", Filename);95ASSERT_FALSE(EC);96sys::path::append(Filename, "data.yaml");97errs() << Filename << "-------\n";98{99int ResultFD = 0;100// Create output file or open existing file and truncate it, once.101ExitOnErr(errorCodeToError(openFileForWrite(Filename, ResultFD,102sys::fs::CD_CreateAlways,103sys::fs::OF_TextWithCRLF)));104raw_fd_ostream FileOstr(ResultFD, true /*shouldClose*/);105
106ExitOnErr(ToDisk.writeYamlTo(State, FileOstr));107}108
109const std::unique_ptr<MemoryBuffer> Buffer =110std::move(*MemoryBuffer::getFile(Filename));111
112{113// Read Triples/Cpu only.114const auto TriplesAndCpus =115ExitOnErr(Benchmark::readTriplesAndCpusFromYamls(*Buffer));116
117ASSERT_THAT(TriplesAndCpus,118testing::ElementsAre(119AllOf(Field(&Benchmark::TripleAndCpu::LLVMTriple,120Eq("llvm_triple")),121Field(&Benchmark::TripleAndCpu::CpuName,122Eq("cpu_name")))));123}124{125// One-element version.126const auto FromDisk =127ExitOnErr(Benchmark::readYaml(State, *Buffer));128
129EXPECT_THAT(FromDisk.Key.Instructions,130Pointwise(EqMCInst(), ToDisk.Key.Instructions));131EXPECT_EQ(FromDisk.Key.Config, ToDisk.Key.Config);132EXPECT_THAT(FromDisk.Key.RegisterInitialValues,133Pointwise(EqRegValue(), ToDisk.Key.RegisterInitialValues));134EXPECT_EQ(FromDisk.Mode, ToDisk.Mode);135EXPECT_EQ(FromDisk.CpuName, ToDisk.CpuName);136EXPECT_EQ(FromDisk.LLVMTriple, ToDisk.LLVMTriple);137EXPECT_EQ(FromDisk.MinInstructions, ToDisk.MinInstructions);138EXPECT_THAT(FromDisk.Measurements, ToDisk.Measurements);139EXPECT_THAT(FromDisk.Error, ToDisk.Error);140EXPECT_EQ(FromDisk.Info, ToDisk.Info);141}142{143// Vector version.144const auto FromDiskVector =145ExitOnErr(Benchmark::readYamls(State, *Buffer));146ASSERT_EQ(FromDiskVector.size(), size_t{1});147const auto &FromDisk = FromDiskVector[0];148EXPECT_THAT(FromDisk.Key.Instructions,149Pointwise(EqMCInst(), ToDisk.Key.Instructions));150EXPECT_EQ(FromDisk.Key.Config, ToDisk.Key.Config);151EXPECT_THAT(FromDisk.Key.RegisterInitialValues,152Pointwise(EqRegValue(), ToDisk.Key.RegisterInitialValues));153EXPECT_EQ(FromDisk.Mode, ToDisk.Mode);154EXPECT_EQ(FromDisk.CpuName, ToDisk.CpuName);155EXPECT_EQ(FromDisk.LLVMTriple, ToDisk.LLVMTriple);156EXPECT_EQ(FromDisk.MinInstructions, ToDisk.MinInstructions);157EXPECT_THAT(FromDisk.Measurements, ToDisk.Measurements);158EXPECT_THAT(FromDisk.Error, ToDisk.Error);159EXPECT_EQ(FromDisk.Info, ToDisk.Info);160}161}
162
163TEST(BenchmarkResultTest, PerInstructionStats) {164PerInstructionStats Stats;165Stats.push(BenchmarkMeasure::Create("a", 0.5, {}));166Stats.push(BenchmarkMeasure::Create("a", 1.5, {}));167Stats.push(BenchmarkMeasure::Create("a", -1.0, {}));168Stats.push(BenchmarkMeasure::Create("a", 0.0, {}));169EXPECT_EQ(Stats.min(), -1.0);170EXPECT_EQ(Stats.max(), 1.5);171EXPECT_EQ(Stats.avg(), 0.25); // (0.5+1.5-1.0+0.0) / 4172}
173} // namespace174} // namespace exegesis175} // namespace llvm176