1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

[llvm-mca] [llvm-mca] Improved error handling and error reporting from class InstrBuilder.

A new class named InstructionError has been added to Support.h in order to
improve the error reporting from class InstrBuilder.
The llvm-mca driver is responsible for handling InstructionError objects, and
printing them out to stderr.

The goal of this patch is to remove all the remaining error handling logic from
the library code.
In particular, this allows us to:
 - Simplify the logic in InstrBuilder by removing a needless dependency from
MCInstrPrinter.
 - Centralize all the error halding logic in a new function named 'runPipeline'
(see llvm-mca.cpp).

This is also a first step towards generalizing class InstrBuilder, so that in
future, we will be able to reuse its logic to also "lower" MachineInstr to
mca::Instruction objects.

Differential Revision: https://reviews.llvm.org/D53585

llvm-svn: 345129
This commit is contained in:
Andrea Di Biagio 2018-10-24 10:56:47 +00:00
parent 91857d1ecd
commit 694545a47e
5 changed files with 84 additions and 47 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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.

View File

@ -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.