From: Andrea Di Biagio Date: Thu, 4 Oct 2018 10:36:49 +0000 (+0000) Subject: [llvm-mca] Check for inconsistencies when constructing instruction descriptors. X-Git-Tag: llvmorg-8.0.0-rc1~7248 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=aacd5e187b9111d2ee206f4e7b942e7243b6dbc4;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/llvm/tools/llvm-mca/include/HardwareUnits/RetireControlUnit.h b/llvm/tools/llvm-mca/include/HardwareUnits/RetireControlUnit.h index 7f2d699..552a209 100644 --- a/llvm/tools/llvm-mca/include/HardwareUnits/RetireControlUnit.h +++ b/llvm/tools/llvm-mca/include/HardwareUnits/RetireControlUnit.h @@ -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(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; } diff --git a/llvm/tools/llvm-mca/include/InstrBuilder.h b/llvm/tools/llvm-mca/include/InstrBuilder.h index 5888b08..e318092 100644 --- a/llvm/tools/llvm-mca/include/InstrBuilder.h +++ b/llvm/tools/llvm-mca/include/InstrBuilder.h @@ -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, diff --git a/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp b/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp index ca3cc8c..af1b01f 100644 --- a/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp +++ b/llvm/tools/llvm-mca/lib/HardwareUnits/RetireControlUnit.cpp @@ -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(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); diff --git a/llvm/tools/llvm-mca/lib/InstrBuilder.cpp b/llvm/tools/llvm-mca/lib/InstrBuilder.cpp index 6f776f3..0a26f40 100644 --- a/llvm/tools/llvm-mca/lib/InstrBuilder.cpp +++ b/llvm/tools/llvm-mca/lib/InstrBuilder.cpp @@ -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("Invalid instruction definition found", + inconvertibleErrorCode()); +} + Expected 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()) {