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