blob: d2ab6b434c4b1ebda84d07783bc991b482619254 [file] [log] [blame]
Clement Courbet9431b722019-09-27 12:56:24 +00001//===-- 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 "Latency.h"
11#include "LlvmState.h"
12#include "MCInstrDescView.h"
13#include "RegisterAliasing.h"
14#include "Uops.h"
15#include "X86InstrInfo.h"
16#include "llvm/CodeGen/MachineBasicBlock.h"
17
18namespace llvm {
19namespace exegesis {
20
21void InitializeX86ExegesisTarget();
22
23namespace {
24
25using testing::ElementsAre;
26using testing::Eq;
27using testing::Field;
28using testing::Property;
29using testing::UnorderedElementsAre;
30
31class X86SnippetRepetitorTest : public ::testing::Test {
32protected:
33 X86SnippetRepetitorTest() : State("x86_64-unknown-linux", "haswell") {}
34
35 static void SetUpTestCase() {
36 LLVMInitializeX86TargetInfo();
37 LLVMInitializeX86TargetMC();
38 LLVMInitializeX86Target();
39 LLVMInitializeX86AsmPrinter();
40 InitializeX86ExegesisTarget();
41 }
42
43 void SetUp() {
44 TM = State.createTargetMachine();
45 Context = std::make_unique<LLVMContext>();
Clement Courbet24078fe2019-09-27 13:21:37 +000046 Mod =
47 std::make_unique<Module>("X86SnippetRepetitorTest", *Context);
48 Mod->setDataLayout(TM->createDataLayout());
Clement Courbet9431b722019-09-27 12:56:24 +000049 MMI = std::make_unique<MachineModuleInfo>(TM.get());
Clement Courbet24078fe2019-09-27 13:21:37 +000050 MF = &createVoidVoidPtrMachineFunction("TestFn", Mod.get(), MMI.get());
Clement Courbet9431b722019-09-27 12:56:24 +000051 }
52
53 void TestCommon(InstructionBenchmark::RepetitionModeE RepetitionMode) {
54 const auto Repetitor = SnippetRepetitor::Create(RepetitionMode, State);
55 const std::vector<MCInst> Instructions = {MCInstBuilder(X86::NOOP)};
56 FunctionFiller Sink(*MF, {X86::EAX});
57 const auto Fill = Repetitor->Repeat(Instructions, kMinInstructions);
58 Fill(Sink);
59 }
60
61 static constexpr const unsigned kMinInstructions = 3;
62
63 const LLVMState State;
Clement Courbet24078fe2019-09-27 13:21:37 +000064 std::unique_ptr<LLVMTargetMachine> TM;
Clement Courbet9431b722019-09-27 12:56:24 +000065 std::unique_ptr<LLVMContext> Context;
Clement Courbet24078fe2019-09-27 13:21:37 +000066 std::unique_ptr<Module> Mod;
Clement Courbet9431b722019-09-27 12:56:24 +000067 std::unique_ptr<MachineModuleInfo> MMI;
68 MachineFunction *MF = nullptr;
69};
70
71static auto HasOpcode = [](unsigned Opcode) {
72 return Property(&MachineInstr::getOpcode, Eq(Opcode));
73};
74
75static auto LiveReg = [](unsigned Reg) {
76 return Field(&MachineBasicBlock::RegisterMaskPair::PhysReg, Eq(Reg));
77};
78
79TEST_F(X86SnippetRepetitorTest, Duplicate) {
80 TestCommon(InstructionBenchmark::Duplicate);
81 // Duplicating creates a single basic block that repeats the instructions.
82 ASSERT_EQ(MF->getNumBlockIDs(), 1u);
83 EXPECT_THAT(MF->getBlockNumbered(0)->instrs(),
84 ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::NOOP),
85 HasOpcode(X86::NOOP), HasOpcode(X86::RETQ)));
86}
87
88TEST_F(X86SnippetRepetitorTest, Loop) {
89 TestCommon(InstructionBenchmark::Loop);
90 // Duplicating creates an entry block, a loop body and a ret block.
91 ASSERT_EQ(MF->getNumBlockIDs(), 3u);
92 const auto &LoopBlock = *MF->getBlockNumbered(1);
93 EXPECT_THAT(LoopBlock.instrs(),
94 ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::ADD64ri8),
95 HasOpcode(X86::JCC_1)));
96 EXPECT_THAT(LoopBlock.liveins(),
97 UnorderedElementsAre(
98 LiveReg(X86::EAX),
99 LiveReg(State.getExegesisTarget().getLoopCounterRegister(
100 State.getTargetMachine().getTargetTriple()))));
101 EXPECT_THAT(MF->getBlockNumbered(2)->instrs(),
102 ElementsAre(HasOpcode(X86::RETQ)));
103}
104
105} // namespace
106} // namespace exegesis
107} // namespace llvm