-
Notifications
You must be signed in to change notification settings - Fork 14.8k
[MCA] Enable customization of individual instructions #155420
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 18 commits
b1a67b7
4abee0f
1298dd3
b5c3b95
302b994
2338978
0be9fbf
f1ad060
757fec3
452bb40
4d655f8
ef2a0f0
77eefdb
d44bfbe
bd8cedf
6e0d12b
08cc266
1282e70
71403fb
b805a3c
801b0da
ed4e0bd
042b3ba
5fb0db7
e124416
74482dd
37d0734
5824130
5029c24
7c40f7b
9e276b6
129b7e4
e28c48c
7e90de7
4065142
f8113c4
6043f89
0d00426
7bf43cf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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,27 @@ 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 +186,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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ | |
//===----------------------------------------------------------------------===// | ||
|
||
#include "llvm/MCA/CustomBehaviour.h" | ||
#include "llvm/MCA/Instruction.h" | ||
|
||
namespace llvm { | ||
namespace mca { | ||
|
@@ -42,19 +43,91 @@ 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(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# 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 | ||
add (%eax), %eax | ||
# LLVM-MCA-CUSTOMIZE | ||
mov %eax, (%ebx) | ||
|
||
# CHECK: Iterations: 10 | ||
# CHECK-NEXT: Instructions: 20 | ||
# CHECK-NEXT: Total Cycles: 1004 | ||
# CHECK-NEXT: Total uOps: 20 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# 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 | ||
add (%eax), %eax | ||
mov %eax, (%ebx) | ||
|
||
# CHECK: Iterations: 10 | ||
# CHECK-NEXT: Instructions: 20 | ||
# CHECK-NEXT: Total Cycles: 1103 | ||
# CHECK-NEXT: Total uOps: 20 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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" | ||
|
||
|
@@ -73,9 +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); | ||
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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
InstrumentManager is already target-specific, why do you need TargetIM here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to have InstrDesc customization generic (e.g. latency change code is generic, other things I do locally also do not require target details) and coexist with target-specific instrumentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think my concern here is that this additional layer of pointer indirection could be avoid if we could simply put this latency updating logics in the base IM and called it from the target-specific, derived IM when needed, as I described in the sibling comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, now the customization in InstrumentManager class and can be reused.