From 88347796440212e7acd97b4e675c568ce5cf1d53 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Mon, 9 Jul 2018 12:30:55 +0000 Subject: [PATCH] [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. llvm-svn: 336543 --- .../llvm-mca/X86/BtVer2/unsupported-instruction.s | 6 +++ llvm/tools/llvm-mca/InstrBuilder.cpp | 58 ++++++++++++++-------- llvm/tools/llvm-mca/InstrBuilder.h | 11 +++- llvm/tools/llvm-mca/llvm-mca.cpp | 2 +- 4 files changed, 52 insertions(+), 25 deletions(-) create mode 100644 llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s b/llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s new file mode 100644 index 0000000..bb88e95 --- /dev/null +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s @@ -0,0 +1,6 @@ +# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s 2>&1 | FileCheck %s + +bzhi %eax, %ebx, %ecx + +# CHECK: error: found an unsupported instruction in the input assembly sequence. +# CHECK-NEXT: note: instruction: bzhil %eax, %ebx, %ecx diff --git a/llvm/tools/llvm-mca/InstrBuilder.cpp b/llvm/tools/llvm-mca/InstrBuilder.cpp index 5b6b31b..c0b25f7 100644 --- a/llvm/tools/llvm-mca/InstrBuilder.cpp +++ b/llvm/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(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(WLE.Cycles); + Write.Latency = + WLE.Cycles < 0 ? ID.MaxLatency : static_cast(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(WLE.Cycles); + Write.Latency = + WLE.Cycles < 0 ? ID.MaxLatency : static_cast(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 ID = llvm::make_unique(); - - 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/llvm/tools/llvm-mca/InstrBuilder.h b/llvm/tools/llvm-mca/InstrBuilder.h index e5e80d7..69a53b6 100644 --- a/llvm/tools/llvm-mca/InstrBuilder.h +++ b/llvm/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 ProcResourceMasks; llvm::DenseMap> 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/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 9398a54..97de338 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/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); -- 2.7.4