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