Skip to content

Commit

Permalink
[llvm-mca] Check for inconsistencies when constructing instruction de…
Browse files Browse the repository at this point in the history
…scriptors.

This should help with catching inconsistent definitions of instructions with
zero opcodes, which also declare to consume scheduler/pipeline resources.

llvm-svn: 343766
  • Loading branch information
Andrea Di Biagio authored and Andrea Di Biagio committed Oct 4, 2018
1 parent 991b0d2 commit aacd5e1
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 2 deletions.
5 changes: 5 additions & 0 deletions llvm/tools/llvm-mca/include/HardwareUnits/RetireControlUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ struct RetireControlUnit : public HardwareUnit {
// of the reorder buffer. To avoid problems, cap the amount of slots to
// the size of the reorder buffer.
Quantity = std::min(Quantity, static_cast<unsigned>(Queue.size()));

// Further normalize the number of micro opcodes for instructions that
// declare zero opcodes. This should match the behavior of method
// reserveSlot().
Quantity = std::max(Quantity, 1U);
return AvailableSlots >= Quantity;
}

Expand Down
2 changes: 2 additions & 0 deletions llvm/tools/llvm-mca/include/InstrBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class InstrBuilder {
unsigned SchedClassID);
llvm::Error populateReads(InstrDesc &ID, const llvm::MCInst &MCI,
unsigned SchedClassID);
llvm::Error verifyInstrDesc(const InstrDesc &ID,
const llvm::MCInst &MCI) const;

public:
InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii,
Expand Down
4 changes: 2 additions & 2 deletions llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ RetireControlUnit::RetireControlUnit(const MCSchedModel &SM)
// Reserves a number of slots, and returns a new token.
unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
unsigned NumMicroOps) {
assert(isAvailable(NumMicroOps));
assert(isAvailable(NumMicroOps) && "Reorder Buffer unavailable!");
unsigned NormalizedQuantity =
std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
// Zero latency instructions may have zero mOps. Artificially bump this
// Zero latency instructions may have zero uOps. Artificially bump this
// value to 1. Although zero latency instructions don't consume scheduler
// resources, they still consume one slot in the retire queue.
NormalizedQuantity = std::max(NormalizedQuantity, 1U);
Expand Down
34 changes: 34 additions & 0 deletions llvm/tools/llvm-mca/lib/InstrBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,36 @@ Error InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
return ErrorSuccess();
}

Error InstrBuilder::verifyInstrDesc(const InstrDesc &ID,
const MCInst &MCI) const {
if (ID.NumMicroOps != 0)
return ErrorSuccess();

bool UsesMemory = ID.MayLoad || ID.MayStore;
bool UsesBuffers = !ID.Buffers.empty();
bool UsesResources = !ID.Resources.empty();
if (!UsesMemory && !UsesBuffers && !UsesResources)
return ErrorSuccess();

std::string ToString;
raw_string_ostream OS(ToString);
if (UsesMemory) {
WithColor::error() << "found an inconsistent instruction that decodes "
<< "into zero opcodes and that consumes load/store "
<< "unit resources.\n";
} else {
WithColor::error() << "found an inconsistent instruction that decodes"
<< " to zero opcodes and that consumes scheduler "
<< "resources.\n";
}

MCIP.printInst(&MCI, OS, "", STI);
OS.flush();
WithColor::note() << "instruction: " << ToString << '\n';
return make_error<StringError>("Invalid instruction definition found",
inconvertibleErrorCode());
}

Expected<const InstrDesc &>
InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
assert(STI.getSchedModel().hasInstrSchedModel() &&
Expand Down Expand Up @@ -392,6 +422,10 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n');
LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n');

// Sanity check on the instruction descriptor.
if (Error Err = verifyInstrDesc(*ID, MCI))
return std::move(Err);

// Now add the new descriptor.
SchedClassID = MCDesc.getSchedClass();
if (!SM.getSchedClassDesc(SchedClassID)->isVariant()) {
Expand Down

0 comments on commit aacd5e1

Please sign in to comment.