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: 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 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 61 static auto HasOpcode = [](unsigned Opcode) { 62 return Property(&MachineInstr::getOpcode, Eq(Opcode)); 63 }; 64 65 static auto LiveReg = [](unsigned Reg) { 66 return Field(&MachineBasicBlock::RegisterMaskPair::PhysReg, Eq(Reg)); 67 }; 68 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 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