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:
parent
22cbe0170a
commit
6465970406
@ -70,6 +70,11 @@ public:
|
|||||||
// of the reorder buffer. To avoid problems, cap the amount of slots to
|
// of the reorder buffer. To avoid problems, cap the amount of slots to
|
||||||
// the size of the reorder buffer.
|
// the size of the reorder buffer.
|
||||||
Quantity = std::min(Quantity, static_cast<unsigned>(Queue.size()));
|
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;
|
return AvailableSlots >= Quantity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,8 @@ class InstrBuilder {
|
|||||||
unsigned SchedClassID);
|
unsigned SchedClassID);
|
||||||
llvm::Error populateReads(InstrDesc &ID, const llvm::MCInst &MCI,
|
llvm::Error populateReads(InstrDesc &ID, const llvm::MCInst &MCI,
|
||||||
unsigned SchedClassID);
|
unsigned SchedClassID);
|
||||||
|
llvm::Error verifyInstrDesc(const InstrDesc &ID,
|
||||||
|
const llvm::MCInst &MCI) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii,
|
InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii,
|
||||||
|
@ -41,10 +41,10 @@ RetireControlUnit::RetireControlUnit(const MCSchedModel &SM)
|
|||||||
// Reserves a number of slots, and returns a new token.
|
// Reserves a number of slots, and returns a new token.
|
||||||
unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
|
unsigned RetireControlUnit::reserveSlot(const InstRef &IR,
|
||||||
unsigned NumMicroOps) {
|
unsigned NumMicroOps) {
|
||||||
assert(isAvailable(NumMicroOps));
|
assert(isAvailable(NumMicroOps) && "Reorder Buffer unavailable!");
|
||||||
unsigned NormalizedQuantity =
|
unsigned NormalizedQuantity =
|
||||||
std::min(NumMicroOps, static_cast<unsigned>(Queue.size()));
|
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
|
// value to 1. Although zero latency instructions don't consume scheduler
|
||||||
// resources, they still consume one slot in the retire queue.
|
// resources, they still consume one slot in the retire queue.
|
||||||
NormalizedQuantity = std::max(NormalizedQuantity, 1U);
|
NormalizedQuantity = std::max(NormalizedQuantity, 1U);
|
||||||
|
@ -321,6 +321,36 @@ Error InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
|
|||||||
return ErrorSuccess();
|
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 &>
|
Expected<const InstrDesc &>
|
||||||
InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
|
InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
|
||||||
assert(STI.getSchedModel().hasInstrSchedModel() &&
|
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\tMaxLatency=" << ID->MaxLatency << '\n');
|
||||||
LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\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.
|
// Now add the new descriptor.
|
||||||
SchedClassID = MCDesc.getSchedClass();
|
SchedClassID = MCDesc.getSchedClass();
|
||||||
if (!SM.getSchedClassDesc(SchedClassID)->isVariant()) {
|
if (!SM.getSchedClassDesc(SchedClassID)->isVariant()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user