1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

[llvm-mca] Check for inconsistencies when constructing instruction descriptors.

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

llvm-svn: 343766
This commit is contained in:
Andrea Di Biagio 2018-10-04 10:36:49 +00:00
parent 22cbe0170a
commit 6465970406
4 changed files with 43 additions and 2 deletions

View File

@ -70,6 +70,11 @@ public:
// 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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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() &&
@ -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()) {