diff options
author | Clement Courbet <courbet@google.com> | 2019-09-27 12:56:24 +0000 |
---|---|---|
committer | Clement Courbet <courbet@google.com> | 2019-09-27 12:56:24 +0000 |
commit | 9431b72ce9e2dee9eddc71cff34f5fdaf853e9d4 (patch) | |
tree | 04653240b761a7a5ba76f0f3199bde02fe4fb208 /llvm/unittests/tools/llvm-exegesis | |
parent | d69fa737fff31a3d5d11d56117c20ca9794bb2a4 (diff) | |
download | bcm5719-llvm-9431b72ce9e2dee9eddc71cff34f5fdaf853e9d4.tar.gz bcm5719-llvm-9431b72ce9e2dee9eddc71cff34f5fdaf853e9d4.zip |
[llvm-exegesis] Add loop mode for repeating the snippet.
Summary:
Before this change the Executable function was made by duplicating the
snippet. This change adds a --repetion-mode={loop|duplicate} flag that
allows choosing between this behaviour and wrapping the snippet instructions
in a loop.
The new mode can help measurements when the snippet fits in the DSB by
short-cirtcuiting decoding. The loop adds a dec + jmp to the measurements, but
since these are not part of the critical path, they execute in parallel
with the measured code and do not impact measurements in practice.
Overview of the change:
- New SnippetRepetitor abstraction that handles repeating the snippet.
The assembler delegates repeating the instructions to this class.
- ExegesisTarget learns how to decrement loop counter and jump.
- Some refactoring of the assembler into FunctionFiller/BasicBlockFiller.
Reviewers: gchatelet
Subscribers: mgorny, tschuett, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D68125
llvm-svn: 373083
Diffstat (limited to 'llvm/unittests/tools/llvm-exegesis')
4 files changed, 121 insertions, 8 deletions
diff --git a/llvm/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h b/llvm/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h index fcbff940528..9a348e4e9de 100644 --- a/llvm/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h +++ b/llvm/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h @@ -43,12 +43,15 @@ protected: } template <class... Bs> - inline void Check(llvm::ArrayRef<RegisterValue> RegisterInitialValues, - llvm::MCInst MCInst, Bs... Bytes) { + inline void Check(ArrayRef<RegisterValue> RegisterInitialValues, MCInst Inst, + Bs... Bytes) { ExecutableFunction Function = - (MCInst.getOpcode() == 0) - ? assembleToFunction(RegisterInitialValues, {}) - : assembleToFunction(RegisterInitialValues, {MCInst}); + (Inst.getOpcode() == 0) + ? assembleToFunction(RegisterInitialValues, [](FunctionFiller &) {}) + : assembleToFunction(RegisterInitialValues, + [Inst](FunctionFiller &Filler) { + Filler.getEntry().addInstruction(Inst); + }); ASSERT_THAT(Function.getFunctionBytes().str(), testing::ElementsAre(Bytes...)); if (CanExecute) { @@ -73,11 +76,11 @@ private: ExecutableFunction assembleToFunction(llvm::ArrayRef<RegisterValue> RegisterInitialValues, - llvm::ArrayRef<llvm::MCInst> Instructions) { + FillFunction Fill) { llvm::SmallString<256> Buffer; llvm::raw_svector_ostream AsmStream(Buffer); assembleToStream(*ET, createTargetMachine(), /*LiveIns=*/{}, - RegisterInitialValues, Instructions, AsmStream); + RegisterInitialValues, Fill, AsmStream); return ExecutableFunction(createTargetMachine(), getObjectFromBuffer(AsmStream.str())); } diff --git a/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt b/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt index 88c38d0d7e8..bf50df389d8 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt +++ b/llvm/unittests/tools/llvm-exegesis/X86/CMakeLists.txt @@ -19,6 +19,7 @@ add_llvm_unittest(LLVMExegesisX86Tests RegisterAliasingTest.cpp SchedClassResolutionTest.cpp SnippetGeneratorTest.cpp + SnippetRepetitorTest.cpp TargetTest.cpp ) target_link_libraries(LLVMExegesisX86Tests PRIVATE diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp index 1c225bb6205..7e433785932 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp @@ -387,7 +387,9 @@ TEST_F(FakeSnippetGeneratorTest, MemoryUse_Movsb) { // - hasAliasingRegisters const unsigned Opcode = llvm::X86::MOVSB; const Instruction &Instr = State.getIC().getInstr(Opcode); - auto Error = Generator.generateConfigurations(Instr).takeError(); + auto Error = + Generator.generateConfigurations(Instr, State.getRATC().emptyRegisters()) + .takeError(); EXPECT_TRUE((bool)Error); llvm::consumeError(std::move(Error)); } diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp new file mode 100644 index 00000000000..3135da26878 --- /dev/null +++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp @@ -0,0 +1,107 @@ +//===-- SnippetRepetitorTest.cpp --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "../Common/AssemblerUtils.h" +#include "Latency.h" +#include "LlvmState.h" +#include "MCInstrDescView.h" +#include "RegisterAliasing.h" +#include "Uops.h" +#include "X86InstrInfo.h" +#include "llvm/CodeGen/MachineBasicBlock.h" + +namespace llvm { +namespace exegesis { + +void InitializeX86ExegesisTarget(); + +namespace { + +using testing::ElementsAre; +using testing::Eq; +using testing::Field; +using testing::Property; +using testing::UnorderedElementsAre; + +class X86SnippetRepetitorTest : public ::testing::Test { +protected: + X86SnippetRepetitorTest() : State("x86_64-unknown-linux", "haswell") {} + + static void SetUpTestCase() { + LLVMInitializeX86TargetInfo(); + LLVMInitializeX86TargetMC(); + LLVMInitializeX86Target(); + LLVMInitializeX86AsmPrinter(); + InitializeX86ExegesisTarget(); + } + + void SetUp() { + TM = State.createTargetMachine(); + Context = std::make_unique<LLVMContext>(); + Module = + std::make_unique<llvm::Module>("X86SnippetRepetitorTest", *Context); + Module->setDataLayout(TM->createDataLayout()); + MMI = std::make_unique<MachineModuleInfo>(TM.get()); + MF = &createVoidVoidPtrMachineFunction("TestFn", Module.get(), MMI.get()); + } + + void TestCommon(InstructionBenchmark::RepetitionModeE RepetitionMode) { + const auto Repetitor = SnippetRepetitor::Create(RepetitionMode, State); + const std::vector<MCInst> Instructions = {MCInstBuilder(X86::NOOP)}; + FunctionFiller Sink(*MF, {X86::EAX}); + const auto Fill = Repetitor->Repeat(Instructions, kMinInstructions); + Fill(Sink); + } + + static constexpr const unsigned kMinInstructions = 3; + + const LLVMState State; + std::unique_ptr<llvm::LLVMTargetMachine> TM; + std::unique_ptr<LLVMContext> Context; + std::unique_ptr<Module> Module; + std::unique_ptr<MachineModuleInfo> MMI; + MachineFunction *MF = nullptr; +}; + +static auto HasOpcode = [](unsigned Opcode) { + return Property(&MachineInstr::getOpcode, Eq(Opcode)); +}; + +static auto LiveReg = [](unsigned Reg) { + return Field(&MachineBasicBlock::RegisterMaskPair::PhysReg, Eq(Reg)); +}; + +TEST_F(X86SnippetRepetitorTest, Duplicate) { + TestCommon(InstructionBenchmark::Duplicate); + // Duplicating creates a single basic block that repeats the instructions. + ASSERT_EQ(MF->getNumBlockIDs(), 1u); + EXPECT_THAT(MF->getBlockNumbered(0)->instrs(), + ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::NOOP), + HasOpcode(X86::NOOP), HasOpcode(X86::RETQ))); +} + +TEST_F(X86SnippetRepetitorTest, Loop) { + TestCommon(InstructionBenchmark::Loop); + // Duplicating creates an entry block, a loop body and a ret block. + ASSERT_EQ(MF->getNumBlockIDs(), 3u); + const auto &LoopBlock = *MF->getBlockNumbered(1); + EXPECT_THAT(LoopBlock.instrs(), + ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::ADD64ri8), + HasOpcode(X86::JCC_1))); + EXPECT_THAT(LoopBlock.liveins(), + UnorderedElementsAre( + LiveReg(X86::EAX), + LiveReg(State.getExegesisTarget().getLoopCounterRegister( + State.getTargetMachine().getTargetTriple())))); + EXPECT_THAT(MF->getBlockNumbered(2)->instrs(), + ElementsAre(HasOpcode(X86::RETQ))); +} + +} // namespace +} // namespace exegesis +} // namespace llvm |