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