[llvm-mca] Propagate fatal llvm-mca errors from library classes to driver.
Summary:
This patch introduces error handling to propagate the errors from llvm-mca library classes (or what will become library classes) up to the driver. This patch also introduces an enum to make clearer the intention of the return value for Stage::execute.
This supports PR38101.
Reviewers: andreadb, courbet, RKSimon
Reviewed By: andreadb
Subscribers: llvm-commits, tschuett, gbedwell
Differential Revision: https://reviews.llvm.org/D50561
llvm-svn: 339594
diff --git a/llvm/tools/llvm-mca/InstrBuilder.cpp b/llvm/tools/llvm-mca/InstrBuilder.cpp
index 053b7b4..1688a56 100644
--- a/llvm/tools/llvm-mca/InstrBuilder.cpp
+++ b/llvm/tools/llvm-mca/InstrBuilder.cpp
@@ -155,8 +155,8 @@
ID.MaxLatency = Latency < 0 ? 100U : static_cast<unsigned>(Latency);
}
-void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
- unsigned SchedClassID) {
+Error 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);
@@ -215,9 +215,11 @@
CurrentDef++;
}
- if (CurrentDef != NumExplicitDefs)
- llvm::report_fatal_error(
- "error: Expected more register operand definitions. ");
+ if (CurrentDef != NumExplicitDefs) {
+ return make_error<StringError>(
+ "error: Expected more register operand definitions.",
+ inconvertibleErrorCode());
+ }
CurrentDef = 0;
for (CurrentDef = 0; CurrentDef < NumImplicitDefs; ++CurrentDef) {
@@ -253,10 +255,10 @@
// MCInst sequence.
const MCOperand &Op = MCI.getOperand(MCI.getNumOperands() - 1);
if (i == MCI.getNumOperands() || !Op.isReg())
- llvm::report_fatal_error(
+ return make_error<StringError>(
"error: expected a register operand for an optional "
- "definition. Instruction has not be correctly analyzed.\n",
- false);
+ "definition. Instruction has not be correctly analyzed.",
+ inconvertibleErrorCode());
WriteDescriptor &Write = ID.Writes[TotalDefs - 1];
Write.OpIndex = MCI.getNumOperands() - 1;
@@ -265,10 +267,12 @@
Write.SClassOrWriteResourceID = 0;
Write.IsOptionalDef = true;
}
+
+ return ErrorSuccess();
}
-void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
- unsigned SchedClassID) {
+Error InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
+ unsigned SchedClassID) {
const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
unsigned NumExplicitDefs = MCDesc.getNumDefs();
@@ -280,9 +284,11 @@
NumExplicitDefs--;
}
- if (NumExplicitDefs)
- llvm::report_fatal_error(
- "error: Expected more register operand definitions. ", false);
+ if (NumExplicitDefs) {
+ return make_error<StringError>(
+ "error: Expected more register operand definitions. ",
+ inconvertibleErrorCode());
+ }
unsigned NumExplicitUses = MCI.getNumOperands() - i;
unsigned NumImplicitUses = MCDesc.getNumImplicitUses();
@@ -292,7 +298,7 @@
}
unsigned TotalUses = NumExplicitUses + NumImplicitUses;
if (!TotalUses)
- return;
+ return ErrorSuccess();
ID.Reads.resize(TotalUses);
for (unsigned CurrentUse = 0; CurrentUse < NumExplicitUses; ++CurrentUse) {
@@ -313,9 +319,11 @@
LLVM_DEBUG(dbgs() << "\t\t[Use] OpIdx=" << Read.OpIndex << ", RegisterID="
<< MRI.getName(Read.RegisterID) << '\n');
}
+ return ErrorSuccess();
}
-const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
+Expected<const InstrDesc &>
+InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
assert(STI.getSchedModel().hasInstrSchedModel() &&
"Itineraries are not yet supported!");
@@ -333,11 +341,13 @@
while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant())
SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &MCI, CPUID);
- if (!SchedClassID)
- llvm::report_fatal_error("unable to resolve this variant class.");
+ if (!SchedClassID) {
+ return make_error<StringError>("unable to resolve this variant class.",
+ inconvertibleErrorCode());
+ }
}
- // Check if this instruction is supported. Otherwise, report a fatal error.
+ // Check if this instruction is supported. Otherwise, report an error.
const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
std::string ToString;
@@ -346,10 +356,10 @@
<< " 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.");
+ return make_error<StringError>(
+ "Don't know how to analyze unsupported instructions",
+ inconvertibleErrorCode());
}
// Create a new empty descriptor.
@@ -375,8 +385,10 @@
initializeUsedResources(*ID, SCDesc, STI, ProcResourceMasks);
computeMaxLatency(*ID, MCDesc, SCDesc, STI);
- populateWrites(*ID, MCI, SchedClassID);
- populateReads(*ID, MCI, SchedClassID);
+ if (auto Err = populateWrites(*ID, MCI, SchedClassID))
+ return std::move(Err);
+ if (auto Err = populateReads(*ID, MCI, SchedClassID))
+ return std::move(Err);
LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n');
LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n');
@@ -392,7 +404,8 @@
return *VariantDescriptors[&MCI];
}
-const InstrDesc &InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) {
+Expected<const InstrDesc &>
+InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) {
if (Descriptors.find_as(MCI.getOpcode()) != Descriptors.end())
return *Descriptors[MCI.getOpcode()];
@@ -402,9 +415,12 @@
return createInstrDescImpl(MCI);
}
-std::unique_ptr<Instruction>
+Expected<std::unique_ptr<Instruction>>
InstrBuilder::createInstruction(const MCInst &MCI) {
- const InstrDesc &D = getOrCreateInstrDesc(MCI);
+ Expected<const InstrDesc &> DescOrErr = getOrCreateInstrDesc(MCI);
+ if (!DescOrErr)
+ return DescOrErr.takeError();
+ const InstrDesc &D = *DescOrErr;
std::unique_ptr<Instruction> NewIS = llvm::make_unique<Instruction>(D);
// Initialize Reads first.
@@ -433,7 +449,7 @@
// Early exit if there are no writes.
if (D.Writes.empty())
- return NewIS;
+ return std::move(NewIS);
// Track register writes that implicitly clear the upper portion of the
// underlying super-registers using an APInt.
@@ -464,6 +480,6 @@
++WriteIndex;
}
- return NewIS;
+ return std::move(NewIS);
}
} // namespace mca