llvm-project
116 строк · 4.2 Кб
1//===-- SnippetRepetitorTest.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 "../Common/AssemblerUtils.h"10#include "LlvmState.h"11#include "MCInstrDescView.h"12#include "RegisterAliasing.h"13#include "TestBase.h"14#include "X86InstrInfo.h"15#include "llvm/CodeGen/MachineBasicBlock.h"16
17namespace llvm {18namespace exegesis {19
20void InitializeX86ExegesisTarget();21
22namespace {23
24using testing::ElementsAre;25using testing::Eq;26using testing::Field;27using testing::Property;28using testing::UnorderedElementsAre;29
30class X86SnippetRepetitorTest : public X86TestBase {31protected:32void SetUp() override {33TM = State.createTargetMachine();34Context = std::make_unique<LLVMContext>();35Mod = std::make_unique<Module>("X86SnippetRepetitorTest", *Context);36Mod->setDataLayout(TM->createDataLayout());37MMI = std::make_unique<MachineModuleInfo>(TM.get());38MF = &createVoidVoidPtrMachineFunction("TestFn", Mod.get(), MMI.get());39}40
41void TestCommon(Benchmark::RepetitionModeE RepetitionMode,42unsigned SnippetInstructions = 1) {43const auto Repetitor = SnippetRepetitor::Create(44RepetitionMode, State,45State.getExegesisTarget().getDefaultLoopCounterRegister(46State.getTargetMachine().getTargetTriple()));47const std::vector<MCInst> Instructions(SnippetInstructions,48MCInstBuilder(X86::NOOP));49FunctionFiller Sink(*MF, {X86::EAX});50const auto Fill =51Repetitor->Repeat(Instructions, kMinInstructions, kLoopBodySize, false);52Fill(Sink);53}54
55static constexpr const unsigned kMinInstructions = 3;56static constexpr const unsigned kLoopBodySize = 5;57
58std::unique_ptr<LLVMTargetMachine> TM;59std::unique_ptr<LLVMContext> Context;60std::unique_ptr<Module> Mod;61std::unique_ptr<MachineModuleInfo> MMI;62MachineFunction *MF = nullptr;63};64
65static auto HasOpcode = [](unsigned Opcode) {66return Property(&MachineInstr::getOpcode, Eq(Opcode));67};68
69static auto LiveReg = [](unsigned Reg) {70return Field(&MachineBasicBlock::RegisterMaskPair::PhysReg, Eq(Reg));71};72
73TEST_F(X86SnippetRepetitorTest, Duplicate) {74TestCommon(Benchmark::Duplicate);75// Duplicating creates a single basic block that repeats the instructions.76ASSERT_EQ(MF->getNumBlockIDs(), 1u);77EXPECT_THAT(MF->getBlockNumbered(0)->instrs(),78ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::NOOP),79HasOpcode(X86::NOOP), HasOpcode(X86::RET64)));80}
81
82TEST_F(X86SnippetRepetitorTest, DuplicateSnippetInstructionCount) {83TestCommon(Benchmark::Duplicate, 2);84// Duplicating a snippet of two instructions with the minimum number of85// instructions set to three duplicates the snippet twice for a total of86// four instructions.87ASSERT_EQ(MF->getNumBlockIDs(), 1u);88EXPECT_THAT(MF->getBlockNumbered(0)->instrs(),89ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::NOOP),90HasOpcode(X86::NOOP), HasOpcode(X86::NOOP),91HasOpcode(X86::RET64)));92}
93
94TEST_F(X86SnippetRepetitorTest, Loop) {95TestCommon(Benchmark::Loop);96// Duplicating creates an entry block, a loop body and a ret block.97ASSERT_EQ(MF->getNumBlockIDs(), 3u);98const auto &LoopBlock = *MF->getBlockNumbered(1);99EXPECT_THAT(LoopBlock.instrs(),100ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::NOOP),101HasOpcode(X86::NOOP), HasOpcode(X86::NOOP),102HasOpcode(X86::NOOP), HasOpcode(X86::ADD64ri8),103HasOpcode(X86::JCC_1)));104EXPECT_THAT(105LoopBlock.liveins(),106UnorderedElementsAre(107LiveReg(X86::EAX),108LiveReg(State.getExegesisTarget().getDefaultLoopCounterRegister(109State.getTargetMachine().getTargetTriple()))));110EXPECT_THAT(MF->getBlockNumbered(2)->instrs(),111ElementsAre(HasOpcode(X86::RET64)));112}
113
114} // namespace115} // namespace exegesis116} // namespace llvm117