From b1a67b7972a83cd1bc4a8bbede1e117d013c667b Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:00:10 +0300 Subject: [PATCH 01/32] Added interface to customize individual instructions and possibility to change latency via special comments * Added customizations to header * Added customization to implementation * Use default small vector size for custom instructions * Typo fixed * Use std::vector for custom descriptors * Revert to SmallVector * Erroneous dereference removed * Introduced annotated instructions * Updated getter method * Updated getter usage * Fixed type usage * Revert to MCInst for regions * Keep annotations in separate map * Removed usage of annotated instruction * Use std::optional * Add setter/getter for explicit latency * Set instruction latency according to annotation * Simplify default return * Revert to explicit default value * Add missing brace * Added missing field name * Typo fixed * Added missing namespace tags * Whitespace removed * Index annotations by smloc * Search latency by SMLoc * Use pointer as a map key * Missing const added * Added optional annotation to MCStreamerWrapper * Added interface to annotate instructions * Move annotations to CodeRegons * Get explicit latency from Regions * Erroneous dereference removed * Add interface to pass latency to MCStreamerWrapper * Fixed incorrect code placement * Make Streamer available to CommentConsumer * Move MCStreamerWrapper definition to make it visible in comment consumers * Parse latency comment * Fix drop_front usage * Fix whitespace skipping on latency annotation * Added test for latency annotation * Additional test for latency annotations * Use load in test instruction * Use load in test instruction * Added instruction builder customization * Added customized instruction creation * Pass builder to custom creation functor * Added header with InstrBuilder declaration * Typo fixed * Added base for instruction customizations test * Added missing result object * Hardcode name for summary view * Explicitly model single instruction * Add actual custom latency test * Typo fixed * Pass latency to lambda body * Adding missing const * Specify lambda return type * Erroneous argument removed * Removed unnecessary lambda return type * Code cleanup * Code cleanup --- llvm/include/llvm/MCA/InstrBuilder.h | 11 ++- llvm/lib/MCA/InstrBuilder.cpp | 15 +++- .../tools/llvm-mca/X86/llvm-mca-markers-13.s | 10 +++ .../tools/llvm-mca/X86/llvm-mca-markers-14.s | 10 +++ llvm/tools/llvm-mca/CodeRegion.h | 18 ++++ llvm/tools/llvm-mca/CodeRegionGenerator.cpp | 12 +++ llvm/tools/llvm-mca/CodeRegionGenerator.h | 85 +++++++++++-------- llvm/tools/llvm-mca/llvm-mca.cpp | 6 +- llvm/unittests/tools/llvm-mca/MCATestBase.cpp | 5 +- llvm/unittests/tools/llvm-mca/MCATestBase.h | 7 +- .../tools/llvm-mca/X86/TestIncrementalMCA.cpp | 26 ++++++ 11 files changed, 159 insertions(+), 46 deletions(-) create mode 100644 llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s create mode 100644 llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s diff --git a/llvm/include/llvm/MCA/InstrBuilder.h b/llvm/include/llvm/MCA/InstrBuilder.h index e0949d975fa99..9bb8c5b28fdad 100644 --- a/llvm/include/llvm/MCA/InstrBuilder.h +++ b/llvm/include/llvm/MCA/InstrBuilder.h @@ -25,6 +25,7 @@ #include "llvm/MCA/Support.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" +#include namespace llvm { namespace mca { @@ -78,6 +79,10 @@ class InstrBuilder { DenseMap, std::unique_ptr> VariantDescriptors; + // These descriptors are customized for particular instructions and cannot + // be reused + SmallVector> CustomDescriptors; + bool FirstCallInst; bool FirstReturnInst; unsigned CallLatency; @@ -87,7 +92,8 @@ class InstrBuilder { Expected getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID); Expected - createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec); + createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec, + std::function Customizer = {}); Expected getOrCreateInstrDesc(const MCInst &MCI, const SmallVector &IVec); @@ -116,7 +122,8 @@ class InstrBuilder { void setInstRecycleCallback(InstRecycleCallback CB) { InstRecycleCB = CB; } LLVM_ABI Expected> - createInstruction(const MCInst &MCI, const SmallVector &IVec); + createInstruction(const MCInst &MCI, const SmallVector &IVec, + std::function Customizer = {}); }; } // namespace mca } // namespace llvm diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp index cad25a6ddd3f5..4a0f09c4160d9 100644 --- a/llvm/lib/MCA/InstrBuilder.cpp +++ b/llvm/lib/MCA/InstrBuilder.cpp @@ -558,7 +558,8 @@ Expected InstrBuilder::getVariantSchedClassID(const MCInst &MCI, Expected InstrBuilder::createInstrDescImpl(const MCInst &MCI, - const SmallVector &IVec) { + const SmallVector &IVec, + std::function Customizer) { assert(STI.getSchedModel().hasInstrSchedModel() && "Itineraries are not yet supported!"); @@ -632,6 +633,12 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI, return std::move(Err); // Now add the new descriptor. + + if (Customizer) { + Customizer(*ID); + return *CustomDescriptors.emplace_back(std::move(ID)); + } + bool IsVariadic = MCDesc.isVariadic(); if ((ID->IsRecyclable = !IsVariadic && !IsVariant)) { auto DKey = std::make_pair(MCI.getOpcode(), SchedClassID); @@ -675,8 +682,10 @@ STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc"); Expected> InstrBuilder::createInstruction(const MCInst &MCI, - const SmallVector &IVec) { - Expected DescOrErr = getOrCreateInstrDesc(MCI, IVec); + const SmallVector &IVec, + std::function Customizer) { + Expected DescOrErr = Customizer? createInstrDescImpl(MCI, IVec, Customizer) : + getOrCreateInstrDesc(MCI, IVec); if (!DescOrErr) return DescOrErr.takeError(); const InstrDesc &D = *DescOrErr; diff --git a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s new file mode 100644 index 0000000000000..9115ffadbdaee --- /dev/null +++ b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s @@ -0,0 +1,10 @@ +# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=10 %s 2>&1 | FileCheck %s + +add (%eax), %eax // LLVM-MCA-LATENCY : 100 +mov %eax, (%ebx) + +# CHECK: Iterations: 10 +# CHECK-NEXT: Instructions: 20 +# CHECK-NEXT: Total Cycles: 1004 +# CHECK-NEXT: Total uOps: 20 diff --git a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s new file mode 100644 index 0000000000000..41da9f4b4cef1 --- /dev/null +++ b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s @@ -0,0 +1,10 @@ +# NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=10 %s 2>&1 | FileCheck %s + +add (%eax), %eax // LLVM-MCA-LATENCY : 100 +mov %eax, (%ebx) // LLVM-MCA-LATENCY : 100 + +# CHECK: Iterations: 10 +# CHECK-NEXT: Instructions: 20 +# CHECK-NEXT: Total Cycles: 1103 +# CHECK-NEXT: Total uOps: 20 diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h index c04ea51169cfb..d16f976fe101e 100644 --- a/llvm/tools/llvm-mca/CodeRegion.h +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -69,10 +69,15 @@ #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" #include +#include namespace llvm { namespace mca { +struct InstAnnotation { + std::optional Latency; +}; + /// A region of assembly code. /// /// It identifies a sequence of machine instructions. @@ -155,6 +160,9 @@ class CodeRegions { llvm::StringMap ActiveRegions; bool FoundErrors; + // Annotations specified in comments, indexed by SMLoc value + llvm::DenseMap Annotations; + public: CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {} virtual ~CodeRegions() = default; @@ -170,6 +178,16 @@ class CodeRegions { void addInstruction(const llvm::MCInst &Instruction); llvm::SourceMgr &getSourceMgr() const { return SM; } + void Annotate(llvm::SMLoc Loc, const InstAnnotation& A) { Annotations[Loc.getPointer()] = A; } + std::optional getExplicitLatency(llvm::SMLoc Loc) const { + const auto It = Annotations.find(Loc.getPointer()); + if (It != Annotations.end()) { + return It->second.Latency; + } else { + return {}; + } + } + llvm::ArrayRef getInstructionSequence(unsigned Idx) const { return Regions[Idx]->getInstructions(); } diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp index f7f929e49ead9..767f92bf6f935 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp @@ -95,6 +95,18 @@ void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc, return; Comment = Comment.drop_front(Position); + if (Comment.starts_with("LLVM-MCA-LATENCY")) { + auto Parts = Comment.split(':'); + Position = Parts.second.find_first_not_of(" \t"); + if (Position >= Parts.second.size()) + return; + auto LatStr = Parts.second.drop_front(Position); + unsigned Latency = 0; + if (!LatStr.getAsInteger(10, Latency)) + Streamer.AddLatencyAnnotation(Latency); + return; + } + if (Comment.consume_front("LLVM-MCA-END")) { // Skip spaces and tabs. Position = Comment.find_first_not_of(" \t"); diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.h b/llvm/tools/llvm-mca/CodeRegionGenerator.h index a48c67a22f27b..2c632be5e7f53 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.h +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.h @@ -31,6 +31,50 @@ namespace llvm { namespace mca { +// This class provides the callbacks that occur when parsing input assembly. +class MCStreamerWrapper : public MCStreamer { +protected: + CodeRegions &Regions; + std::optional CurrentAnnotation; + +public: + MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R) + : MCStreamer(Context), Regions(R) {} + + // We only want to intercept the emission of new instructions. + void emitInstruction(const MCInst &Inst, + const MCSubtargetInfo & /* unused */) override { + Regions.addInstruction(Inst); + if (CurrentAnnotation) { + Regions.Annotate(Inst.getLoc(), *CurrentAnnotation); + CurrentAnnotation = {}; + } + } + + void AddLatencyAnnotation(unsigned Lat) { + if (!CurrentAnnotation) CurrentAnnotation = InstAnnotation(); + CurrentAnnotation->Latency = Lat; + } + + bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { + return true; + } + + void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + Align ByteAlignment) override {} + void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, Align ByteAlignment = Align(1), + SMLoc Loc = SMLoc()) override {} + void beginCOFFSymbolDef(const MCSymbol *Symbol) override {} + void emitCOFFSymbolStorageClass(int StorageClass) override {} + void emitCOFFSymbolType(int Type) override {} + void endCOFFSymbolDef() override {} + + ArrayRef GetInstructionSequence(unsigned Index) const { + return Regions.getInstructionSequence(Index); + } +}; + class MCACommentConsumer : public AsmCommentConsumer { protected: bool FoundError = false; @@ -44,9 +88,10 @@ class MCACommentConsumer : public AsmCommentConsumer { /// A comment consumer that parses strings. The only valid tokens are strings. class AnalysisRegionCommentConsumer : public MCACommentConsumer { AnalysisRegions &Regions; + MCStreamerWrapper &Streamer; public: - AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {} + AnalysisRegionCommentConsumer(AnalysisRegions &R, MCStreamerWrapper &S) : Regions(R), Streamer(S) {} /// Parses a comment. It begins a new region if it is of the form /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END. @@ -82,40 +127,6 @@ class InstrumentRegionCommentConsumer : public MCACommentConsumer { InstrumentManager &getInstrumentManager() { return IM; } }; -// This class provides the callbacks that occur when parsing input assembly. -class MCStreamerWrapper : public MCStreamer { -protected: - CodeRegions &Regions; - -public: - MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R) - : MCStreamer(Context), Regions(R) {} - - // We only want to intercept the emission of new instructions. - void emitInstruction(const MCInst &Inst, - const MCSubtargetInfo & /* unused */) override { - Regions.addInstruction(Inst); - } - - bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { - return true; - } - - void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - Align ByteAlignment) override {} - void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, Align ByteAlignment = Align(1), - SMLoc Loc = SMLoc()) override {} - void beginCOFFSymbolDef(const MCSymbol *Symbol) override {} - void emitCOFFSymbolStorageClass(int StorageClass) override {} - void emitCOFFSymbolType(int Type) override {} - void endCOFFSymbolDef() override {} - - ArrayRef GetInstructionSequence(unsigned Index) const { - return Regions.getInstructionSequence(Index); - } -}; - class InstrumentMCStreamer : public MCStreamerWrapper { InstrumentManager &IM; @@ -210,15 +221,15 @@ class AsmCodeRegionGenerator : public virtual CodeRegionGenerator { class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator, public AsmCodeRegionGenerator { - AnalysisRegionCommentConsumer CC; MCStreamerWrapper Streamer; + AnalysisRegionCommentConsumer CC; public: AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C, const MCAsmInfo &A, const MCSubtargetInfo &S, const MCInstrInfo &I) : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I), - CC(Regions), Streamer(Ctx, Regions) {} + Streamer(Ctx, Regions), CC(Regions, Streamer) {} MCACommentConsumer *getCommentConsumer() override { return &CC; }; CodeRegions &getRegions() override { return Regions; }; diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 4b0611186d21f..5f653ffcd83ed 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -633,7 +633,11 @@ int main(int argc, char **argv) { const SmallVector Instruments = InstrumentRegions.getActiveInstruments(Loc); - Expected> Inst = + auto Latency = Regions.getExplicitLatency(Loc); + Expected> Inst = Latency ? + IB.createInstruction(MCI, Instruments, [=](llvm::mca::InstrDesc& ID) { + for (auto& W : ID.Writes) W.Latency = *Latency; + ID.MaxLatency = *Latency; }) : IB.createInstruction(MCI, Instruments); if (!Inst) { if (auto NewE = handleErrors( diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp index cd3258ef96d64..96413168b8f5e 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp @@ -61,7 +61,8 @@ void MCATestBase::SetUp() { Error MCATestBase::runBaselineMCA(json::Object &Result, ArrayRef Insts, ArrayRef Views, - const mca::PipelineOptions *PO) { + const mca::PipelineOptions *PO, + Builder B) { mca::Context MCA(*MRI, *STI); // Default InstrumentManager @@ -72,7 +73,7 @@ Error MCATestBase::runBaselineMCA(json::Object &Result, ArrayRef Insts, SmallVector> LoweredInsts; for (const auto &MCI : Insts) { Expected> Inst = - IB.createInstruction(MCI, Instruments); + B ? B(IB, MCI, Instruments) : IB.createInstruction(MCI, Instruments); if (!Inst) { if (auto NewE = handleErrors(Inst.takeError(), diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.h b/llvm/unittests/tools/llvm-mca/MCATestBase.h index 66e20a45c96ce..399a8e892bc28 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.h +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.h @@ -24,6 +24,7 @@ #include "llvm/MC/MCTargetOptions.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/MCA/Context.h" +#include "llvm/MCA/InstrBuilder.h" #include "llvm/TargetParser/SubtargetFeature.h" #include "llvm/TargetParser/Triple.h" @@ -70,12 +71,16 @@ class MCATestBase : public ::testing::Test { void SetUp() override; + using Builder = std::function> + (mca::InstrBuilder&, const MCInst&, const SmallVector&)>; + /// Utility function to run MCA with (nearly) the same configuration as the /// `llvm-mca` tool to verify result correctness. /// This function only displays on SummaryView by default. virtual Error runBaselineMCA(json::Object &Result, ArrayRef Insts, ArrayRef Views = {}, - const mca::PipelineOptions *PO = nullptr); + const mca::PipelineOptions *PO = nullptr, + Builder B = {}); }; } // end namespace mca diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 1a14c687295ca..cf66460b11fc8 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -234,3 +234,29 @@ TEST_F(X86TestBase, TestVariantInstructionsSameAddress) { Expected Cycles = P->run(); ASSERT_TRUE(static_cast(Cycles)); } + +TEST_F(X86TestBase, TestInstructionCustomization) { + const unsigned ExplicitLatency = 100; + SmallVector MCIs; + MCInst InstructionToAdd = MCInstBuilder(X86::XOR64rr) + .addReg(X86::RAX) + .addReg(X86::RAX) + .addReg(X86::RAX); + MCIs.push_back(InstructionToAdd); + + // Run the baseline. + json::Object BaselineResult; + auto E = runBaselineMCA(BaselineResult, MCIs, {}, nullptr, + [=](InstrBuilder& IB, const MCInst& MCI, const SmallVector& Instruments) { + return IB.createInstruction(MCI, Instruments, + [=](InstrDesc& ID) { + for (auto& W : ID.Writes) W.Latency = ExplicitLatency; + ID.MaxLatency = ExplicitLatency; + }); + }); + auto *BaselineObj = BaselineResult.getObject("SummaryView"); + auto V = BaselineObj->getInteger("TotalCycles"); + ASSERT_TRUE(V); + // Additional 3 cycles for Dispatch, Executed and Retired states + ASSERT_EQ(unsigned(*V), ExplicitLatency + 3) << "Total cycles do not match"; +} From 4abee0f229ed6859ed9f0f86662a75f34d788664 Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:28:21 +0300 Subject: [PATCH 02/32] Fix formatting --- llvm/include/llvm/MCA/InstrBuilder.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/MCA/InstrBuilder.h b/llvm/include/llvm/MCA/InstrBuilder.h index 9bb8c5b28fdad..7b2fbde2c4a0e 100644 --- a/llvm/include/llvm/MCA/InstrBuilder.h +++ b/llvm/include/llvm/MCA/InstrBuilder.h @@ -93,7 +93,7 @@ class InstrBuilder { Expected getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID); Expected createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer = {}); + std::function Customizer = {}); Expected getOrCreateInstrDesc(const MCInst &MCI, const SmallVector &IVec); @@ -123,7 +123,7 @@ class InstrBuilder { LLVM_ABI Expected> createInstruction(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer = {}); + std::function Customizer = {}); }; } // namespace mca } // namespace llvm From 1298dd3391061b66c57bd69b58a44894f001f4fe Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:31:59 +0300 Subject: [PATCH 03/32] Fix formatting --- llvm/lib/MCA/InstrBuilder.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp index 4a0f09c4160d9..8b3e52a871f71 100644 --- a/llvm/lib/MCA/InstrBuilder.cpp +++ b/llvm/lib/MCA/InstrBuilder.cpp @@ -559,7 +559,7 @@ Expected InstrBuilder::getVariantSchedClassID(const MCInst &MCI, Expected InstrBuilder::createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer) { + std::function Customizer) { assert(STI.getSchedModel().hasInstrSchedModel() && "Itineraries are not yet supported!"); @@ -638,7 +638,7 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI, Customizer(*ID); return *CustomDescriptors.emplace_back(std::move(ID)); } - + bool IsVariadic = MCDesc.isVariadic(); if ((ID->IsRecyclable = !IsVariadic && !IsVariant)) { auto DKey = std::make_pair(MCI.getOpcode(), SchedClassID); @@ -683,9 +683,10 @@ STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc"); Expected> InstrBuilder::createInstruction(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer) { - Expected DescOrErr = Customizer? createInstrDescImpl(MCI, IVec, Customizer) : - getOrCreateInstrDesc(MCI, IVec); + std::function Customizer) { + Expected DescOrErr = + Customizer ? createInstrDescImpl(MCI, IVec, Customizer) + : getOrCreateInstrDesc(MCI, IVec); if (!DescOrErr) return DescOrErr.takeError(); const InstrDesc &D = *DescOrErr; From b5c3b952f9295d3ed4e493d2d3d2dd6c88a5adf2 Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:35:46 +0300 Subject: [PATCH 04/32] Fix formatting --- llvm/tools/llvm-mca/CodeRegion.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h index d16f976fe101e..0b5385a6d7ad1 100644 --- a/llvm/tools/llvm-mca/CodeRegion.h +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -68,8 +68,8 @@ #include "llvm/Support/Error.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" -#include #include +#include namespace llvm { namespace mca { @@ -161,7 +161,7 @@ class CodeRegions { bool FoundErrors; // Annotations specified in comments, indexed by SMLoc value - llvm::DenseMap Annotations; + llvm::DenseMap Annotations; public: CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {} @@ -178,7 +178,9 @@ class CodeRegions { void addInstruction(const llvm::MCInst &Instruction); llvm::SourceMgr &getSourceMgr() const { return SM; } - void Annotate(llvm::SMLoc Loc, const InstAnnotation& A) { Annotations[Loc.getPointer()] = A; } + void Annotate(llvm::SMLoc Loc, const InstAnnotation& A) { + Annotations[Loc.getPointer()] = A; + } std::optional getExplicitLatency(llvm::SMLoc Loc) const { const auto It = Annotations.find(Loc.getPointer()); if (It != Annotations.end()) { From 302b994407840ae4a4039ce5cbb25de7edf7d2f5 Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:37:17 +0300 Subject: [PATCH 05/32] Fix formatting --- llvm/tools/llvm-mca/CodeRegionGenerator.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp index 767f92bf6f935..0d400760f17e1 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp @@ -96,15 +96,15 @@ void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc, Comment = Comment.drop_front(Position); if (Comment.starts_with("LLVM-MCA-LATENCY")) { - auto Parts = Comment.split(':'); - Position = Parts.second.find_first_not_of(" \t"); - if (Position >= Parts.second.size()) - return; - auto LatStr = Parts.second.drop_front(Position); - unsigned Latency = 0; - if (!LatStr.getAsInteger(10, Latency)) - Streamer.AddLatencyAnnotation(Latency); + auto Parts = Comment.split(':'); + Position = Parts.second.find_first_not_of(" \t"); + if (Position >= Parts.second.size()) return; + auto LatStr = Parts.second.drop_front(Position); + unsigned Latency = 0; + if (!LatStr.getAsInteger(10, Latency)) + Streamer.AddLatencyAnnotation(Latency); + return; } if (Comment.consume_front("LLVM-MCA-END")) { From 23389785357f8cf7a11ce7050cf8904eb4915db2 Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:39:13 +0300 Subject: [PATCH 06/32] Fix formatting --- llvm/tools/llvm-mca/CodeRegionGenerator.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.h b/llvm/tools/llvm-mca/CodeRegionGenerator.h index 2c632be5e7f53..1f43a8b26c471 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.h +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.h @@ -52,7 +52,8 @@ class MCStreamerWrapper : public MCStreamer { } void AddLatencyAnnotation(unsigned Lat) { - if (!CurrentAnnotation) CurrentAnnotation = InstAnnotation(); + if (!CurrentAnnotation) + CurrentAnnotation = InstAnnotation(); CurrentAnnotation->Latency = Lat; } @@ -91,7 +92,8 @@ class AnalysisRegionCommentConsumer : public MCACommentConsumer { MCStreamerWrapper &Streamer; public: - AnalysisRegionCommentConsumer(AnalysisRegions &R, MCStreamerWrapper &S) : Regions(R), Streamer(S) {} + AnalysisRegionCommentConsumer(AnalysisRegions &R, MCStreamerWrapper &S) + : Regions(R), Streamer(S) {} /// Parses a comment. It begins a new region if it is of the form /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END. From 0be9fbf1719caf78d8db77d3c26249ee30dc2e3a Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:41:47 +0300 Subject: [PATCH 07/32] Fix formatting --- llvm/tools/llvm-mca/llvm-mca.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 5f653ffcd83ed..902a603a8e7dc 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -634,11 +634,14 @@ int main(int argc, char **argv) { InstrumentRegions.getActiveInstruments(Loc); auto Latency = Regions.getExplicitLatency(Loc); - Expected> Inst = Latency ? - IB.createInstruction(MCI, Instruments, [=](llvm::mca::InstrDesc& ID) { - for (auto& W : ID.Writes) W.Latency = *Latency; - ID.MaxLatency = *Latency; }) : - IB.createInstruction(MCI, Instruments); + Expected> Inst = + Latency ? IB.createInstruction(MCI, Instruments, + [=](llvm::mca::InstrDesc& ID) { + for (auto& W : ID.Writes) + W.Latency = *Latency; + ID.MaxLatency = *Latency; + }) + : IB.createInstruction(MCI, Instruments); if (!Inst) { if (auto NewE = handleErrors( Inst.takeError(), From f1ad060d678b53d1bdd4a6c0659bbfb0764d9cfb Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:43:15 +0300 Subject: [PATCH 08/32] Fix formatting --- llvm/unittests/tools/llvm-mca/MCATestBase.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp index 96413168b8f5e..e2ff1dbe73a49 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp @@ -61,8 +61,7 @@ void MCATestBase::SetUp() { Error MCATestBase::runBaselineMCA(json::Object &Result, ArrayRef Insts, ArrayRef Views, - const mca::PipelineOptions *PO, - Builder B) { + const mca::PipelineOptions *PO, Builder B) { mca::Context MCA(*MRI, *STI); // Default InstrumentManager From 757fec3e279200fe3d7a9abdded8b412fbec9ac5 Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:44:43 +0300 Subject: [PATCH 09/32] Fix formatting --- llvm/unittests/tools/llvm-mca/MCATestBase.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.h b/llvm/unittests/tools/llvm-mca/MCATestBase.h index 399a8e892bc28..557da7b3d0d05 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.h +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.h @@ -71,8 +71,9 @@ class MCATestBase : public ::testing::Test { void SetUp() override; - using Builder = std::function> - (mca::InstrBuilder&, const MCInst&, const SmallVector&)>; + using Builder = std::function>( + mca::InstrBuilder&, const MCInst&, + const SmallVector &)>; /// Utility function to run MCA with (nearly) the same configuration as the /// `llvm-mca` tool to verify result correctness. From 452bb402949d7c427417d88d96c5ed220237a300 Mon Sep 17 00:00:00 2001 From: Roman Belenov <103195329+r-belenov@users.noreply.github.com> Date: Tue, 26 Aug 2025 17:47:02 +0300 Subject: [PATCH 10/32] Fix formatting --- .../tools/llvm-mca/X86/TestIncrementalMCA.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index cf66460b11fc8..8aa879b3e053d 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -236,7 +236,7 @@ TEST_F(X86TestBase, TestVariantInstructionsSameAddress) { } TEST_F(X86TestBase, TestInstructionCustomization) { - const unsigned ExplicitLatency = 100; + const unsigned ExplicitLatency = 100; SmallVector MCIs; MCInst InstructionToAdd = MCInstBuilder(X86::XOR64rr) .addReg(X86::RAX) @@ -247,13 +247,15 @@ TEST_F(X86TestBase, TestInstructionCustomization) { // Run the baseline. json::Object BaselineResult; auto E = runBaselineMCA(BaselineResult, MCIs, {}, nullptr, - [=](InstrBuilder& IB, const MCInst& MCI, const SmallVector& Instruments) { - return IB.createInstruction(MCI, Instruments, - [=](InstrDesc& ID) { - for (auto& W : ID.Writes) W.Latency = ExplicitLatency; - ID.MaxLatency = ExplicitLatency; - }); - }); + [=](InstrBuilder &IB, const MCInst &MCI, + const SmallVector &Instruments) { + return IB.createInstruction( + MCI, Instruments, [=](InstrDesc &ID) { + for (auto &W : ID.Writes) + W.Latency = ExplicitLatency; + ID.MaxLatency = ExplicitLatency; + }); + }); auto *BaselineObj = BaselineResult.getObject("SummaryView"); auto V = BaselineObj->getInteger("TotalCycles"); ASSERT_TRUE(V); From 4d655f875362cbae9fc17febfa78fc874a168c86 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Tue, 26 Aug 2025 17:51:49 +0300 Subject: [PATCH 11/32] Fix formatting --- llvm/tools/llvm-mca/CodeRegion.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h index 0b5385a6d7ad1..52c0854779be6 100644 --- a/llvm/tools/llvm-mca/CodeRegion.h +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -178,7 +178,7 @@ class CodeRegions { void addInstruction(const llvm::MCInst &Instruction); llvm::SourceMgr &getSourceMgr() const { return SM; } - void Annotate(llvm::SMLoc Loc, const InstAnnotation& A) { + void Annotate(llvm::SMLoc Loc, const InstAnnotation &A) { Annotations[Loc.getPointer()] = A; } std::optional getExplicitLatency(llvm::SMLoc Loc) const { From ef2a0f0106358ee44d1a036e8b6cf2ab6fc50179 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Tue, 26 Aug 2025 17:52:56 +0300 Subject: [PATCH 12/32] Fix formatting --- llvm/tools/llvm-mca/llvm-mca.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 902a603a8e7dc..73ac11794154f 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -636,8 +636,8 @@ int main(int argc, char **argv) { auto Latency = Regions.getExplicitLatency(Loc); Expected> Inst = Latency ? IB.createInstruction(MCI, Instruments, - [=](llvm::mca::InstrDesc& ID) { - for (auto& W : ID.Writes) + [=](llvm::mca::InstrDesc &ID) { + for (auto &W : ID.Writes) W.Latency = *Latency; ID.MaxLatency = *Latency; }) From 77eefdbeefd5f004d9b7c304e963fe44d65549b4 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Tue, 26 Aug 2025 17:54:25 +0300 Subject: [PATCH 13/32] Fix formatting --- llvm/unittests/tools/llvm-mca/MCATestBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.h b/llvm/unittests/tools/llvm-mca/MCATestBase.h index 557da7b3d0d05..e991252cd3efd 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.h +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.h @@ -72,7 +72,7 @@ class MCATestBase : public ::testing::Test { void SetUp() override; using Builder = std::function>( - mca::InstrBuilder&, const MCInst&, + mca::InstrBuilder &, const MCInst &, const SmallVector &)>; /// Utility function to run MCA with (nearly) the same configuration as the From 6e0d12b6aa58c9608b677da571781157e07bb4af Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Wed, 27 Aug 2025 07:59:05 +0300 Subject: [PATCH 14/32] Using function_ref to pass function arguments * Switch to function_ref * Switch to function_ref * Check pipeline execution status * Switch to function_ref --- llvm/include/llvm/MCA/InstrBuilder.h | 4 ++-- llvm/lib/MCA/InstrBuilder.cpp | 4 ++-- llvm/unittests/tools/llvm-mca/MCATestBase.h | 2 +- llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp | 1 + 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/MCA/InstrBuilder.h b/llvm/include/llvm/MCA/InstrBuilder.h index 7b2fbde2c4a0e..6779d27dcca3a 100644 --- a/llvm/include/llvm/MCA/InstrBuilder.h +++ b/llvm/include/llvm/MCA/InstrBuilder.h @@ -93,7 +93,7 @@ class InstrBuilder { Expected getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID); Expected createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer = {}); + function_ref Customizer = {}); Expected getOrCreateInstrDesc(const MCInst &MCI, const SmallVector &IVec); @@ -123,7 +123,7 @@ class InstrBuilder { LLVM_ABI Expected> createInstruction(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer = {}); + function_ref Customizer = {}); }; } // namespace mca } // namespace llvm diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp index 8b3e52a871f71..f65145b4203c0 100644 --- a/llvm/lib/MCA/InstrBuilder.cpp +++ b/llvm/lib/MCA/InstrBuilder.cpp @@ -559,7 +559,7 @@ Expected InstrBuilder::getVariantSchedClassID(const MCInst &MCI, Expected InstrBuilder::createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer) { + function_ref Customizer) { assert(STI.getSchedModel().hasInstrSchedModel() && "Itineraries are not yet supported!"); @@ -683,7 +683,7 @@ STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc"); Expected> InstrBuilder::createInstruction(const MCInst &MCI, const SmallVector &IVec, - std::function Customizer) { + function_ref Customizer) { Expected DescOrErr = Customizer ? createInstrDescImpl(MCI, IVec, Customizer) : getOrCreateInstrDesc(MCI, IVec); diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.h b/llvm/unittests/tools/llvm-mca/MCATestBase.h index e991252cd3efd..c741d1f90c7f0 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.h +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.h @@ -71,7 +71,7 @@ class MCATestBase : public ::testing::Test { void SetUp() override; - using Builder = std::function>( + using Builder = function_ref>( mca::InstrBuilder &, const MCInst &, const SmallVector &)>; diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 8aa879b3e053d..668afd1a8d6be 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -256,6 +256,7 @@ TEST_F(X86TestBase, TestInstructionCustomization) { ID.MaxLatency = ExplicitLatency; }); }); + ASSERT_FALSE(bool(E)) << "Failed to run baseline"; auto *BaselineObj = BaselineResult.getObject("SummaryView"); auto V = BaselineObj->getInteger("TotalCycles"); ASSERT_TRUE(V); From 08cc266db1c57e7d06d7a3f3374d52239e0c1f73 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Wed, 27 Aug 2025 16:59:23 +0300 Subject: [PATCH 15/32] Use InstrumentManager to customize instructions Extended InstrumentManager to allow InstrDesc modification with instruments; added common instrument that can modify instruction latencies. --- llvm/include/llvm/MCA/CustomBehaviour.h | 25 +++++- llvm/include/llvm/MCA/InstrBuilder.h | 6 +- llvm/lib/MCA/CustomBehaviour.cpp | 72 +++++++++++++++ llvm/lib/MCA/InstrBuilder.cpp | 12 ++- .../tools/llvm-mca/X86/llvm-mca-markers-13.s | 4 +- .../tools/llvm-mca/X86/llvm-mca-markers-14.s | 5 +- llvm/tools/llvm-mca/CodeRegion.h | 20 ----- llvm/tools/llvm-mca/CodeRegionGenerator.cpp | 12 --- llvm/tools/llvm-mca/CodeRegionGenerator.h | 87 ++++++++----------- llvm/tools/llvm-mca/llvm-mca.cpp | 18 ++-- llvm/unittests/tools/llvm-mca/MCATestBase.cpp | 17 ++-- llvm/unittests/tools/llvm-mca/MCATestBase.h | 6 +- .../tools/llvm-mca/X86/TestIncrementalMCA.cpp | 14 +-- 13 files changed, 166 insertions(+), 132 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index 0bf86ce688f44..f73be65d7af5e 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -130,6 +130,9 @@ class Instrument { virtual ~Instrument() = default; + virtual bool canCustomize() const { return false; } + virtual void customize(InstrDesc &) const {} + StringRef getDesc() const { return Desc; } StringRef getData() const { return Data; } }; @@ -143,19 +146,26 @@ class LLVM_ABI InstrumentManager { protected: const MCSubtargetInfo &STI; const MCInstrInfo &MCII; + bool EnableDefaults; + std::unique_ptr TargetIM; public: - InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII) - : STI(STI), MCII(MCII) {} + InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + bool EnableDefaults = false, + std::unique_ptr TargetIM = {}) + : STI(STI), MCII(MCII), EnableDefaults(EnableDefaults), + TargetIM(std::move(TargetIM)) {} virtual ~InstrumentManager() = default; /// Returns true if llvm-mca should ignore instruments. - virtual bool shouldIgnoreInstruments() const { return true; } + virtual bool shouldIgnoreInstruments() const { + return !EnableDefaults && + (!TargetIM || TargetIM->shouldIgnoreInstruments()); } // Returns true if this supports processing Instrument with // Instrument.Desc equal to Type - virtual bool supportsInstrumentType(StringRef Type) const { return false; } + virtual bool supportsInstrumentType(StringRef Type) const; /// Allocate an Instrument, and return a unique pointer to it. This function /// may be useful to create instruments coming from comments in the assembly. @@ -175,6 +185,13 @@ class LLVM_ABI InstrumentManager { /// it returns the SchedClassID that belongs to MCI. virtual unsigned getSchedClassID(const MCInstrInfo &MCII, const MCInst &MCI, const SmallVector &IVec) const; + + // Return true if instruments can modify instruction description + virtual bool canCustomize(const SmallVector &IVec) const; + + // Customize instruction description + virtual void customize(const SmallVector &IVec, + llvm::mca::InstrDesc &Desc) const; }; } // namespace mca diff --git a/llvm/include/llvm/MCA/InstrBuilder.h b/llvm/include/llvm/MCA/InstrBuilder.h index 6779d27dcca3a..32923deb3e096 100644 --- a/llvm/include/llvm/MCA/InstrBuilder.h +++ b/llvm/include/llvm/MCA/InstrBuilder.h @@ -92,8 +92,7 @@ class InstrBuilder { Expected getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID); Expected - createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec, - function_ref Customizer = {}); + createInstrDescImpl(const MCInst &MCI, const SmallVector &IVec); Expected getOrCreateInstrDesc(const MCInst &MCI, const SmallVector &IVec); @@ -122,8 +121,7 @@ class InstrBuilder { void setInstRecycleCallback(InstRecycleCallback CB) { InstRecycleCB = CB; } LLVM_ABI Expected> - createInstruction(const MCInst &MCI, const SmallVector &IVec, - function_ref Customizer = {}); + createInstruction(const MCInst &MCI, const SmallVector &IVec); }; } // namespace mca } // namespace llvm diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index 1aa266e0a1e43..d196afeefba25 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/MCA/CustomBehaviour.h" +#include "llvm/MCA/Instruction.h" namespace llvm { namespace mca { @@ -42,19 +43,90 @@ CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, return std::vector>(); } +class CustomInstrument : public Instrument { + std::optional Latency; +public: + static const llvm::StringRef DESC_NAME; + explicit CustomInstrument(StringRef Data) : Instrument(DESC_NAME, Data) { + // Skip spaces and tabs. + unsigned Position = Data.find_first_not_of(" \t"); + if (Position >= Data.size()) + // We reached the end of the comment. Bail out. + return; + Data = Data.drop_front(Position); + auto [Name, Value] = Data.split(':'); + if (Name.upper() == "LATENCY") { + Position = Value.find_first_not_of(" \t"); + if (Position >= Value.size()) + return; + auto Stripped = Value.drop_front(Position); + unsigned L = 0; + if (!Stripped.getAsInteger(10, L)) + Latency = L; + } + } + + bool canCustomize() const override { + return bool(Latency); + } + + void customize(InstrDesc& ID) const override { + if (Latency) { + for (auto &W : ID.Writes) + W.Latency = *Latency; + ID.MaxLatency = *Latency; + } + } +}; + +const llvm::StringRef CustomInstrument::DESC_NAME = "CUSTOMIZE"; + +bool InstrumentManager::supportsInstrumentType(StringRef Type) const { + if (EnableDefaults && Type == CustomInstrument::DESC_NAME) + return true; + if (TargetIM) + return TargetIM->supportsInstrumentType(Type); + return false; +} + +bool InstrumentManager::canCustomize(const llvm::SmallVector &IVec) const { + for (const auto I : IVec) { + if (I->canCustomize()) + return true; + } + return false; +} + +void InstrumentManager::customize(const llvm::SmallVector &IVec, InstrDesc &ID) const { + for (const auto I : IVec) { + if (I->canCustomize()) + I->customize(ID); + } +} + UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc, llvm::StringRef Data) { + if (!EnableDefaults) + return std::make_unique(Desc, Data); + if (Desc == CustomInstrument::DESC_NAME) + return std::make_unique(Data); + if (TargetIM && TargetIM->supportsInstrumentType(Desc)) + return TargetIM->createInstrument(Desc, Data); return std::make_unique(Desc, Data); } SmallVector InstrumentManager::createInstruments(const MCInst &Inst) { + if (TargetIM) + return TargetIM->createInstruments(Inst); return SmallVector(); } unsigned InstrumentManager::getSchedClassID( const MCInstrInfo &MCII, const MCInst &MCI, const llvm::SmallVector &IVec) const { + if (TargetIM) + return TargetIM->getSchedClassID(MCII, MCI, IVec); return MCII.get(MCI.getOpcode()).getSchedClass(); } diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp index f65145b4203c0..1625677ce3e15 100644 --- a/llvm/lib/MCA/InstrBuilder.cpp +++ b/llvm/lib/MCA/InstrBuilder.cpp @@ -558,8 +558,7 @@ Expected InstrBuilder::getVariantSchedClassID(const MCInst &MCI, Expected InstrBuilder::createInstrDescImpl(const MCInst &MCI, - const SmallVector &IVec, - function_ref Customizer) { + const SmallVector &IVec) { assert(STI.getSchedModel().hasInstrSchedModel() && "Itineraries are not yet supported!"); @@ -634,8 +633,8 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI, // Now add the new descriptor. - if (Customizer) { - Customizer(*ID); + if (IM.canCustomize(IVec)) { + IM.customize(IVec, *ID); return *CustomDescriptors.emplace_back(std::move(ID)); } @@ -682,10 +681,9 @@ STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc"); Expected> InstrBuilder::createInstruction(const MCInst &MCI, - const SmallVector &IVec, - function_ref Customizer) { + const SmallVector &IVec) { Expected DescOrErr = - Customizer ? createInstrDescImpl(MCI, IVec, Customizer) + IM.canCustomize(IVec) ? createInstrDescImpl(MCI, IVec) : getOrCreateInstrDesc(MCI, IVec); if (!DescOrErr) return DescOrErr.takeError(); diff --git a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s index 9115ffadbdaee..1c39a667e0733 100644 --- a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s +++ b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s @@ -1,7 +1,9 @@ # NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py # RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=10 %s 2>&1 | FileCheck %s -add (%eax), %eax // LLVM-MCA-LATENCY : 100 +# LLVM-MCA-CUSTOMIZE Latency:100 +add (%eax), %eax +# LLVM-MCA-CUSTOMIZE mov %eax, (%ebx) # CHECK: Iterations: 10 diff --git a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s index 41da9f4b4cef1..b887cc3002a73 100644 --- a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s +++ b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s @@ -1,8 +1,9 @@ # NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py # RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=10 %s 2>&1 | FileCheck %s -add (%eax), %eax // LLVM-MCA-LATENCY : 100 -mov %eax, (%ebx) // LLVM-MCA-LATENCY : 100 +# LLVM-MCA-CUSTOMIZE Latency:100 +add (%eax), %eax +mov %eax, (%ebx) # CHECK: Iterations: 10 # CHECK-NEXT: Instructions: 20 diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h index 52c0854779be6..c04ea51169cfb 100644 --- a/llvm/tools/llvm-mca/CodeRegion.h +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -68,16 +68,11 @@ #include "llvm/Support/Error.h" #include "llvm/Support/SMLoc.h" #include "llvm/Support/SourceMgr.h" -#include #include namespace llvm { namespace mca { -struct InstAnnotation { - std::optional Latency; -}; - /// A region of assembly code. /// /// It identifies a sequence of machine instructions. @@ -160,9 +155,6 @@ class CodeRegions { llvm::StringMap ActiveRegions; bool FoundErrors; - // Annotations specified in comments, indexed by SMLoc value - llvm::DenseMap Annotations; - public: CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {} virtual ~CodeRegions() = default; @@ -178,18 +170,6 @@ class CodeRegions { void addInstruction(const llvm::MCInst &Instruction); llvm::SourceMgr &getSourceMgr() const { return SM; } - void Annotate(llvm::SMLoc Loc, const InstAnnotation &A) { - Annotations[Loc.getPointer()] = A; - } - std::optional getExplicitLatency(llvm::SMLoc Loc) const { - const auto It = Annotations.find(Loc.getPointer()); - if (It != Annotations.end()) { - return It->second.Latency; - } else { - return {}; - } - } - llvm::ArrayRef getInstructionSequence(unsigned Idx) const { return Regions[Idx]->getInstructions(); } diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp index 0d400760f17e1..f7f929e49ead9 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp @@ -95,18 +95,6 @@ void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc, return; Comment = Comment.drop_front(Position); - if (Comment.starts_with("LLVM-MCA-LATENCY")) { - auto Parts = Comment.split(':'); - Position = Parts.second.find_first_not_of(" \t"); - if (Position >= Parts.second.size()) - return; - auto LatStr = Parts.second.drop_front(Position); - unsigned Latency = 0; - if (!LatStr.getAsInteger(10, Latency)) - Streamer.AddLatencyAnnotation(Latency); - return; - } - if (Comment.consume_front("LLVM-MCA-END")) { // Skip spaces and tabs. Position = Comment.find_first_not_of(" \t"); diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.h b/llvm/tools/llvm-mca/CodeRegionGenerator.h index 1f43a8b26c471..a48c67a22f27b 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.h +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.h @@ -31,51 +31,6 @@ namespace llvm { namespace mca { -// This class provides the callbacks that occur when parsing input assembly. -class MCStreamerWrapper : public MCStreamer { -protected: - CodeRegions &Regions; - std::optional CurrentAnnotation; - -public: - MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R) - : MCStreamer(Context), Regions(R) {} - - // We only want to intercept the emission of new instructions. - void emitInstruction(const MCInst &Inst, - const MCSubtargetInfo & /* unused */) override { - Regions.addInstruction(Inst); - if (CurrentAnnotation) { - Regions.Annotate(Inst.getLoc(), *CurrentAnnotation); - CurrentAnnotation = {}; - } - } - - void AddLatencyAnnotation(unsigned Lat) { - if (!CurrentAnnotation) - CurrentAnnotation = InstAnnotation(); - CurrentAnnotation->Latency = Lat; - } - - bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { - return true; - } - - void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, - Align ByteAlignment) override {} - void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, - uint64_t Size = 0, Align ByteAlignment = Align(1), - SMLoc Loc = SMLoc()) override {} - void beginCOFFSymbolDef(const MCSymbol *Symbol) override {} - void emitCOFFSymbolStorageClass(int StorageClass) override {} - void emitCOFFSymbolType(int Type) override {} - void endCOFFSymbolDef() override {} - - ArrayRef GetInstructionSequence(unsigned Index) const { - return Regions.getInstructionSequence(Index); - } -}; - class MCACommentConsumer : public AsmCommentConsumer { protected: bool FoundError = false; @@ -89,11 +44,9 @@ class MCACommentConsumer : public AsmCommentConsumer { /// A comment consumer that parses strings. The only valid tokens are strings. class AnalysisRegionCommentConsumer : public MCACommentConsumer { AnalysisRegions &Regions; - MCStreamerWrapper &Streamer; public: - AnalysisRegionCommentConsumer(AnalysisRegions &R, MCStreamerWrapper &S) - : Regions(R), Streamer(S) {} + AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {} /// Parses a comment. It begins a new region if it is of the form /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END. @@ -129,6 +82,40 @@ class InstrumentRegionCommentConsumer : public MCACommentConsumer { InstrumentManager &getInstrumentManager() { return IM; } }; +// This class provides the callbacks that occur when parsing input assembly. +class MCStreamerWrapper : public MCStreamer { +protected: + CodeRegions &Regions; + +public: + MCStreamerWrapper(MCContext &Context, mca::CodeRegions &R) + : MCStreamer(Context), Regions(R) {} + + // We only want to intercept the emission of new instructions. + void emitInstruction(const MCInst &Inst, + const MCSubtargetInfo & /* unused */) override { + Regions.addInstruction(Inst); + } + + bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override { + return true; + } + + void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size, + Align ByteAlignment) override {} + void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr, + uint64_t Size = 0, Align ByteAlignment = Align(1), + SMLoc Loc = SMLoc()) override {} + void beginCOFFSymbolDef(const MCSymbol *Symbol) override {} + void emitCOFFSymbolStorageClass(int StorageClass) override {} + void emitCOFFSymbolType(int Type) override {} + void endCOFFSymbolDef() override {} + + ArrayRef GetInstructionSequence(unsigned Index) const { + return Regions.getInstructionSequence(Index); + } +}; + class InstrumentMCStreamer : public MCStreamerWrapper { InstrumentManager &IM; @@ -223,15 +210,15 @@ class AsmCodeRegionGenerator : public virtual CodeRegionGenerator { class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator, public AsmCodeRegionGenerator { - MCStreamerWrapper Streamer; AnalysisRegionCommentConsumer CC; + MCStreamerWrapper Streamer; public: AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C, const MCAsmInfo &A, const MCSubtargetInfo &S, const MCInstrInfo &I) : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I), - Streamer(Ctx, Regions), CC(Regions, Streamer) {} + CC(Regions), Streamer(Ctx, Regions) {} MCACommentConsumer *getCommentConsumer() override { return &CC; }; CodeRegions &getRegions() override { return Regions; }; diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 73ac11794154f..019c5a0db86aa 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -511,12 +511,13 @@ int main(int argc, char **argv) { std::unique_ptr IM; if (!DisableInstrumentManager) { - IM = std::unique_ptr( - TheTarget->createInstrumentManager(*STI, *MCII)); + std::unique_ptr TargetIM = + std::unique_ptr(TheTarget->createInstrumentManager(*STI, *MCII)); + IM = std::make_unique(*STI, *MCII, true, std::move(TargetIM)); } if (!IM) { - // If the target doesn't have its own IM implemented (or the -disable-cb - // flag is set) then we use the base class (which does nothing). + // If -disable-cb flag is set then we use the base class with default behavior + // (which does nothing). IM = std::make_unique(*STI, *MCII); } @@ -633,15 +634,8 @@ int main(int argc, char **argv) { const SmallVector Instruments = InstrumentRegions.getActiveInstruments(Loc); - auto Latency = Regions.getExplicitLatency(Loc); Expected> Inst = - Latency ? IB.createInstruction(MCI, Instruments, - [=](llvm::mca::InstrDesc &ID) { - for (auto &W : ID.Writes) - W.Latency = *Latency; - ID.MaxLatency = *Latency; - }) - : IB.createInstruction(MCI, Instruments); + IB.createInstruction(MCI, Instruments); if (!Inst) { if (auto NewE = handleErrors( Inst.takeError(), diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp index e2ff1dbe73a49..98ebd96fd0005 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp @@ -61,18 +61,25 @@ void MCATestBase::SetUp() { Error MCATestBase::runBaselineMCA(json::Object &Result, ArrayRef Insts, ArrayRef Views, - const mca::PipelineOptions *PO, Builder B) { + const mca::PipelineOptions *PO, + SmallVector> Descs) { mca::Context MCA(*MRI, *STI); - // Default InstrumentManager - auto IM = std::make_unique(*STI, *MCII); + // Enable instruments when descriptions are provided + auto IM = std::make_unique(*STI, *MCII, !Descs.empty()); mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM, /*CallLatency=*/100); - const SmallVector Instruments; + SmallVector Instruments; + SmallVector InstrumentsOwner; + for (const auto& Desc : Descs) { + auto I = IM->createInstrument(Desc.first, Desc.second); + Instruments.push_back(I.get()); + InstrumentsOwner.push_back(std::move(I)); + } SmallVector> LoweredInsts; for (const auto &MCI : Insts) { Expected> Inst = - B ? B(IB, MCI, Instruments) : IB.createInstruction(MCI, Instruments); + IB.createInstruction(MCI, Instruments); if (!Inst) { if (auto NewE = handleErrors(Inst.takeError(), diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.h b/llvm/unittests/tools/llvm-mca/MCATestBase.h index c741d1f90c7f0..71de00f1e457b 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.h +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.h @@ -71,17 +71,13 @@ class MCATestBase : public ::testing::Test { void SetUp() override; - using Builder = function_ref>( - mca::InstrBuilder &, const MCInst &, - const SmallVector &)>; - /// Utility function to run MCA with (nearly) the same configuration as the /// `llvm-mca` tool to verify result correctness. /// This function only displays on SummaryView by default. virtual Error runBaselineMCA(json::Object &Result, ArrayRef Insts, ArrayRef Views = {}, const mca::PipelineOptions *PO = nullptr, - Builder B = {}); + SmallVector> Descs = {}); }; } // end namespace mca diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 668afd1a8d6be..390697c2dd987 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -243,19 +243,13 @@ TEST_F(X86TestBase, TestInstructionCustomization) { .addReg(X86::RAX) .addReg(X86::RAX); MCIs.push_back(InstructionToAdd); + SmallVector> InstrDescs; + InstrDescs.push_back(std::make_pair(StringRef("CUSTOMIZE"), + StringRef("Latency:100"))); // Run the baseline. json::Object BaselineResult; - auto E = runBaselineMCA(BaselineResult, MCIs, {}, nullptr, - [=](InstrBuilder &IB, const MCInst &MCI, - const SmallVector &Instruments) { - return IB.createInstruction( - MCI, Instruments, [=](InstrDesc &ID) { - for (auto &W : ID.Writes) - W.Latency = ExplicitLatency; - ID.MaxLatency = ExplicitLatency; - }); - }); + auto E = runBaselineMCA(BaselineResult, MCIs, {}, nullptr, InstrDescs); ASSERT_FALSE(bool(E)) << "Failed to run baseline"; auto *BaselineObj = BaselineResult.getObject("SummaryView"); auto V = BaselineObj->getInteger("TotalCycles"); From 1282e706e5a08b3933930a4a50e5d47e9ad8ee3f Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Wed, 27 Aug 2025 17:34:33 +0300 Subject: [PATCH 16/32] Fix formatting Fixed formatting issues --- llvm/include/llvm/MCA/CustomBehaviour.h | 3 ++- llvm/lib/MCA/CustomBehaviour.cpp | 13 +++++++------ llvm/lib/MCA/InstrBuilder.cpp | 6 +++--- llvm/tools/llvm-mca/llvm-mca.cpp | 12 +++++++----- llvm/unittests/tools/llvm-mca/MCATestBase.cpp | 14 ++++++++------ llvm/unittests/tools/llvm-mca/MCATestBase.h | 9 +++++---- .../tools/llvm-mca/X86/TestIncrementalMCA.cpp | 4 ++-- 7 files changed, 34 insertions(+), 27 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index f73be65d7af5e..63331518f76ab 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -161,7 +161,8 @@ class LLVM_ABI InstrumentManager { /// Returns true if llvm-mca should ignore instruments. virtual bool shouldIgnoreInstruments() const { return !EnableDefaults && - (!TargetIM || TargetIM->shouldIgnoreInstruments()); } + (!TargetIM || TargetIM->shouldIgnoreInstruments()); + } // Returns true if this supports processing Instrument with // Instrument.Desc equal to Type diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index d196afeefba25..d22117af29025 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -45,6 +45,7 @@ CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, class CustomInstrument : public Instrument { std::optional Latency; + public: static const llvm::StringRef DESC_NAME; explicit CustomInstrument(StringRef Data) : Instrument(DESC_NAME, Data) { @@ -66,11 +67,9 @@ class CustomInstrument : public Instrument { } } - bool canCustomize() const override { - return bool(Latency); - } + bool canCustomize() const override { return bool(Latency); } - void customize(InstrDesc& ID) const override { + void customize(InstrDesc &ID) const override { if (Latency) { for (auto &W : ID.Writes) W.Latency = *Latency; @@ -89,7 +88,8 @@ bool InstrumentManager::supportsInstrumentType(StringRef Type) const { return false; } -bool InstrumentManager::canCustomize(const llvm::SmallVector &IVec) const { +bool InstrumentManager::canCustomize( + const llvm::SmallVector &IVec) const { for (const auto I : IVec) { if (I->canCustomize()) return true; @@ -97,7 +97,8 @@ bool InstrumentManager::canCustomize(const llvm::SmallVector &IVec return false; } -void InstrumentManager::customize(const llvm::SmallVector &IVec, InstrDesc &ID) const { +void InstrumentManager::customize(const llvm::SmallVector &IVec, + InstrDesc &ID) const { for (const auto I : IVec) { if (I->canCustomize()) I->customize(ID); diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp index 1625677ce3e15..ffd6a8d5c14a8 100644 --- a/llvm/lib/MCA/InstrBuilder.cpp +++ b/llvm/lib/MCA/InstrBuilder.cpp @@ -682,9 +682,9 @@ STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc"); Expected> InstrBuilder::createInstruction(const MCInst &MCI, const SmallVector &IVec) { - Expected DescOrErr = - IM.canCustomize(IVec) ? createInstrDescImpl(MCI, IVec) - : getOrCreateInstrDesc(MCI, IVec); + Expected DescOrErr = IM.canCustomize(IVec) + ? createInstrDescImpl(MCI, IVec) + : getOrCreateInstrDesc(MCI, IVec); if (!DescOrErr) return DescOrErr.takeError(); const InstrDesc &D = *DescOrErr; diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 019c5a0db86aa..6d937d1de9441 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -512,12 +512,14 @@ int main(int argc, char **argv) { std::unique_ptr IM; if (!DisableInstrumentManager) { std::unique_ptr TargetIM = - std::unique_ptr(TheTarget->createInstrumentManager(*STI, *MCII)); - IM = std::make_unique(*STI, *MCII, true, std::move(TargetIM)); + std::unique_ptr( + TheTarget->createInstrumentManager(*STI, *MCII)); + IM = std::make_unique(*STI, *MCII, true, + std::move(TargetIM)); } if (!IM) { - // If -disable-cb flag is set then we use the base class with default behavior - // (which does nothing). + // If -disable-cb flag is set then we use the base class with default + // behavior (which does nothing). IM = std::make_unique(*STI, *MCII); } @@ -635,7 +637,7 @@ int main(int argc, char **argv) { InstrumentRegions.getActiveInstruments(Loc); Expected> Inst = - IB.createInstruction(MCI, Instruments); + IB.createInstruction(MCI, Instruments); if (!Inst) { if (auto NewE = handleErrors( Inst.takeError(), diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp index 98ebd96fd0005..22f91a7acbc0a 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp @@ -59,19 +59,21 @@ void MCATestBase::SetUp() { ASSERT_TRUE(IP); } -Error MCATestBase::runBaselineMCA(json::Object &Result, ArrayRef Insts, - ArrayRef Views, - const mca::PipelineOptions *PO, - SmallVector> Descs) { +Error MCATestBase::runBaselineMCA( + json::Object &Result, ArrayRef Insts, + ArrayRef Views, + const mca::PipelineOptions *PO, + SmallVector> Descs) { mca::Context MCA(*MRI, *STI); // Enable instruments when descriptions are provided - auto IM = std::make_unique(*STI, *MCII, !Descs.empty()); + auto IM = + std::make_unique(*STI, *MCII, !Descs.empty()); mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM, /*CallLatency=*/100); SmallVector Instruments; SmallVector InstrumentsOwner; - for (const auto& Desc : Descs) { + for (const auto &Desc : Descs) { auto I = IM->createInstrument(Desc.first, Desc.second); Instruments.push_back(I.get()); InstrumentsOwner.push_back(std::move(I)); diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.h b/llvm/unittests/tools/llvm-mca/MCATestBase.h index 71de00f1e457b..1d88bc36ac0fa 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.h +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.h @@ -74,10 +74,11 @@ class MCATestBase : public ::testing::Test { /// Utility function to run MCA with (nearly) the same configuration as the /// `llvm-mca` tool to verify result correctness. /// This function only displays on SummaryView by default. - virtual Error runBaselineMCA(json::Object &Result, ArrayRef Insts, - ArrayRef Views = {}, - const mca::PipelineOptions *PO = nullptr, - SmallVector> Descs = {}); + virtual Error + runBaselineMCA(json::Object &Result, ArrayRef Insts, + ArrayRef Views = {}, + const mca::PipelineOptions *PO = nullptr, + SmallVector> Descs = {}); }; } // end namespace mca diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 390697c2dd987..4ab9fcd7f71da 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -244,8 +244,8 @@ TEST_F(X86TestBase, TestInstructionCustomization) { .addReg(X86::RAX); MCIs.push_back(InstructionToAdd); SmallVector> InstrDescs; - InstrDescs.push_back(std::make_pair(StringRef("CUSTOMIZE"), - StringRef("Latency:100"))); + InstrDescs.push_back( + std::make_pair(StringRef("CUSTOMIZE"), StringRef("Latency:100"))); // Run the baseline. json::Object BaselineResult; From 71403fbbe04cdb39f06bfa4c8a6cd07c720fc28a Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 28 Aug 2025 10:47:06 +0300 Subject: [PATCH 17/32] Move latency customization logic to base Instrument --- llvm/include/llvm/MCA/CustomBehaviour.h | 31 +++++++++++-- llvm/lib/MCA/CustomBehaviour.cpp | 45 ++----------------- llvm/unittests/tools/llvm-mca/MCATestBase.cpp | 3 +- 3 files changed, 33 insertions(+), 46 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index 63331518f76ab..64c050f96d8c2 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -123,15 +123,40 @@ class Instrument { /// The instrumentation data const StringRef Data; + std::optional Latency; + public: - Instrument(StringRef Desc, StringRef Data) : Desc(Desc), Data(Data) {} + Instrument(StringRef Desc, StringRef Data) : Desc(Desc), Data(Data) { + // Skip spaces and tabs. + unsigned Position = Data.find_first_not_of(" \t"); + if (Position >= Data.size()) + // We reached the end of the comment. Bail out. + return; + Data = Data.drop_front(Position); + auto [Name, Value] = Data.split(':'); + if (Name.upper() == "LATENCY") { + Position = Value.find_first_not_of(" \t"); + if (Position >= Value.size()) + return; + auto Stripped = Value.drop_front(Position); + unsigned L = 0; + if (!Stripped.getAsInteger(10, L)) + Latency = L; + } + } Instrument() : Instrument("", "") {} virtual ~Instrument() = default; - virtual bool canCustomize() const { return false; } - virtual void customize(InstrDesc &) const {} + virtual bool canCustomize() const { return bool(Latency); } + virtual void customize(InstrDesc &ID) const { + if (Latency) { + for (auto &W : ID.Writes) + W.Latency = *Latency; + ID.MaxLatency = *Latency; + } + } StringRef getDesc() const { return Desc; } StringRef getData() const { return Data; } diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index d22117af29025..ecbf58e33376e 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -43,45 +43,10 @@ CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, return std::vector>(); } -class CustomInstrument : public Instrument { - std::optional Latency; - -public: - static const llvm::StringRef DESC_NAME; - explicit CustomInstrument(StringRef Data) : Instrument(DESC_NAME, Data) { - // Skip spaces and tabs. - unsigned Position = Data.find_first_not_of(" \t"); - if (Position >= Data.size()) - // We reached the end of the comment. Bail out. - return; - Data = Data.drop_front(Position); - auto [Name, Value] = Data.split(':'); - if (Name.upper() == "LATENCY") { - Position = Value.find_first_not_of(" \t"); - if (Position >= Value.size()) - return; - auto Stripped = Value.drop_front(Position); - unsigned L = 0; - if (!Stripped.getAsInteger(10, L)) - Latency = L; - } - } - - bool canCustomize() const override { return bool(Latency); } - - void customize(InstrDesc &ID) const override { - if (Latency) { - for (auto &W : ID.Writes) - W.Latency = *Latency; - ID.MaxLatency = *Latency; - } - } -}; - -const llvm::StringRef CustomInstrument::DESC_NAME = "CUSTOMIZE"; +static const llvm::StringRef CustomInstrumentName = "CUSTOMIZE"; bool InstrumentManager::supportsInstrumentType(StringRef Type) const { - if (EnableDefaults && Type == CustomInstrument::DESC_NAME) + if (EnableDefaults && Type == CustomInstrumentName) return true; if (TargetIM) return TargetIM->supportsInstrumentType(Type); @@ -107,12 +72,10 @@ void InstrumentManager::customize(const llvm::SmallVector &IVec, UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc, llvm::StringRef Data) { - if (!EnableDefaults) - return std::make_unique(Desc, Data); - if (Desc == CustomInstrument::DESC_NAME) - return std::make_unique(Data); if (TargetIM && TargetIM->supportsInstrumentType(Desc)) return TargetIM->createInstrument(Desc, Data); + if (!EnableDefaults) + return std::make_unique(Desc, Data); return std::make_unique(Desc, Data); } diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp index 22f91a7acbc0a..1be41d5c76598 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp @@ -60,8 +60,7 @@ void MCATestBase::SetUp() { } Error MCATestBase::runBaselineMCA( - json::Object &Result, ArrayRef Insts, - ArrayRef Views, + json::Object &Result, ArrayRef Insts, ArrayRef Views, const mca::PipelineOptions *PO, SmallVector> Descs) { mca::Context MCA(*MRI, *STI); From b805a3c083c3415553bfbba34f09397f74cf63a7 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 28 Aug 2025 16:48:13 +0300 Subject: [PATCH 18/32] Simplify IM creation --- llvm/include/llvm/MCA/CustomBehaviour.h | 7 ++++--- llvm/lib/MCA/CustomBehaviour.cpp | 9 +++++++++ llvm/tools/llvm-mca/llvm-mca.cpp | 17 ++++------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index 64c050f96d8c2..c9a67c542994f 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -27,6 +27,9 @@ #include "llvm/Support/Compiler.h" namespace llvm { + +class Target; + namespace mca { /// Class which can be overriden by targets to modify the @@ -177,9 +180,7 @@ class LLVM_ABI InstrumentManager { public: InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, bool EnableDefaults = false, - std::unique_ptr TargetIM = {}) - : STI(STI), MCII(MCII), EnableDefaults(EnableDefaults), - TargetIM(std::move(TargetIM)) {} + const Target* TheTarget = nullptr); virtual ~InstrumentManager() = default; diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index ecbf58e33376e..7b2817d277365 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -13,6 +13,7 @@ #include "llvm/MCA/CustomBehaviour.h" #include "llvm/MCA/Instruction.h" +#include "llvm/MC/TargetRegistry.h" namespace llvm { namespace mca { @@ -45,6 +46,14 @@ CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, static const llvm::StringRef CustomInstrumentName = "CUSTOMIZE"; +InstrumentManager::InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, + bool EnableDefaults,const Target* TheTarget) + : STI(STI), MCII(MCII), EnableDefaults(EnableDefaults) { + if (TheTarget) + TargetIM = std::unique_ptr( + TheTarget->createInstrumentManager(STI, MCII)); +} + bool InstrumentManager::supportsInstrumentType(StringRef Type) const { if (EnableDefaults && Type == CustomInstrumentName) return true; diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 6d937d1de9441..bbebdb94d33e3 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -509,19 +509,10 @@ int main(int argc, char **argv) { return 1; } - std::unique_ptr IM; - if (!DisableInstrumentManager) { - std::unique_ptr TargetIM = - std::unique_ptr( - TheTarget->createInstrumentManager(*STI, *MCII)); - IM = std::make_unique(*STI, *MCII, true, - std::move(TargetIM)); - } - if (!IM) { - // If -disable-cb flag is set then we use the base class with default - // behavior (which does nothing). - IM = std::make_unique(*STI, *MCII); - } + std::unique_ptr IM = + std::make_unique(*STI, *MCII, !DisableInstrumentManager, + DisableInstrumentManager ? nullptr : + TheTarget); // Parse the input and create InstrumentRegion that llvm-mca // can use to improve analysis. From 801b0da28b3a56ae2cbea62ac29aa1e2da51ff2d Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 28 Aug 2025 17:00:04 +0300 Subject: [PATCH 19/32] Fix formatting --- llvm/include/llvm/MCA/CustomBehaviour.h | 2 +- llvm/lib/MCA/CustomBehaviour.cpp | 12 +++++++----- llvm/tools/llvm-mca/llvm-mca.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index c9a67c542994f..3f461e58c748c 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -180,7 +180,7 @@ class LLVM_ABI InstrumentManager { public: InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, bool EnableDefaults = false, - const Target* TheTarget = nullptr); + const Target *TheTarget = nullptr); virtual ~InstrumentManager() = default; diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index 7b2817d277365..e89511e563e50 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -46,12 +46,14 @@ CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, static const llvm::StringRef CustomInstrumentName = "CUSTOMIZE"; -InstrumentManager::InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, - bool EnableDefaults,const Target* TheTarget) +InstrumentManager::InstrumentManager(const MCSubtargetInfo &STI, + const MCInstrInfo &MCII, + bool EnableDefaults, + const Target* TheTarget) : STI(STI), MCII(MCII), EnableDefaults(EnableDefaults) { - if (TheTarget) - TargetIM = std::unique_ptr( - TheTarget->createInstrumentManager(STI, MCII)); + if (TheTarget) + TargetIM = std::unique_ptr( + TheTarget->createInstrumentManager(STI, MCII)); } bool InstrumentManager::supportsInstrumentType(StringRef Type) const { diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index bbebdb94d33e3..6fcb5a6ba85f1 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -509,10 +509,10 @@ int main(int argc, char **argv) { return 1; } - std::unique_ptr IM = - std::make_unique(*STI, *MCII, !DisableInstrumentManager, - DisableInstrumentManager ? nullptr : - TheTarget); + std::unique_ptr IM = + std::make_unique( + *STI, *MCII, !DisableInstrumentManager, + DisableInstrumentManager ? nullptr : TheTarget); // Parse the input and create InstrumentRegion that llvm-mca // can use to improve analysis. From ed4e0bde8b0044b233d3fdfed39b582edfc93eb9 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Fri, 29 Aug 2025 10:02:59 +0300 Subject: [PATCH 20/32] Remove target IM from base class --- llvm/include/llvm/MCA/CustomBehaviour.h | 15 ++++----------- llvm/lib/MCA/CustomBehaviour.cpp | 24 +----------------------- llvm/tools/llvm-mca/llvm-mca.cpp | 19 +++++++++++++++---- 3 files changed, 20 insertions(+), 38 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index 3f461e58c748c..b69cee4564b3f 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -27,9 +27,6 @@ #include "llvm/Support/Compiler.h" namespace llvm { - -class Target; - namespace mca { /// Class which can be overriden by targets to modify the @@ -174,21 +171,17 @@ class LLVM_ABI InstrumentManager { protected: const MCSubtargetInfo &STI; const MCInstrInfo &MCII; - bool EnableDefaults; - std::unique_ptr TargetIM; + bool EnableInstruments; public: InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, - bool EnableDefaults = false, - const Target *TheTarget = nullptr); + bool EnableInstruments = false) : + STI(STI), MCII(MCII), EnableInstruments(EnableInstruments) {}; virtual ~InstrumentManager() = default; /// Returns true if llvm-mca should ignore instruments. - virtual bool shouldIgnoreInstruments() const { - return !EnableDefaults && - (!TargetIM || TargetIM->shouldIgnoreInstruments()); - } + virtual bool shouldIgnoreInstruments() const { return !EnableInstruments; } // Returns true if this supports processing Instrument with // Instrument.Desc equal to Type diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index e89511e563e50..2f48444cb0fbe 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -46,22 +46,8 @@ CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, static const llvm::StringRef CustomInstrumentName = "CUSTOMIZE"; -InstrumentManager::InstrumentManager(const MCSubtargetInfo &STI, - const MCInstrInfo &MCII, - bool EnableDefaults, - const Target* TheTarget) - : STI(STI), MCII(MCII), EnableDefaults(EnableDefaults) { - if (TheTarget) - TargetIM = std::unique_ptr( - TheTarget->createInstrumentManager(STI, MCII)); -} - bool InstrumentManager::supportsInstrumentType(StringRef Type) const { - if (EnableDefaults && Type == CustomInstrumentName) - return true; - if (TargetIM) - return TargetIM->supportsInstrumentType(Type); - return false; + return EnableInstruments && Type == CustomInstrumentName; } bool InstrumentManager::canCustomize( @@ -83,25 +69,17 @@ void InstrumentManager::customize(const llvm::SmallVector &IVec, UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc, llvm::StringRef Data) { - if (TargetIM && TargetIM->supportsInstrumentType(Desc)) - return TargetIM->createInstrument(Desc, Data); - if (!EnableDefaults) - return std::make_unique(Desc, Data); return std::make_unique(Desc, Data); } SmallVector InstrumentManager::createInstruments(const MCInst &Inst) { - if (TargetIM) - return TargetIM->createInstruments(Inst); return SmallVector(); } unsigned InstrumentManager::getSchedClassID( const MCInstrInfo &MCII, const MCInst &MCI, const llvm::SmallVector &IVec) const { - if (TargetIM) - return TargetIM->getSchedClassID(MCII, MCI, IVec); return MCII.get(MCI.getOpcode()).getSchedClass(); } diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 6fcb5a6ba85f1..a568db5aa458c 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -509,10 +509,21 @@ int main(int argc, char **argv) { return 1; } - std::unique_ptr IM = - std::make_unique( - *STI, *MCII, !DisableInstrumentManager, - DisableInstrumentManager ? nullptr : TheTarget); + std::unique_ptr IM; + if (!DisableInstrumentManager) { + IM = std::unique_ptr( + TheTarget->createInstrumentManager(*STI, *MCII)); + if (!IM) { + // If the target doesn't have its own IM implemented we use base class with + // instruments enabled. + IM = std::make_unique(*STI, *MCII, true); + } + } + else { + // If the -disable-cb flag is set then we use the default base class + // implementation (which does nothing). + IM = std::make_unique(*STI, *MCII); + } // Parse the input and create InstrumentRegion that llvm-mca // can use to improve analysis. From 042b3baa21e058259451fabadf45e281cbc93edf Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Fri, 29 Aug 2025 10:12:53 +0300 Subject: [PATCH 21/32] Fix formatting * Update CustomBehaviour.h * Update CustomBehaviour.cpp * Update llvm-mca.cpp --- llvm/include/llvm/MCA/CustomBehaviour.h | 4 ++-- llvm/lib/MCA/CustomBehaviour.cpp | 1 - llvm/tools/llvm-mca/llvm-mca.cpp | 7 +++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index b69cee4564b3f..3b3fd740651ff 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -175,8 +175,8 @@ class LLVM_ABI InstrumentManager { public: InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, - bool EnableInstruments = false) : - STI(STI), MCII(MCII), EnableInstruments(EnableInstruments) {}; + bool EnableInstruments = false) + : STI(STI), MCII(MCII), EnableInstruments(EnableInstruments) {}; virtual ~InstrumentManager() = default; diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index 2f48444cb0fbe..48fc9e5d2f4bf 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -13,7 +13,6 @@ #include "llvm/MCA/CustomBehaviour.h" #include "llvm/MCA/Instruction.h" -#include "llvm/MC/TargetRegistry.h" namespace llvm { namespace mca { diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index a568db5aa458c..7bcad9cd64355 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -514,12 +514,11 @@ int main(int argc, char **argv) { IM = std::unique_ptr( TheTarget->createInstrumentManager(*STI, *MCII)); if (!IM) { - // If the target doesn't have its own IM implemented we use base class with - // instruments enabled. + // If the target doesn't have its own IM implemented we use base class + // with instruments enabled. IM = std::make_unique(*STI, *MCII, true); } - } - else { + } else { // If the -disable-cb flag is set then we use the default base class // implementation (which does nothing). IM = std::make_unique(*STI, *MCII); From 5fb0db741a2a372ab7fee92949298e6c0831c249 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Fri, 12 Sep 2025 12:08:43 +0300 Subject: [PATCH 22/32] Use explicit latency instrument Latency customization logic is moved to dedicated instrument. --- llvm/docs/CommandGuide/llvm-mca.rst | 14 ++++++ llvm/include/llvm/MCA/CustomBehaviour.h | 44 ++++++++++--------- llvm/lib/MCA/CustomBehaviour.cpp | 8 +++- .../tools/llvm-mca/X86/llvm-mca-markers-13.s | 4 +- .../tools/llvm-mca/X86/llvm-mca-markers-14.s | 2 +- .../tools/llvm-mca/X86/TestIncrementalMCA.cpp | 3 +- 6 files changed, 48 insertions(+), 27 deletions(-) diff --git a/llvm/docs/CommandGuide/llvm-mca.rst b/llvm/docs/CommandGuide/llvm-mca.rst index 1daae5d064aca..c7600834d262e 100644 --- a/llvm/docs/CommandGuide/llvm-mca.rst +++ b/llvm/docs/CommandGuide/llvm-mca.rst @@ -383,6 +383,20 @@ that do not start with `LLVM-MCA-` are ignored by :program:`llvm-mca`. An instruction (a MCInst) is added to an InstrumentRegion R only if its location is in range [R.RangeStart, R.RangeEnd]. +There is one instrument that can be used on all targets to explicitly +set instruction latencies. It can be used, for example, to model the +cache misses that impact load latencies. The syntax is like + +.. code-block:: none + + # LLVM-MCA-LATENCY 100 + mov (%edi), %eax + # LLVM-MCA-LATENCY + +It set the latency of mov instruction to 100. LLVM-MCA-LATENCY without +argument ends the region with explicit latency, after it default target +latencies are used. + On RISCV targets, vector instructions have different behaviour depending on the LMUL. Code can be instrumented with a comment that takes the following form: diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index 3b3fd740651ff..c075d781ccef9 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -123,43 +123,45 @@ class Instrument { /// The instrumentation data const StringRef Data; - std::optional Latency; +public: + Instrument(StringRef Desc, StringRef Data) : Desc(Desc), Data(Data) {} + + Instrument() : Instrument("", "") {} + + virtual ~Instrument() = default; + + virtual bool canCustomize() const { return false; } + virtual void customize(InstrDesc &) const {} + + StringRef getDesc() const { return Desc; } + StringRef getData() const { return Data; } +}; +class LatencyInstrument : public Instrument { + std::optional Latency; public: - Instrument(StringRef Desc, StringRef Data) : Desc(Desc), Data(Data) { + static const llvm::StringRef DESC_NAME; + LatencyInstrument(StringRef Data) : Instrument(DESC_NAME, Data) { // Skip spaces and tabs. unsigned Position = Data.find_first_not_of(" \t"); if (Position >= Data.size()) // We reached the end of the comment. Bail out. return; Data = Data.drop_front(Position); - auto [Name, Value] = Data.split(':'); - if (Name.upper() == "LATENCY") { - Position = Value.find_first_not_of(" \t"); - if (Position >= Value.size()) - return; - auto Stripped = Value.drop_front(Position); - unsigned L = 0; - if (!Stripped.getAsInteger(10, L)) - Latency = L; - } + unsigned L = 0; + if (!Data.getAsInteger(10, L)) + Latency = L; } - Instrument() : Instrument("", "") {} - - virtual ~Instrument() = default; - - virtual bool canCustomize() const { return bool(Latency); } - virtual void customize(InstrDesc &ID) const { + bool canCustomize() const override { return bool(Latency); } + void customize(InstrDesc &ID) const override { if (Latency) { + // TODO Allow to customize a subset of ID.Writes for (auto &W : ID.Writes) W.Latency = *Latency; ID.MaxLatency = *Latency; } } - - StringRef getDesc() const { return Desc; } - StringRef getData() const { return Data; } }; using UniqueInstrument = std::unique_ptr; diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index 48fc9e5d2f4bf..da2aa973a5a87 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -43,10 +43,10 @@ CustomBehaviour::getEndViews(llvm::MCInstPrinter &IP, return std::vector>(); } -static const llvm::StringRef CustomInstrumentName = "CUSTOMIZE"; +const llvm::StringRef LatencyInstrument::DESC_NAME = "LATENCY"; bool InstrumentManager::supportsInstrumentType(StringRef Type) const { - return EnableInstruments && Type == CustomInstrumentName; + return EnableInstruments && Type == LatencyInstrument::DESC_NAME; } bool InstrumentManager::canCustomize( @@ -68,6 +68,10 @@ void InstrumentManager::customize(const llvm::SmallVector &IVec, UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc, llvm::StringRef Data) { + if (!EnableInstruments) + return std::make_unique(Desc, Data); + if (Desc == LatencyInstrument::DESC_NAME) + return std::make_unique(Data); return std::make_unique(Desc, Data); } diff --git a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s index 1c39a667e0733..aa00ac4400820 100644 --- a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s +++ b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-13.s @@ -1,9 +1,9 @@ # NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py # RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=10 %s 2>&1 | FileCheck %s -# LLVM-MCA-CUSTOMIZE Latency:100 +# LLVM-MCA-LATENCY 100 add (%eax), %eax -# LLVM-MCA-CUSTOMIZE +# LLVM-MCA-LATENCY mov %eax, (%ebx) # CHECK: Iterations: 10 diff --git a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s index b887cc3002a73..f460f1df8a703 100644 --- a/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s +++ b/llvm/test/tools/llvm-mca/X86/llvm-mca-markers-14.s @@ -1,7 +1,7 @@ # NOTE: Assertions have been autogenerated by utils/update_mca_test_checks.py # RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -iterations=10 %s 2>&1 | FileCheck %s -# LLVM-MCA-CUSTOMIZE Latency:100 +# LLVM-MCA-LATENCY 100 add (%eax), %eax mov %eax, (%ebx) diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 4ab9fcd7f71da..7bfbbd7b1ccdd 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -235,6 +235,7 @@ TEST_F(X86TestBase, TestVariantInstructionsSameAddress) { ASSERT_TRUE(static_cast(Cycles)); } +// Test customization of instruction latency with instruments TEST_F(X86TestBase, TestInstructionCustomization) { const unsigned ExplicitLatency = 100; SmallVector MCIs; @@ -245,7 +246,7 @@ TEST_F(X86TestBase, TestInstructionCustomization) { MCIs.push_back(InstructionToAdd); SmallVector> InstrDescs; InstrDescs.push_back( - std::make_pair(StringRef("CUSTOMIZE"), StringRef("Latency:100"))); + std::make_pair(StringRef("LATENCY"), StringRef("100"))); // Run the baseline. json::Object BaselineResult; From e1244168f7d9d26ff8602a8aa8b9d1f0b3435f3c Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Fri, 12 Sep 2025 12:18:42 +0300 Subject: [PATCH 23/32] Fix formatting (#12) * Update CustomBehaviour.h * Update TestIncrementalMCA.cpp --- llvm/include/llvm/MCA/CustomBehaviour.h | 3 ++- llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index c075d781ccef9..39c5f23f10e29 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -125,7 +125,7 @@ class Instrument { public: Instrument(StringRef Desc, StringRef Data) : Desc(Desc), Data(Data) {} - + Instrument() : Instrument("", "") {} virtual ~Instrument() = default; @@ -139,6 +139,7 @@ class Instrument { class LatencyInstrument : public Instrument { std::optional Latency; + public: static const llvm::StringRef DESC_NAME; LatencyInstrument(StringRef Data) : Instrument(DESC_NAME, Data) { diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 7bfbbd7b1ccdd..0bbb565de94ad 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -245,8 +245,7 @@ TEST_F(X86TestBase, TestInstructionCustomization) { .addReg(X86::RAX); MCIs.push_back(InstructionToAdd); SmallVector> InstrDescs; - InstrDescs.push_back( - std::make_pair(StringRef("LATENCY"), StringRef("100"))); + InstrDescs.push_back(std::make_pair(StringRef("LATENCY"), StringRef("100"))); // Run the baseline. json::Object BaselineResult; From 74482dd19ff6cb38defaf19ce3d5e6cb0feb9624 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Fri, 12 Sep 2025 13:38:13 +0300 Subject: [PATCH 24/32] Removing redundant include was required for initial approach with customization passed via std::function, now we use IM methods. --- llvm/include/llvm/MCA/InstrBuilder.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/MCA/InstrBuilder.h b/llvm/include/llvm/MCA/InstrBuilder.h index 32923deb3e096..a5ce632b03634 100644 --- a/llvm/include/llvm/MCA/InstrBuilder.h +++ b/llvm/include/llvm/MCA/InstrBuilder.h @@ -25,7 +25,6 @@ #include "llvm/MCA/Support.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" -#include namespace llvm { namespace mca { From 5824130d68d5af926911a382b252438403fc05bd Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Fri, 12 Sep 2025 14:53:48 +0300 Subject: [PATCH 25/32] Make latency test more consistent Ensure the same value is used to set the latency and test the result --- llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 0bbb565de94ad..45133a805805b 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -245,7 +245,8 @@ TEST_F(X86TestBase, TestInstructionCustomization) { .addReg(X86::RAX); MCIs.push_back(InstructionToAdd); SmallVector> InstrDescs; - InstrDescs.push_back(std::make_pair(StringRef("LATENCY"), StringRef("100"))); + auto LatStr = std::to_string(ExplicitLatency); + InstrDescs.push_back(std::make_pair(StringRef("LATENCY"), StringRef(LatStr))); // Run the baseline. json::Object BaselineResult; From 7c40f7bfb8ba5da357c83914a2e08facd619fa2f Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Wed, 17 Sep 2025 10:40:49 +0300 Subject: [PATCH 26/32] Move customization logic to InstrumentManager --- llvm/include/llvm/MCA/CustomBehaviour.h | 16 +++------------ llvm/lib/MCA/CustomBehaviour.cpp | 26 +++++++++++++++++-------- llvm/tools/llvm-mca/llvm-mca.cpp | 8 ++++---- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index 39c5f23f10e29..fec656b1ddeb5 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -130,9 +130,6 @@ class Instrument { virtual ~Instrument() = default; - virtual bool canCustomize() const { return false; } - virtual void customize(InstrDesc &) const {} - StringRef getDesc() const { return Desc; } StringRef getData() const { return Data; } }; @@ -154,15 +151,8 @@ class LatencyInstrument : public Instrument { Latency = L; } - bool canCustomize() const override { return bool(Latency); } - void customize(InstrDesc &ID) const override { - if (Latency) { - // TODO Allow to customize a subset of ID.Writes - for (auto &W : ID.Writes) - W.Latency = *Latency; - ID.MaxLatency = *Latency; - } - } + bool hasValue() const { return bool(Latency); } + unsigned getLatency() { return *Latency; } }; using UniqueInstrument = std::unique_ptr; @@ -178,7 +168,7 @@ class LLVM_ABI InstrumentManager { public: InstrumentManager(const MCSubtargetInfo &STI, const MCInstrInfo &MCII, - bool EnableInstruments = false) + bool EnableInstruments = true) : STI(STI), MCII(MCII), EnableInstruments(EnableInstruments) {}; virtual ~InstrumentManager() = default; diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index da2aa973a5a87..ed1fb2fe22570 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -52,8 +52,10 @@ bool InstrumentManager::supportsInstrumentType(StringRef Type) const { bool InstrumentManager::canCustomize( const llvm::SmallVector &IVec) const { for (const auto I : IVec) { - if (I->canCustomize()) - return true; + if (I->getDesc() == LatencyInstrument::DESC_NAME) { + auto LatInst = static_cast(I); + return LatInst->hasValue(); + } } return false; } @@ -61,17 +63,25 @@ bool InstrumentManager::canCustomize( void InstrumentManager::customize(const llvm::SmallVector &IVec, InstrDesc &ID) const { for (const auto I : IVec) { - if (I->canCustomize()) - I->customize(ID); + if (I->getDesc() == LatencyInstrument::DESC_NAME) { + auto LatInst = static_cast(I); + if (LatInst->hasValue()) { + auto Latency = LatInst->getLatency(); + // TODO Allow to customize a subset of ID.Writes + for (auto &W : ID.Writes) + W.Latency = Latency; + ID.MaxLatency = Latency; + } + } } } UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc, llvm::StringRef Data) { - if (!EnableInstruments) - return std::make_unique(Desc, Data); - if (Desc == LatencyInstrument::DESC_NAME) - return std::make_unique(Data); + if (EnableInstruments) { + if (Desc == LatencyInstrument::DESC_NAME) + return std::make_unique(Data); + } return std::make_unique(Desc, Data); } diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 1c5d6965df735..fa7d5d1892f1f 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -516,12 +516,12 @@ int main(int argc, char **argv) { if (!IM) { // If the target doesn't have its own IM implemented we use base class // with instruments enabled. - IM = std::make_unique(*STI, *MCII, true); + IM = std::make_unique(*STI, *MCII); } } else { - // If the -disable-cb flag is set then we use the default base class - // implementation (which does nothing). - IM = std::make_unique(*STI, *MCII); + // If the -disable-im flag is set then we use the default base class + // implementation and disable the instruments. + IM = std::make_unique(*STI, *MCII, /*EnableInstruments=*/false); } // Parse the input and create InstrumentRegion that llvm-mca From 9e276b677a2d8e872e0d651ab7b3ab1e068cbb96 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Wed, 17 Sep 2025 10:50:16 +0300 Subject: [PATCH 27/32] Fix formatting (#14) --- llvm/lib/MCA/CustomBehaviour.cpp | 4 ++-- llvm/tools/llvm-mca/llvm-mca.cpp | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index ed1fb2fe22570..cb52c7e52a50d 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -53,7 +53,7 @@ bool InstrumentManager::canCustomize( const llvm::SmallVector &IVec) const { for (const auto I : IVec) { if (I->getDesc() == LatencyInstrument::DESC_NAME) { - auto LatInst = static_cast(I); + auto LatInst = static_cast(I); return LatInst->hasValue(); } } @@ -64,7 +64,7 @@ void InstrumentManager::customize(const llvm::SmallVector &IVec, InstrDesc &ID) const { for (const auto I : IVec) { if (I->getDesc() == LatencyInstrument::DESC_NAME) { - auto LatInst = static_cast(I); + auto LatInst = static_cast(I); if (LatInst->hasValue()) { auto Latency = LatInst->getLatency(); // TODO Allow to customize a subset of ID.Writes diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index fa7d5d1892f1f..294841c8127c9 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -521,7 +521,8 @@ int main(int argc, char **argv) { } else { // If the -disable-im flag is set then we use the default base class // implementation and disable the instruments. - IM = std::make_unique(*STI, *MCII, /*EnableInstruments=*/false); + IM = std::make_unique(*STI, *MCII, + /*EnableInstruments=*/false); } // Parse the input and create InstrumentRegion that llvm-mca From e28c48cf07bfff4390c6ae22db40b7830548d4ba Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 18 Sep 2025 10:26:35 +0300 Subject: [PATCH 28/32] FIxed incorrect Enlish Co-authored-by: Min-Yih Hsu --- llvm/docs/CommandGuide/llvm-mca.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/CommandGuide/llvm-mca.rst b/llvm/docs/CommandGuide/llvm-mca.rst index c7600834d262e..8598a5ca84ed8 100644 --- a/llvm/docs/CommandGuide/llvm-mca.rst +++ b/llvm/docs/CommandGuide/llvm-mca.rst @@ -393,7 +393,7 @@ cache misses that impact load latencies. The syntax is like mov (%edi), %eax # LLVM-MCA-LATENCY -It set the latency of mov instruction to 100. LLVM-MCA-LATENCY without +It sets the latency of mov instruction to 100. LLVM-MCA-LATENCY without argument ends the region with explicit latency, after it default target latencies are used. From 7e90de71f874d5a9f854c19a5ce0264362e9ca78 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 18 Sep 2025 10:54:25 +0300 Subject: [PATCH 29/32] Addressed minor comments --- llvm/include/llvm/MCA/CustomBehaviour.h | 14 ++++++-------- llvm/lib/MCA/CustomBehaviour.cpp | 10 +++++----- llvm/unittests/tools/llvm-mca/MCATestBase.cpp | 2 +- llvm/unittests/tools/llvm-mca/MCATestBase.h | 2 +- .../tools/llvm-mca/X86/TestIncrementalMCA.cpp | 2 +- 5 files changed, 14 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/MCA/CustomBehaviour.h b/llvm/include/llvm/MCA/CustomBehaviour.h index fec656b1ddeb5..0ce3993be95ba 100644 --- a/llvm/include/llvm/MCA/CustomBehaviour.h +++ b/llvm/include/llvm/MCA/CustomBehaviour.h @@ -138,21 +138,19 @@ class LatencyInstrument : public Instrument { std::optional Latency; public: - static const llvm::StringRef DESC_NAME; + static const StringRef DESC_NAME; LatencyInstrument(StringRef Data) : Instrument(DESC_NAME, Data) { // Skip spaces and tabs. - unsigned Position = Data.find_first_not_of(" \t"); - if (Position >= Data.size()) - // We reached the end of the comment. Bail out. + Data = Data.trim(); + if (Data.empty()) // Empty description. Bail out. return; - Data = Data.drop_front(Position); unsigned L = 0; if (!Data.getAsInteger(10, L)) Latency = L; } bool hasValue() const { return bool(Latency); } - unsigned getLatency() { return *Latency; } + unsigned getLatency() const { return *Latency; } }; using UniqueInstrument = std::unique_ptr; @@ -200,10 +198,10 @@ class LLVM_ABI InstrumentManager { const SmallVector &IVec) const; // Return true if instruments can modify instruction description - virtual bool canCustomize(const SmallVector &IVec) const; + virtual bool canCustomize(const ArrayRef IVec) const; // Customize instruction description - virtual void customize(const SmallVector &IVec, + virtual void customize(const ArrayRef IVec, llvm::mca::InstrDesc &Desc) const; }; diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index cb52c7e52a50d..f01230945746f 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -50,7 +50,7 @@ bool InstrumentManager::supportsInstrumentType(StringRef Type) const { } bool InstrumentManager::canCustomize( - const llvm::SmallVector &IVec) const { + const ArrayRef IVec) const { for (const auto I : IVec) { if (I->getDesc() == LatencyInstrument::DESC_NAME) { auto LatInst = static_cast(I); @@ -60,13 +60,13 @@ bool InstrumentManager::canCustomize( return false; } -void InstrumentManager::customize(const llvm::SmallVector &IVec, +void InstrumentManager::customize(const ArrayRef IVec, InstrDesc &ID) const { for (const auto I : IVec) { if (I->getDesc() == LatencyInstrument::DESC_NAME) { auto LatInst = static_cast(I); if (LatInst->hasValue()) { - auto Latency = LatInst->getLatency(); + unsigned Latency = LatInst->getLatency(); // TODO Allow to customize a subset of ID.Writes for (auto &W : ID.Writes) W.Latency = Latency; @@ -76,8 +76,8 @@ void InstrumentManager::customize(const llvm::SmallVector &IVec, } } -UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc, - llvm::StringRef Data) { +UniqueInstrument InstrumentManager::createInstrument(StringRef Desc, + StringRef Data) { if (EnableInstruments) { if (Desc == LatencyInstrument::DESC_NAME) return std::make_unique(Data); diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp index 06c79cf03f22f..c47ac4828fc40 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.cpp +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.cpp @@ -60,7 +60,7 @@ void MCATestBase::SetUp() { Error MCATestBase::runBaselineMCA( json::Object &Result, ArrayRef Insts, ArrayRef Views, const mca::PipelineOptions *PO, - SmallVector> Descs) { + ArrayRef> Descs) { mca::Context MCA(*MRI, *STI); // Enable instruments when descriptions are provided diff --git a/llvm/unittests/tools/llvm-mca/MCATestBase.h b/llvm/unittests/tools/llvm-mca/MCATestBase.h index 1d88bc36ac0fa..6672305cdb878 100644 --- a/llvm/unittests/tools/llvm-mca/MCATestBase.h +++ b/llvm/unittests/tools/llvm-mca/MCATestBase.h @@ -78,7 +78,7 @@ class MCATestBase : public ::testing::Test { runBaselineMCA(json::Object &Result, ArrayRef Insts, ArrayRef Views = {}, const mca::PipelineOptions *PO = nullptr, - SmallVector> Descs = {}); + ArrayRef> Descs = {}); }; } // end namespace mca diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 45133a805805b..5501c753c5952 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -246,7 +246,7 @@ TEST_F(X86TestBase, TestInstructionCustomization) { MCIs.push_back(InstructionToAdd); SmallVector> InstrDescs; auto LatStr = std::to_string(ExplicitLatency); - InstrDescs.push_back(std::make_pair(StringRef("LATENCY"), StringRef(LatStr))); + InstrDescs.push_back(std::make_pair("LATENCY", LatStr)); // Run the baseline. json::Object BaselineResult; From 40651427558647a5ce9c8ea86d11825b2f30339e Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 18 Sep 2025 11:01:05 +0300 Subject: [PATCH 30/32] Fixed formatting --- llvm/lib/MCA/CustomBehaviour.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/MCA/CustomBehaviour.cpp b/llvm/lib/MCA/CustomBehaviour.cpp index f01230945746f..51b85bf819840 100644 --- a/llvm/lib/MCA/CustomBehaviour.cpp +++ b/llvm/lib/MCA/CustomBehaviour.cpp @@ -49,8 +49,7 @@ bool InstrumentManager::supportsInstrumentType(StringRef Type) const { return EnableInstruments && Type == LatencyInstrument::DESC_NAME; } -bool InstrumentManager::canCustomize( - const ArrayRef IVec) const { +bool InstrumentManager::canCustomize(const ArrayRef IVec) const { for (const auto I : IVec) { if (I->getDesc() == LatencyInstrument::DESC_NAME) { auto LatInst = static_cast(I); From 6043f89c530e7063fda2945b008d71fc64e84ae2 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 18 Sep 2025 12:35:15 +0300 Subject: [PATCH 31/32] Ensure test instruction can not be eliminated on dispatch stage --- llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 5501c753c5952..9e9ca04795445 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -241,8 +241,8 @@ TEST_F(X86TestBase, TestInstructionCustomization) { SmallVector MCIs; MCInst InstructionToAdd = MCInstBuilder(X86::XOR64rr) .addReg(X86::RAX) - .addReg(X86::RAX) - .addReg(X86::RAX); + .addReg(X86::RBX) + .addReg(X86::RCX); MCIs.push_back(InstructionToAdd); SmallVector> InstrDescs; auto LatStr = std::to_string(ExplicitLatency); From 7bf43cf8e9e2750e7a51a456822551e4fa639635 Mon Sep 17 00:00:00 2001 From: Roman Belenov Date: Thu, 18 Sep 2025 13:18:13 +0300 Subject: [PATCH 32/32] Revert to explicit StringRef conversion to check the tests --- llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp index 9e9ca04795445..17809e7beda95 100644 --- a/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp +++ b/llvm/unittests/tools/llvm-mca/X86/TestIncrementalMCA.cpp @@ -246,7 +246,7 @@ TEST_F(X86TestBase, TestInstructionCustomization) { MCIs.push_back(InstructionToAdd); SmallVector> InstrDescs; auto LatStr = std::to_string(ExplicitLatency); - InstrDescs.push_back(std::make_pair("LATENCY", LatStr)); + InstrDescs.push_back(std::make_pair(StringRef("LATENCY"), StringRef(LatStr))); // Run the baseline. json::Object BaselineResult;