diff options
author | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2018-07-09 12:30:55 +0000 |
---|---|---|
committer | Andrea Di Biagio <Andrea_DiBiagio@sn.scee.net> | 2018-07-09 12:30:55 +0000 |
commit | d77ac0d3a5beca0cbc1517aa5994cfe24effa459 (patch) | |
tree | 460cc661a6a1d3695504e2e76b0ba36818e6ccc2 /tools/llvm-mca | |
parent | ceb3c09eb4cc3f2ab1aae2a5387525abab07b34f (diff) |
[llvm-mca] report an error if the assembly sequence contains an unsupported instruction.
This is a short-term fix for PR38093.
For now, we llvm::report_fatal_error if the instruction builder finds an
unsupported instruction in the instruction stream.
We need to revisit this fix once we start addressing PR38101.
Essentially, we need a better framework for error handling.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336543 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-mca')
-rw-r--r-- | tools/llvm-mca/InstrBuilder.cpp | 58 | ||||
-rw-r--r-- | tools/llvm-mca/InstrBuilder.h | 11 | ||||
-rw-r--r-- | tools/llvm-mca/llvm-mca.cpp | 2 |
3 files changed, 46 insertions, 25 deletions
diff --git a/tools/llvm-mca/InstrBuilder.cpp b/tools/llvm-mca/InstrBuilder.cpp index 5b6b31b2eda..c0b25f783c8 100644 --- a/tools/llvm-mca/InstrBuilder.cpp +++ b/tools/llvm-mca/InstrBuilder.cpp @@ -17,8 +17,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/MC/MCInst.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/WithColor.h" +#include "llvm/Support/raw_ostream.h" #define DEBUG_TYPE "llvm-mca" @@ -155,10 +155,12 @@ static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc, ID.MaxLatency = Latency < 0 ? 100U : static_cast<unsigned>(Latency); } -static void populateWrites(InstrDesc &ID, const MCInst &MCI, - const MCInstrDesc &MCDesc, - const MCSchedClassDesc &SCDesc, - const MCSubtargetInfo &STI) { +void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI, + unsigned SchedClassID) { + const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode()); + const MCSchedModel &SM = STI.getSchedModel(); + const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); + // These are for now the (strong) assumptions made by this algorithm: // * The number of explicit and implicit register definitions in a MCInst // matches the number of explicit and implicit definitions according to @@ -196,8 +198,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI, const MCWriteLatencyEntry &WLE = *STI.getWriteLatencyEntry(&SCDesc, CurrentDef); // Conservatively default to MaxLatency. - Write.Latency = WLE.Cycles < 0 ? ID.MaxLatency - : static_cast<unsigned>(WLE.Cycles); + Write.Latency = + WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles); Write.SClassOrWriteResourceID = WLE.WriteResourceID; } else { // Assign a default latency for this write. @@ -226,8 +228,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI, const MCWriteLatencyEntry &WLE = *STI.getWriteLatencyEntry(&SCDesc, Index); // Conservatively default to MaxLatency. - Write.Latency = WLE.Cycles < 0 ? ID.MaxLatency - : static_cast<unsigned>(WLE.Cycles); + Write.Latency = + WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles); Write.SClassOrWriteResourceID = WLE.WriteResourceID; } else { // Assign a default latency for this write. @@ -262,14 +264,13 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI, } } -static void populateReads(InstrDesc &ID, const MCInst &MCI, - const MCInstrDesc &MCDesc, - const MCSchedClassDesc &SCDesc, - const MCSubtargetInfo &STI) { - unsigned SchedClassID = MCDesc.getSchedClass(); - unsigned i = 0; +void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI, + unsigned SchedClassID) { + const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode()); unsigned NumExplicitDefs = MCDesc.getNumDefs(); + // Skip explicit definitions. + unsigned i = 0; for (; i < MCI.getNumOperands() && NumExplicitDefs; ++i) { const MCOperand &Op = MCI.getOperand(i); if (Op.isReg()) @@ -314,8 +315,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) { assert(STI.getSchedModel().hasInstrSchedModel() && "Itineraries are not yet supported!"); - unsigned short Opcode = MCI.getOpcode(); // Obtain the instruction descriptor from the opcode. + unsigned short Opcode = MCI.getOpcode(); const MCInstrDesc &MCDesc = MCII.get(Opcode); const MCSchedModel &SM = STI.getSchedModel(); @@ -332,10 +333,23 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) { llvm::report_fatal_error("unable to resolve this variant class."); } + // Check if this instruction is supported. Otherwise, report a fatal error. + const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); + if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) { + std::string ToString; + llvm::raw_string_ostream OS(ToString); + WithColor::error() << "found an unsupported instruction in the input" + << " assembly sequence.\n"; + MCIP.printInst(&MCI, OS, "", STI); + OS.flush(); + + WithColor::note() << "instruction: " << ToString << '\n'; + llvm::report_fatal_error( + "Don't know how to analyze unsupported instructions."); + } + // Create a new empty descriptor. std::unique_ptr<InstrDesc> ID = llvm::make_unique<InstrDesc>(); - - const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); ID->NumMicroOps = SCDesc.NumMicroOps; if (MCDesc.isCall()) { @@ -357,8 +371,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) { initializeUsedResources(*ID, SCDesc, STI, ProcResourceMasks); computeMaxLatency(*ID, MCDesc, SCDesc, STI); - populateWrites(*ID, MCI, MCDesc, SCDesc, STI); - populateReads(*ID, MCI, MCDesc, SCDesc, STI); + populateWrites(*ID, MCI, SchedClassID); + populateReads(*ID, MCI, SchedClassID); LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n'); LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n'); @@ -428,8 +442,8 @@ InstrBuilder::createInstruction(const MCInst &MCI) { // Initialize writes. unsigned WriteIndex = 0; for (const WriteDescriptor &WD : D.Writes) { - unsigned RegID = - WD.isImplicitWrite() ? WD.RegisterID : MCI.getOperand(WD.OpIndex).getReg(); + unsigned RegID = WD.isImplicitWrite() ? WD.RegisterID + : MCI.getOperand(WD.OpIndex).getReg(); // Check if this is a optional definition that references NoReg. if (WD.IsOptionalDef && !RegID) { ++WriteIndex; diff --git a/tools/llvm-mca/InstrBuilder.h b/tools/llvm-mca/InstrBuilder.h index e5e80d7cf79..69a53b6fec2 100644 --- a/tools/llvm-mca/InstrBuilder.h +++ b/tools/llvm-mca/InstrBuilder.h @@ -17,6 +17,7 @@ #include "Instruction.h" #include "Support.h" +#include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" @@ -41,6 +42,7 @@ class InstrBuilder { const llvm::MCInstrInfo &MCII; const llvm::MCRegisterInfo &MRI; const llvm::MCInstrAnalysis &MCIA; + llvm::MCInstPrinter &MCIP; llvm::SmallVector<uint64_t, 8> ProcResourceMasks; llvm::DenseMap<unsigned short, std::unique_ptr<const InstrDesc>> Descriptors; @@ -51,11 +53,16 @@ class InstrBuilder { InstrBuilder(const InstrBuilder &) = delete; InstrBuilder &operator=(const InstrBuilder &) = delete; + void populateWrites(InstrDesc &ID, const llvm::MCInst &MCI, + unsigned SchedClassID); + void populateReads(InstrDesc &ID, const llvm::MCInst &MCI, + unsigned SchedClassID); + public: InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii, const llvm::MCRegisterInfo &mri, - const llvm::MCInstrAnalysis &mcia) - : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), + const llvm::MCInstrAnalysis &mcia, llvm::MCInstPrinter &mcip) + : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), MCIP(mcip), ProcResourceMasks(STI.getSchedModel().getNumProcResourceKinds()) { computeProcResourceMasks(STI.getSchedModel(), ProcResourceMasks); } diff --git a/tools/llvm-mca/llvm-mca.cpp b/tools/llvm-mca/llvm-mca.cpp index 9398a547fd4..97de338d960 100644 --- a/tools/llvm-mca/llvm-mca.cpp +++ b/tools/llvm-mca/llvm-mca.cpp @@ -460,7 +460,7 @@ int main(int argc, char **argv) { Width = DispatchWidth; // Create an instruction builder. - mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA); + mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA, *IP); // Create a context to control ownership of the pipeline hardware. mca::Context MCA(*MRI, *STI); |