[llvm] [MCA] Enable customization of individual instructions (PR #155420)
Roman Belenov via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 12 03:38:34 PDT 2025
https://github.com/r-belenov updated https://github.com/llvm/llvm-project/pull/155420
>From b1a67b7972a83cd1bc4a8bbede1e117d013c667b Mon Sep 17 00:00:00 2001
From: Roman Belenov <103195329+r-belenov at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:00:10 +0300
Subject: [PATCH 01/24] 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 <functional>
namespace llvm {
namespace mca {
@@ -78,6 +79,10 @@ class InstrBuilder {
DenseMap<std::pair<hash_code, unsigned>, std::unique_ptr<const InstrDesc>>
VariantDescriptors;
+ // These descriptors are customized for particular instructions and cannot
+ // be reused
+ SmallVector<std::unique_ptr<const InstrDesc>> CustomDescriptors;
+
bool FirstCallInst;
bool FirstReturnInst;
unsigned CallLatency;
@@ -87,7 +92,8 @@ class InstrBuilder {
Expected<unsigned> getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID);
Expected<const InstrDesc &>
- createInstrDescImpl(const MCInst &MCI, const SmallVector<Instrument *> &IVec);
+ createInstrDescImpl(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
+ std::function<void(InstrDesc&)> Customizer = {});
Expected<const InstrDesc &>
getOrCreateInstrDesc(const MCInst &MCI,
const SmallVector<Instrument *> &IVec);
@@ -116,7 +122,8 @@ class InstrBuilder {
void setInstRecycleCallback(InstRecycleCallback CB) { InstRecycleCB = CB; }
LLVM_ABI Expected<std::unique_ptr<Instruction>>
- createInstruction(const MCInst &MCI, const SmallVector<Instrument *> &IVec);
+ createInstruction(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
+ std::function<void(InstrDesc&)> 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<unsigned> InstrBuilder::getVariantSchedClassID(const MCInst &MCI,
Expected<const InstrDesc &>
InstrBuilder::createInstrDescImpl(const MCInst &MCI,
- const SmallVector<Instrument *> &IVec) {
+ const SmallVector<Instrument *> &IVec,
+ std::function<void(InstrDesc&)> 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<std::unique_ptr<Instruction>>
InstrBuilder::createInstruction(const MCInst &MCI,
- const SmallVector<Instrument *> &IVec) {
- Expected<const InstrDesc &> DescOrErr = getOrCreateInstrDesc(MCI, IVec);
+ const SmallVector<Instrument *> &IVec,
+ std::function<void(InstrDesc&)> Customizer) {
+ Expected<const InstrDesc &> 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 <vector>
+#include <utility>
namespace llvm {
namespace mca {
+struct InstAnnotation {
+ std::optional<unsigned> Latency;
+};
+
/// A region of assembly code.
///
/// It identifies a sequence of machine instructions.
@@ -155,6 +160,9 @@ class CodeRegions {
llvm::StringMap<unsigned> ActiveRegions;
bool FoundErrors;
+ // Annotations specified in comments, indexed by SMLoc value
+ llvm::DenseMap<const char*, InstAnnotation> 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<unsigned> getExplicitLatency(llvm::SMLoc Loc) const {
+ const auto It = Annotations.find(Loc.getPointer());
+ if (It != Annotations.end()) {
+ return It->second.Latency;
+ } else {
+ return {};
+ }
+ }
+
llvm::ArrayRef<llvm::MCInst> 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<InstAnnotation> 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<MCInst> 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<MCInst> 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<mca::Instrument *> Instruments =
InstrumentRegions.getActiveInstruments(Loc);
- Expected<std::unique_ptr<mca::Instruction>> Inst =
+ auto Latency = Regions.getExplicitLatency(Loc);
+ Expected<std::unique_ptr<mca::Instruction>> 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<MCInst> Insts,
ArrayRef<mca::View *> 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<MCInst> Insts,
SmallVector<std::unique_ptr<mca::Instruction>> LoweredInsts;
for (const auto &MCI : Insts) {
Expected<std::unique_ptr<mca::Instruction>> 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<Expected<std::unique_ptr<mca::Instruction>>
+ (mca::InstrBuilder&, const MCInst&, const SmallVector<mca::Instrument *>&)>;
+
/// 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<MCInst> Insts,
ArrayRef<mca::View *> 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<unsigned> Cycles = P->run();
ASSERT_TRUE(static_cast<bool>(Cycles));
}
+
+TEST_F(X86TestBase, TestInstructionCustomization) {
+ const unsigned ExplicitLatency = 100;
+ SmallVector<MCInst> 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<Instrument*>& 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:28:21 +0300
Subject: [PATCH 02/24] 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<unsigned> getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID);
Expected<const InstrDesc &>
createInstrDescImpl(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc&)> Customizer = {});
+ std::function<void(InstrDesc &)> Customizer = {});
Expected<const InstrDesc &>
getOrCreateInstrDesc(const MCInst &MCI,
const SmallVector<Instrument *> &IVec);
@@ -123,7 +123,7 @@ class InstrBuilder {
LLVM_ABI Expected<std::unique_ptr<Instruction>>
createInstruction(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc&)> Customizer = {});
+ std::function<void(InstrDesc &)> Customizer = {});
};
} // namespace mca
} // namespace llvm
>From 1298dd3391061b66c57bd69b58a44894f001f4fe Mon Sep 17 00:00:00 2001
From: Roman Belenov <103195329+r-belenov at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:31:59 +0300
Subject: [PATCH 03/24] 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<unsigned> InstrBuilder::getVariantSchedClassID(const MCInst &MCI,
Expected<const InstrDesc &>
InstrBuilder::createInstrDescImpl(const MCInst &MCI,
const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc&)> Customizer) {
+ std::function<void(InstrDesc &)> 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<std::unique_ptr<Instruction>>
InstrBuilder::createInstruction(const MCInst &MCI,
const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc&)> Customizer) {
- Expected<const InstrDesc &> DescOrErr = Customizer? createInstrDescImpl(MCI, IVec, Customizer) :
- getOrCreateInstrDesc(MCI, IVec);
+ std::function<void(InstrDesc &)> Customizer) {
+ Expected<const InstrDesc &> 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:35:46 +0300
Subject: [PATCH 04/24] 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 <vector>
#include <utility>
+#include <vector>
namespace llvm {
namespace mca {
@@ -161,7 +161,7 @@ class CodeRegions {
bool FoundErrors;
// Annotations specified in comments, indexed by SMLoc value
- llvm::DenseMap<const char*, InstAnnotation> Annotations;
+ llvm::DenseMap<const char *, InstAnnotation> 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<unsigned> 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:37:17 +0300
Subject: [PATCH 05/24] 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:39:13 +0300
Subject: [PATCH 06/24] 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:41:47 +0300
Subject: [PATCH 07/24] 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<std::unique_ptr<mca::Instruction>> 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<std::unique_ptr<mca::Instruction>> 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:43:15 +0300
Subject: [PATCH 08/24] 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<MCInst> Insts,
ArrayRef<mca::View *> 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:44:43 +0300
Subject: [PATCH 09/24] 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<Expected<std::unique_ptr<mca::Instruction>>
- (mca::InstrBuilder&, const MCInst&, const SmallVector<mca::Instrument *>&)>;
+ using Builder = std::function<Expected<std::unique_ptr<mca::Instruction>>(
+ mca::InstrBuilder&, const MCInst&,
+ const SmallVector<mca::Instrument *> &)>;
/// 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 at users.noreply.github.com>
Date: Tue, 26 Aug 2025 17:47:02 +0300
Subject: [PATCH 10/24] 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<MCInst> 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<Instrument*>& 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<Instrument *> &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 <rbelenov at gmail.com>
Date: Tue, 26 Aug 2025 17:51:49 +0300
Subject: [PATCH 11/24] 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<unsigned> getExplicitLatency(llvm::SMLoc Loc) const {
>From ef2a0f0106358ee44d1a036e8b6cf2ab6fc50179 Mon Sep 17 00:00:00 2001
From: Roman Belenov <rbelenov at gmail.com>
Date: Tue, 26 Aug 2025 17:52:56 +0300
Subject: [PATCH 12/24] 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<std::unique_ptr<mca::Instruction>> 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 <rbelenov at gmail.com>
Date: Tue, 26 Aug 2025 17:54:25 +0300
Subject: [PATCH 13/24] 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<Expected<std::unique_ptr<mca::Instruction>>(
- mca::InstrBuilder&, const MCInst&,
+ mca::InstrBuilder &, const MCInst &,
const SmallVector<mca::Instrument *> &)>;
/// Utility function to run MCA with (nearly) the same configuration as the
>From 6e0d12b6aa58c9608b677da571781157e07bb4af Mon Sep 17 00:00:00 2001
From: Roman Belenov <rbelenov at gmail.com>
Date: Wed, 27 Aug 2025 07:59:05 +0300
Subject: [PATCH 14/24] 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<unsigned> getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID);
Expected<const InstrDesc &>
createInstrDescImpl(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc &)> Customizer = {});
+ function_ref<void(InstrDesc &)> Customizer = {});
Expected<const InstrDesc &>
getOrCreateInstrDesc(const MCInst &MCI,
const SmallVector<Instrument *> &IVec);
@@ -123,7 +123,7 @@ class InstrBuilder {
LLVM_ABI Expected<std::unique_ptr<Instruction>>
createInstruction(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc &)> Customizer = {});
+ function_ref<void(InstrDesc &)> 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<unsigned> InstrBuilder::getVariantSchedClassID(const MCInst &MCI,
Expected<const InstrDesc &>
InstrBuilder::createInstrDescImpl(const MCInst &MCI,
const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc &)> Customizer) {
+ function_ref<void(InstrDesc &)> 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<std::unique_ptr<Instruction>>
InstrBuilder::createInstruction(const MCInst &MCI,
const SmallVector<Instrument *> &IVec,
- std::function<void(InstrDesc &)> Customizer) {
+ function_ref<void(InstrDesc &)> Customizer) {
Expected<const InstrDesc &> 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<Expected<std::unique_ptr<mca::Instruction>>(
+ using Builder = function_ref<Expected<std::unique_ptr<mca::Instruction>>(
mca::InstrBuilder &, const MCInst &,
const SmallVector<mca::Instrument *> &)>;
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 <rbelenov at gmail.com>
Date: Wed, 27 Aug 2025 16:59:23 +0300
Subject: [PATCH 15/24] 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<InstrumentManager> 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<InstrumentManager> 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<Instrument *> &IVec) const;
+
+ // Return true if instruments can modify instruction description
+ virtual bool canCustomize(const SmallVector<Instrument *> &IVec) const;
+
+ // Customize instruction description
+ virtual void customize(const SmallVector<Instrument *> &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<unsigned> getVariantSchedClassID(const MCInst &MCI, unsigned SchedClassID);
Expected<const InstrDesc &>
- createInstrDescImpl(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
- function_ref<void(InstrDesc &)> Customizer = {});
+ createInstrDescImpl(const MCInst &MCI, const SmallVector<Instrument *> &IVec);
Expected<const InstrDesc &>
getOrCreateInstrDesc(const MCInst &MCI,
const SmallVector<Instrument *> &IVec);
@@ -122,8 +121,7 @@ class InstrBuilder {
void setInstRecycleCallback(InstRecycleCallback CB) { InstRecycleCB = CB; }
LLVM_ABI Expected<std::unique_ptr<Instruction>>
- createInstruction(const MCInst &MCI, const SmallVector<Instrument *> &IVec,
- function_ref<void(InstrDesc &)> Customizer = {});
+ createInstruction(const MCInst &MCI, const SmallVector<Instrument *> &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<std::unique_ptr<View>>();
}
+class CustomInstrument : public Instrument {
+ std::optional<unsigned> 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<Instrument *> &IVec) const {
+ for (const auto I : IVec) {
+ if (I->canCustomize())
+ return true;
+ }
+ return false;
+}
+
+void InstrumentManager::customize(const llvm::SmallVector<Instrument *> &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<Instrument>(Desc, Data);
+ if (Desc == CustomInstrument::DESC_NAME)
+ return std::make_unique<CustomInstrument>(Data);
+ if (TargetIM && TargetIM->supportsInstrumentType(Desc))
+ return TargetIM->createInstrument(Desc, Data);
return std::make_unique<Instrument>(Desc, Data);
}
SmallVector<UniqueInstrument>
InstrumentManager::createInstruments(const MCInst &Inst) {
+ if (TargetIM)
+ return TargetIM->createInstruments(Inst);
return SmallVector<UniqueInstrument>();
}
unsigned InstrumentManager::getSchedClassID(
const MCInstrInfo &MCII, const MCInst &MCI,
const llvm::SmallVector<Instrument *> &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<unsigned> InstrBuilder::getVariantSchedClassID(const MCInst &MCI,
Expected<const InstrDesc &>
InstrBuilder::createInstrDescImpl(const MCInst &MCI,
- const SmallVector<Instrument *> &IVec,
- function_ref<void(InstrDesc &)> Customizer) {
+ const SmallVector<Instrument *> &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<std::unique_ptr<Instruction>>
InstrBuilder::createInstruction(const MCInst &MCI,
- const SmallVector<Instrument *> &IVec,
- function_ref<void(InstrDesc &)> Customizer) {
+ const SmallVector<Instrument *> &IVec) {
Expected<const InstrDesc &> 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 <utility>
#include <vector>
namespace llvm {
namespace mca {
-struct InstAnnotation {
- std::optional<unsigned> Latency;
-};
-
/// A region of assembly code.
///
/// It identifies a sequence of machine instructions.
@@ -160,9 +155,6 @@ class CodeRegions {
llvm::StringMap<unsigned> ActiveRegions;
bool FoundErrors;
- // Annotations specified in comments, indexed by SMLoc value
- llvm::DenseMap<const char *, InstAnnotation> 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<unsigned> getExplicitLatency(llvm::SMLoc Loc) const {
- const auto It = Annotations.find(Loc.getPointer());
- if (It != Annotations.end()) {
- return It->second.Latency;
- } else {
- return {};
- }
- }
-
llvm::ArrayRef<llvm::MCInst> 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<InstAnnotation> 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<MCInst> 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<MCInst> 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<mca::InstrumentManager> IM;
if (!DisableInstrumentManager) {
- IM = std::unique_ptr<mca::InstrumentManager>(
- TheTarget->createInstrumentManager(*STI, *MCII));
+ std::unique_ptr<mca::InstrumentManager> TargetIM =
+ std::unique_ptr<mca::InstrumentManager>(TheTarget->createInstrumentManager(*STI, *MCII));
+ IM = std::make_unique<mca::InstrumentManager>(*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<mca::InstrumentManager>(*STI, *MCII);
}
@@ -633,15 +634,8 @@ int main(int argc, char **argv) {
const SmallVector<mca::Instrument *> Instruments =
InstrumentRegions.getActiveInstruments(Loc);
- auto Latency = Regions.getExplicitLatency(Loc);
Expected<std::unique_ptr<mca::Instruction>> 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<MCInst> Insts,
ArrayRef<mca::View *> Views,
- const mca::PipelineOptions *PO, Builder B) {
+ const mca::PipelineOptions *PO,
+ SmallVector<std::pair<StringRef, StringRef>> Descs) {
mca::Context MCA(*MRI, *STI);
- // Default InstrumentManager
- auto IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
+ // Enable instruments when descriptions are provided
+ auto IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII, !Descs.empty());
mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM, /*CallLatency=*/100);
- const SmallVector<mca::Instrument *> Instruments;
+ SmallVector<mca::Instrument *> Instruments;
+ SmallVector<mca::UniqueInstrument> 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<std::unique_ptr<mca::Instruction>> LoweredInsts;
for (const auto &MCI : Insts) {
Expected<std::unique_ptr<mca::Instruction>> 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<Expected<std::unique_ptr<mca::Instruction>>(
- mca::InstrBuilder &, const MCInst &,
- const SmallVector<mca::Instrument *> &)>;
-
/// 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<MCInst> Insts,
ArrayRef<mca::View *> Views = {},
const mca::PipelineOptions *PO = nullptr,
- Builder B = {});
+ SmallVector<std::pair<StringRef, StringRef>> 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<std::pair<StringRef, StringRef>> 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<Instrument *> &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 <rbelenov at gmail.com>
Date: Wed, 27 Aug 2025 17:34:33 +0300
Subject: [PATCH 16/24] 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<unsigned> 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<Instrument *> &IVec) const {
+bool InstrumentManager::canCustomize(
+ const llvm::SmallVector<Instrument *> &IVec) const {
for (const auto I : IVec) {
if (I->canCustomize())
return true;
@@ -97,7 +97,8 @@ bool InstrumentManager::canCustomize(const llvm::SmallVector<Instrument *> &IVec
return false;
}
-void InstrumentManager::customize(const llvm::SmallVector<Instrument *> &IVec, InstrDesc &ID) const {
+void InstrumentManager::customize(const llvm::SmallVector<Instrument *> &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<std::unique_ptr<Instruction>>
InstrBuilder::createInstruction(const MCInst &MCI,
const SmallVector<Instrument *> &IVec) {
- Expected<const InstrDesc &> DescOrErr =
- IM.canCustomize(IVec) ? createInstrDescImpl(MCI, IVec)
- : getOrCreateInstrDesc(MCI, IVec);
+ Expected<const InstrDesc &> 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<mca::InstrumentManager> IM;
if (!DisableInstrumentManager) {
std::unique_ptr<mca::InstrumentManager> TargetIM =
- std::unique_ptr<mca::InstrumentManager>(TheTarget->createInstrumentManager(*STI, *MCII));
- IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII, true, std::move(TargetIM));
+ std::unique_ptr<mca::InstrumentManager>(
+ TheTarget->createInstrumentManager(*STI, *MCII));
+ IM = std::make_unique<mca::InstrumentManager>(*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<mca::InstrumentManager>(*STI, *MCII);
}
@@ -635,7 +637,7 @@ int main(int argc, char **argv) {
InstrumentRegions.getActiveInstruments(Loc);
Expected<std::unique_ptr<mca::Instruction>> 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<MCInst> Insts,
- ArrayRef<mca::View *> Views,
- const mca::PipelineOptions *PO,
- SmallVector<std::pair<StringRef, StringRef>> Descs) {
+Error MCATestBase::runBaselineMCA(
+ json::Object &Result, ArrayRef<MCInst> Insts,
+ ArrayRef<mca::View *> Views,
+ const mca::PipelineOptions *PO,
+ SmallVector<std::pair<StringRef, StringRef>> Descs) {
mca::Context MCA(*MRI, *STI);
// Enable instruments when descriptions are provided
- auto IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII, !Descs.empty());
+ auto IM =
+ std::make_unique<mca::InstrumentManager>(*STI, *MCII, !Descs.empty());
mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM, /*CallLatency=*/100);
SmallVector<mca::Instrument *> Instruments;
SmallVector<mca::UniqueInstrument> 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<MCInst> Insts,
- ArrayRef<mca::View *> Views = {},
- const mca::PipelineOptions *PO = nullptr,
- SmallVector<std::pair<StringRef, StringRef>> Descs = {});
+ virtual Error
+ runBaselineMCA(json::Object &Result, ArrayRef<MCInst> Insts,
+ ArrayRef<mca::View *> Views = {},
+ const mca::PipelineOptions *PO = nullptr,
+ SmallVector<std::pair<StringRef, StringRef>> 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<std::pair<StringRef, StringRef>> 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 <rbelenov at gmail.com>
Date: Thu, 28 Aug 2025 10:47:06 +0300
Subject: [PATCH 17/24] 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<unsigned> 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<std::unique_ptr<View>>();
}
-class CustomInstrument : public Instrument {
- std::optional<unsigned> 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<Instrument *> &IVec,
UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc,
llvm::StringRef Data) {
- if (!EnableDefaults)
- return std::make_unique<Instrument>(Desc, Data);
- if (Desc == CustomInstrument::DESC_NAME)
- return std::make_unique<CustomInstrument>(Data);
if (TargetIM && TargetIM->supportsInstrumentType(Desc))
return TargetIM->createInstrument(Desc, Data);
+ if (!EnableDefaults)
+ return std::make_unique<Instrument>(Desc, Data);
return std::make_unique<Instrument>(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<MCInst> Insts,
- ArrayRef<mca::View *> Views,
+ json::Object &Result, ArrayRef<MCInst> Insts, ArrayRef<mca::View *> Views,
const mca::PipelineOptions *PO,
SmallVector<std::pair<StringRef, StringRef>> Descs) {
mca::Context MCA(*MRI, *STI);
>From b805a3c083c3415553bfbba34f09397f74cf63a7 Mon Sep 17 00:00:00 2001
From: Roman Belenov <rbelenov at gmail.com>
Date: Thu, 28 Aug 2025 16:48:13 +0300
Subject: [PATCH 18/24] 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<InstrumentManager> 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<InstrumentManager>(
+ 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<mca::InstrumentManager> IM;
- if (!DisableInstrumentManager) {
- std::unique_ptr<mca::InstrumentManager> TargetIM =
- std::unique_ptr<mca::InstrumentManager>(
- TheTarget->createInstrumentManager(*STI, *MCII));
- IM = std::make_unique<mca::InstrumentManager>(*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<mca::InstrumentManager>(*STI, *MCII);
- }
+ std::unique_ptr<mca::InstrumentManager> IM =
+ std::make_unique<mca::InstrumentManager>(*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 <rbelenov at gmail.com>
Date: Thu, 28 Aug 2025 17:00:04 +0300
Subject: [PATCH 19/24] 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<InstrumentManager>(
- TheTarget->createInstrumentManager(STI, MCII));
+ if (TheTarget)
+ TargetIM = std::unique_ptr<InstrumentManager>(
+ 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<mca::InstrumentManager> IM =
- std::make_unique<mca::InstrumentManager>(*STI, *MCII, !DisableInstrumentManager,
- DisableInstrumentManager ? nullptr :
- TheTarget);
+ std::unique_ptr<mca::InstrumentManager> IM =
+ std::make_unique<mca::InstrumentManager>(
+ *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 <rbelenov at gmail.com>
Date: Fri, 29 Aug 2025 10:02:59 +0300
Subject: [PATCH 20/24] 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<InstrumentManager> 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<InstrumentManager>(
- 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<Instrument *> &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<Instrument>(Desc, Data);
return std::make_unique<Instrument>(Desc, Data);
}
SmallVector<UniqueInstrument>
InstrumentManager::createInstruments(const MCInst &Inst) {
- if (TargetIM)
- return TargetIM->createInstruments(Inst);
return SmallVector<UniqueInstrument>();
}
unsigned InstrumentManager::getSchedClassID(
const MCInstrInfo &MCII, const MCInst &MCI,
const llvm::SmallVector<Instrument *> &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<mca::InstrumentManager> IM =
- std::make_unique<mca::InstrumentManager>(
- *STI, *MCII, !DisableInstrumentManager,
- DisableInstrumentManager ? nullptr : TheTarget);
+ std::unique_ptr<mca::InstrumentManager> IM;
+ if (!DisableInstrumentManager) {
+ IM = std::unique_ptr<mca::InstrumentManager>(
+ 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<mca::InstrumentManager>(*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<mca::InstrumentManager>(*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 <rbelenov at gmail.com>
Date: Fri, 29 Aug 2025 10:12:53 +0300
Subject: [PATCH 21/24] 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<mca::InstrumentManager>(
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<mca::InstrumentManager>(*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<mca::InstrumentManager>(*STI, *MCII);
>From 5fb0db741a2a372ab7fee92949298e6c0831c249 Mon Sep 17 00:00:00 2001
From: Roman Belenov <rbelenov at gmail.com>
Date: Fri, 12 Sep 2025 12:08:43 +0300
Subject: [PATCH 22/24] 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<unsigned> 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<unsigned> 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<Instrument>;
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<std::unique_ptr<View>>();
}
-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<Instrument *> &IVec,
UniqueInstrument InstrumentManager::createInstrument(llvm::StringRef Desc,
llvm::StringRef Data) {
+ if (!EnableInstruments)
+ return std::make_unique<Instrument>(Desc, Data);
+ if (Desc == LatencyInstrument::DESC_NAME)
+ return std::make_unique<LatencyInstrument>(Data);
return std::make_unique<Instrument>(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<bool>(Cycles));
}
+// Test customization of instruction latency with instruments
TEST_F(X86TestBase, TestInstructionCustomization) {
const unsigned ExplicitLatency = 100;
SmallVector<MCInst> MCIs;
@@ -245,7 +246,7 @@ TEST_F(X86TestBase, TestInstructionCustomization) {
MCIs.push_back(InstructionToAdd);
SmallVector<std::pair<StringRef, StringRef>> 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 <rbelenov at gmail.com>
Date: Fri, 12 Sep 2025 12:18:42 +0300
Subject: [PATCH 23/24] 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<unsigned> 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<std::pair<StringRef, StringRef>> 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 <rbelenov at gmail.com>
Date: Fri, 12 Sep 2025 13:38:13 +0300
Subject: [PATCH 24/24] Removing redundant include
<functional> 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 <functional>
namespace llvm {
namespace mca {
More information about the llvm-commits
mailing list