diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/test/tools/llvm-mca/ARM/unsupported-write-variant.s | 6 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/include/InstrBuilder.h | 6 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/include/Support.h | 20 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/lib/InstrBuilder.cpp | 59 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/llvm-mca.cpp | 40 |
5 files changed, 84 insertions, 47 deletions
diff --git a/llvm/test/tools/llvm-mca/ARM/unsupported-write-variant.s b/llvm/test/tools/llvm-mca/ARM/unsupported-write-variant.s new file mode 100644 index 00000000000..f4511f54ab5 --- /dev/null +++ b/llvm/test/tools/llvm-mca/ARM/unsupported-write-variant.s @@ -0,0 +1,6 @@ +# RUN: not llvm-mca -march=arm -mcpu=swift -all-views=false 2>&1 < %s | FileCheck %s + +add r3, r1, r12, lsl #2 + +# CHECK: error: unable to resolve scheduling class for write variant. +# CHECK-NEXT: note: instruction: add r3, r1, r12, lsl #2 diff --git a/llvm/tools/llvm-mca/include/InstrBuilder.h b/llvm/tools/llvm-mca/include/InstrBuilder.h index ff7fb52044a..9fee94bbb3f 100644 --- a/llvm/tools/llvm-mca/include/InstrBuilder.h +++ b/llvm/tools/llvm-mca/include/InstrBuilder.h @@ -17,7 +17,6 @@ #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,7 +40,6 @@ 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; @@ -66,8 +64,8 @@ class InstrBuilder { public: InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii, const llvm::MCRegisterInfo &mri, - const llvm::MCInstrAnalysis &mcia, llvm::MCInstPrinter &mcip) - : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), MCIP(mcip), + const llvm::MCInstrAnalysis &mcia) + : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), ProcResourceMasks(STI.getSchedModel().getNumProcResourceKinds()) { computeProcResourceMasks(STI.getSchedModel(), ProcResourceMasks); } diff --git a/llvm/tools/llvm-mca/include/Support.h b/llvm/tools/llvm-mca/include/Support.h index 91c8e1b4177..9371394542d 100644 --- a/llvm/tools/llvm-mca/include/Support.h +++ b/llvm/tools/llvm-mca/include/Support.h @@ -18,9 +18,29 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCSchedule.h" +#include "llvm/Support/Error.h" namespace mca { +template <typename T> +class InstructionError : public llvm::ErrorInfo<InstructionError<T>> { +public: + static char ID; + std::string Message; + const T &Inst; + + InstructionError(std::string M, const T &MCI) + : Message(std::move(M)), Inst(MCI) {} + + void log(llvm::raw_ostream &OS) const override { OS << Message; } + + std::error_code convertToErrorCode() const override { + return llvm::inconvertibleErrorCode(); + } +}; + +template <typename T> char InstructionError<T>::ID; + /// This class represents the number of cycles per resource (fractions of /// cycles). That quantity is managed here as a ratio, and accessed via the /// double cast-operator below. The two quantities, number of cycles and diff --git a/llvm/tools/llvm-mca/lib/InstrBuilder.cpp b/llvm/tools/llvm-mca/lib/InstrBuilder.cpp index 1cb020a9f6d..55f1ebf6e8a 100644 --- a/llvm/tools/llvm-mca/lib/InstrBuilder.cpp +++ b/llvm/tools/llvm-mca/lib/InstrBuilder.cpp @@ -215,9 +215,8 @@ Error InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI, } if (CurrentDef != NumExplicitDefs) { - return make_error<StringError>( - "error: Expected more register operand definitions.", - inconvertibleErrorCode()); + return make_error<InstructionError<MCInst>>( + "Expected more register operand definitions.", MCI); } CurrentDef = 0; @@ -253,11 +252,12 @@ Error InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI, // Always assume that the optional definition is the last operand of the // MCInst sequence. const MCOperand &Op = MCI.getOperand(MCI.getNumOperands() - 1); - if (i == MCI.getNumOperands() || !Op.isReg()) - return make_error<StringError>( - "error: expected a register operand for an optional " - "definition. Instruction has not be correctly analyzed.", - inconvertibleErrorCode()); + if (i == MCI.getNumOperands() || !Op.isReg()) { + std::string Message = + "expected a register operand for an optional definition. Instruction " + "has not been correctly analyzed."; + return make_error<InstructionError<MCInst>>(Message, MCI); + } WriteDescriptor &Write = ID.Writes[TotalDefs - 1]; Write.OpIndex = MCI.getNumOperands() - 1; @@ -284,9 +284,8 @@ Error InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI, } if (NumExplicitDefs) { - return make_error<StringError>( - "error: Expected more register operand definitions. ", - inconvertibleErrorCode()); + return make_error<InstructionError<MCInst>>( + "Expected more register operand definitions.", MCI); } unsigned NumExplicitUses = MCI.getNumOperands() - i; @@ -332,23 +331,18 @@ Error InstrBuilder::verifyInstrDesc(const InstrDesc &ID, if (!UsesMemory && !UsesBuffers && !UsesResources) return ErrorSuccess(); - std::string ToString; - raw_string_ostream OS(ToString); + StringRef Message; if (UsesMemory) { - WithColor::error() << "found an inconsistent instruction that decodes " - << "into zero opcodes and that consumes load/store " - << "unit resources.\n"; + Message = "found an inconsistent instruction that decodes " + "into zero opcodes and that consumes load/store " + "unit resources."; } else { - WithColor::error() << "found an inconsistent instruction that decodes" - << " to zero opcodes and that consumes scheduler " - << "resources.\n"; + Message = "found an inconsistent instruction that decodes " + "to zero opcodes and that consumes scheduler " + "resources."; } - MCIP.printInst(&MCI, OS, "", STI); - OS.flush(); - WithColor::note() << "instruction: " << ToString << '\n'; - return make_error<StringError>("Invalid instruction definition found", - inconvertibleErrorCode()); + return make_error<InstructionError<MCInst>>(Message, MCI); } Expected<const InstrDesc &> @@ -371,24 +365,17 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI) { SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &MCI, CPUID); if (!SchedClassID) { - return make_error<StringError>("unable to resolve this variant class.", - inconvertibleErrorCode()); + return make_error<InstructionError<MCInst>>( + "unable to resolve scheduling class for write variant.", MCI); } } // Check if this instruction is supported. Otherwise, report an error. const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) { - std::string ToString; - 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'; - return make_error<StringError>( - "Don't know how to analyze unsupported instructions", - inconvertibleErrorCode()); + return make_error<InstructionError<MCInst>>( + "found an unsupported instruction in the input assembly sequence.", + MCI); } // Create a new empty descriptor. diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 59b78ff1545..9ad761e6665 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -35,6 +35,7 @@ #include "Views/TimelineView.h" #include "include/Context.h" #include "include/Pipeline.h" +#include "include/Support.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectFileInfo.h" @@ -326,6 +327,30 @@ static void processViewOptions() { processOptionImpl(PrintRetireStats, Default); } +// Returns true on success. +static bool runPipeline(mca::Pipeline &P, MCInstPrinter &MCIP, + const MCSubtargetInfo &STI) { + // Handle pipeline errors here. + if (auto Err = P.run()) { + if (auto NewE = handleErrors( + std::move(Err), + [&MCIP, &STI](const mca::InstructionError<MCInst> &IE) { + std::string InstructionStr; + raw_string_ostream SS(InstructionStr); + WithColor::error() << IE.Message << '\n'; + MCIP.printInst(&IE.Inst, SS, "", STI); + SS.flush(); + WithColor::note() << "instruction: " << InstructionStr << '\n'; + })) { + // Default case. + WithColor::error() << toString(std::move(NewE)); + } + return false; + } + + return true; +} + int main(int argc, char **argv) { InitLLVM X(argc, argv); @@ -462,7 +487,7 @@ int main(int argc, char **argv) { Width = DispatchWidth; // Create an instruction builder. - mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA, *IP); + mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA); // Create a context to control ownership of the pipeline hardware. mca::Context MCA(*MRI, *STI); @@ -504,9 +529,10 @@ int main(int argc, char **argv) { } Printer.addView( llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S)); - auto Err = P->run(); - if (Err) - report_fatal_error(toString(std::move(Err))); + + if (!runPipeline(*P, *IP, *STI)) + return 1; + Printer.printReport(TOF->os()); continue; } @@ -543,9 +569,9 @@ int main(int argc, char **argv) { *STI, *IP, S, TimelineMaxIterations, TimelineMaxCycles)); } - auto Err = P->run(); - if (Err) - report_fatal_error(toString(std::move(Err))); + if (!runPipeline(*P, *IP, *STI)) + return 1; + Printer.printReport(TOF->os()); // Clear the InstrBuilder internal state in preparation for another round. |