From 2b31a673de51061d0407b79127054a5083659efc Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Fri, 19 Jan 2024 11:34:16 -0800 Subject: [PATCH] [llvm-exegesis] Make duplicate snippet repetitor produce whole snippets (#77224) Currently, the duplicate snippet repetitor will truncate snippets that do not exactly divide the minimum number of instructions. This patch corrects that behavior by making the duplicate snippet repetitor duplicate the snippet in its entirety until the minimum number of instructions has been reached. This makes the behavior consistent with the loop snippet repetitor, which will execute at least `--num-repetitions` (soon to be renamed `--min-instructions`) instructions. --- .../llvm-exegesis/lib/SnippetRepetitor.cpp | 8 ++++---- .../llvm-exegesis/X86/SnippetRepetitorTest.cpp | 18 ++++++++++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp b/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp index 1872f550c3f31..c1660c2d4a1b8 100644 --- a/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp +++ b/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp @@ -30,10 +30,10 @@ class DuplicateSnippetRepetitor : public SnippetRepetitor { CleanupMemory](FunctionFiller &Filler) { auto Entry = Filler.getEntry(); if (!Instructions.empty()) { - // Add the whole snippet at least once. - Entry.addInstructions(Instructions); - for (unsigned I = Instructions.size(); I < MinInstructions; ++I) { - Entry.addInstruction(Instructions[I % Instructions.size()]); + const unsigned NumRepetitions = + divideCeil(MinInstructions, Instructions.size()); + for (unsigned I = 0; I < NumRepetitions; ++I) { + Entry.addInstructions(Instructions); } } Entry.addReturn(State.getExegesisTarget(), CleanupMemory); diff --git a/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp b/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp index d2382ec0cddc4..25e8836087c15 100644 --- a/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp +++ b/llvm/unittests/tools/llvm-exegesis/X86/SnippetRepetitorTest.cpp @@ -38,9 +38,11 @@ class X86SnippetRepetitorTest : public X86TestBase { MF = &createVoidVoidPtrMachineFunction("TestFn", Mod.get(), MMI.get()); } - void TestCommon(Benchmark::RepetitionModeE RepetitionMode) { + void TestCommon(Benchmark::RepetitionModeE RepetitionMode, + unsigned SnippetInstructions = 1) { const auto Repetitor = SnippetRepetitor::Create(RepetitionMode, State); - const std::vector Instructions = {MCInstBuilder(X86::NOOP)}; + const std::vector Instructions(SnippetInstructions, + MCInstBuilder(X86::NOOP)); FunctionFiller Sink(*MF, {X86::EAX}); const auto Fill = Repetitor->Repeat(Instructions, kMinInstructions, kLoopBodySize, false); @@ -74,6 +76,18 @@ TEST_F(X86SnippetRepetitorTest, Duplicate) { HasOpcode(X86::NOOP), HasOpcode(X86::RET64))); } +TEST_F(X86SnippetRepetitorTest, DuplicateSnippetInstructionCount) { + TestCommon(Benchmark::Duplicate, 2); + // Duplicating a snippet of two instructions with the minimum number of + // instructions set to three duplicates the snippet twice for a total of + // four instructions. + ASSERT_EQ(MF->getNumBlockIDs(), 1u); + EXPECT_THAT(MF->getBlockNumbered(0)->instrs(), + ElementsAre(HasOpcode(X86::NOOP), HasOpcode(X86::NOOP), + HasOpcode(X86::NOOP), HasOpcode(X86::NOOP), + HasOpcode(X86::RET64))); +} + TEST_F(X86SnippetRepetitorTest, Loop) { TestCommon(Benchmark::Loop); // Duplicating creates an entry block, a loop body and a ret block.