1 //===-- SnippetRepetitorTest.cpp --------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "../Common/AssemblerUtils.h"
10 #include "LlvmState.h"
11 #include "MCInstrDescView.h"
12 #include "RegisterAliasing.h"
14 #include "X86InstrInfo.h"
15 #include "llvm/CodeGen/MachineBasicBlock.h"
20 void InitializeX86ExegesisTarget();
24 using testing::ElementsAre
;
27 using testing::Property
;
28 using testing::UnorderedElementsAre
;
30 class X86SnippetRepetitorTest
: public X86TestBase
{
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());
41 void TestCommon(InstructionBenchmark::RepetitionModeE RepetitionMode
) {
42 const auto Repetitor
= SnippetRepetitor::Create(RepetitionMode
, State
);
43 const std::vector
<MCInst
> Instructions
= {MCInstBuilder(X86::NOOP
)};
44 FunctionFiller
Sink(*MF
, {X86::EAX
});
46 Repetitor
->Repeat(Instructions
, kMinInstructions
, kLoopBodySize
);
50 static constexpr const unsigned kMinInstructions
= 3;
51 static constexpr const unsigned kLoopBodySize
= 5;
53 std::unique_ptr
<LLVMTargetMachine
> TM
;
54 std::unique_ptr
<LLVMContext
> Context
;
55 std::unique_ptr
<Module
> Mod
;
56 std::unique_ptr
<MachineModuleInfo
> MMI
;
57 MachineFunction
*MF
= nullptr;
60 static auto HasOpcode
= [](unsigned Opcode
) {
61 return Property(&MachineInstr::getOpcode
, Eq(Opcode
));
64 static auto LiveReg
= [](unsigned Reg
) {
65 return Field(&MachineBasicBlock::RegisterMaskPair::PhysReg
, Eq(Reg
));
68 TEST_F(X86SnippetRepetitorTest
, Duplicate
) {
69 TestCommon(InstructionBenchmark::Duplicate
);
70 // Duplicating creates a single basic block that repeats the instructions.
71 ASSERT_EQ(MF
->getNumBlockIDs(), 1u);
72 EXPECT_THAT(MF
->getBlockNumbered(0)->instrs(),
73 ElementsAre(HasOpcode(X86::NOOP
), HasOpcode(X86::NOOP
),
74 HasOpcode(X86::NOOP
), HasOpcode(X86::RET64
)));
77 TEST_F(X86SnippetRepetitorTest
, Loop
) {
78 TestCommon(InstructionBenchmark::Loop
);
79 // Duplicating creates an entry block, a loop body and a ret block.
80 ASSERT_EQ(MF
->getNumBlockIDs(), 3u);
81 const auto &LoopBlock
= *MF
->getBlockNumbered(1);
82 EXPECT_THAT(LoopBlock
.instrs(),
83 ElementsAre(HasOpcode(X86::NOOP
), HasOpcode(X86::NOOP
),
84 HasOpcode(X86::NOOP
), HasOpcode(X86::NOOP
),
85 HasOpcode(X86::NOOP
), HasOpcode(X86::ADD64ri8
),
86 HasOpcode(X86::JCC_1
)));
87 EXPECT_THAT(LoopBlock
.liveins(),
90 LiveReg(State
.getExegesisTarget().getLoopCounterRegister(
91 State
.getTargetMachine().getTargetTriple()))));
92 EXPECT_THAT(MF
->getBlockNumbered(2)->instrs(),
93 ElementsAre(HasOpcode(X86::RET64
)));
97 } // namespace exegesis