// 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;
}
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,
// 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);
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() &&
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()) {