aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-mca
diff options
context:
space:
mode:
authorMatt Davis <Matthew.Davis@sony.com>2018-08-13 18:11:48 +0000
committerMatt Davis <Matthew.Davis@sony.com>2018-08-13 18:11:48 +0000
commitfd195ce798b4b3a3ec67bd9c5120bd430bc2b007 (patch)
tree901d3510c9b46e65553f27e4f4a5950e4868fb66 /tools/llvm-mca
parent09af9d2e29f653220dd11ccda9e67d31cf79343f (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@339594 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-mca')
-rw-r--r--tools/llvm-mca/DispatchStage.cpp6
-rw-r--r--tools/llvm-mca/DispatchStage.h2
-rw-r--r--tools/llvm-mca/ExecuteStage.cpp8
-rw-r--r--tools/llvm-mca/ExecuteStage.h2
-rw-r--r--tools/llvm-mca/FetchStage.cpp12
-rw-r--r--tools/llvm-mca/FetchStage.h2
-rw-r--r--tools/llvm-mca/InstrBuilder.cpp72
-rw-r--r--tools/llvm-mca/InstrBuilder.h18
-rw-r--r--tools/llvm-mca/InstructionTables.cpp4
-rw-r--r--tools/llvm-mca/InstructionTables.h2
-rw-r--r--tools/llvm-mca/Pipeline.cpp28
-rw-r--r--tools/llvm-mca/Pipeline.h7
-rw-r--r--tools/llvm-mca/RegisterFile.cpp10
-rw-r--r--tools/llvm-mca/RegisterFile.h1
-rw-r--r--tools/llvm-mca/RetireStage.h2
-rw-r--r--tools/llvm-mca/Stage.h16
-rw-r--r--tools/llvm-mca/llvm-mca.cpp9
17 files changed, 131 insertions, 70 deletions
diff --git a/tools/llvm-mca/DispatchStage.cpp b/tools/llvm-mca/DispatchStage.cpp
index 1f508886c29..d397f72f4ab 100644
--- a/tools/llvm-mca/DispatchStage.cpp
+++ b/tools/llvm-mca/DispatchStage.cpp
@@ -136,12 +136,12 @@ void DispatchStage::cycleStart() {
CarryOver = CarryOver >= DispatchWidth ? CarryOver - DispatchWidth : 0U;
}
-bool DispatchStage::execute(InstRef &IR) {
+Stage::Status DispatchStage::execute(InstRef &IR) {
const InstrDesc &Desc = IR.getInstruction()->getDesc();
if (!isAvailable(Desc.NumMicroOps) || !canDispatch(IR))
- return false;
+ return Stage::Stop;
dispatch(IR);
- return true;
+ return Stage::Continue;
}
#ifndef NDEBUG
diff --git a/tools/llvm-mca/DispatchStage.h b/tools/llvm-mca/DispatchStage.h
index 4262a241c08..496c8f5fc2f 100644
--- a/tools/llvm-mca/DispatchStage.h
+++ b/tools/llvm-mca/DispatchStage.h
@@ -94,7 +94,7 @@ public:
// RetireStage::hasWorkToComplete will check for that case.
virtual bool hasWorkToComplete() const override final { return false; }
virtual void cycleStart() override final;
- virtual bool execute(InstRef &IR) override final;
+ virtual Status execute(InstRef &IR) override final;
void notifyDispatchStall(const InstRef &IR, unsigned EventType);
#ifndef NDEBUG
diff --git a/tools/llvm-mca/ExecuteStage.cpp b/tools/llvm-mca/ExecuteStage.cpp
index 1bc9c4a0dbd..25f90b46964 100644
--- a/tools/llvm-mca/ExecuteStage.cpp
+++ b/tools/llvm-mca/ExecuteStage.cpp
@@ -96,7 +96,7 @@ void ExecuteStage::cycleStart() {
}
// Schedule the instruction for execution on the hardware.
-bool ExecuteStage::execute(InstRef &IR) {
+Stage::Status ExecuteStage::execute(InstRef &IR) {
#ifndef NDEBUG
// Ensure that the HWS has not stored this instruction in its queues.
HWS.sanityCheck(IR);
@@ -112,7 +112,7 @@ bool ExecuteStage::execute(InstRef &IR) {
// Obtain a slot in the LSU. If we cannot reserve resources, return true, so
// that succeeding stages can make progress.
if (!HWS.reserveResources(IR))
- return true;
+ return Stage::Continue;
// If we did not return early, then the scheduler is ready for execution.
notifyInstructionReady(IR);
@@ -133,7 +133,7 @@ bool ExecuteStage::execute(InstRef &IR) {
// If we cannot issue immediately, the HWS will add IR to its ready queue for
// execution later, so we must return early here.
if (!HWS.issueImmediately(IR))
- return true;
+ return Stage::Continue;
LLVM_DEBUG(dbgs() << "[SCHEDULER] Instruction #" << IR
<< " issued immediately\n");
@@ -148,7 +148,7 @@ bool ExecuteStage::execute(InstRef &IR) {
if (IR.getInstruction()->isExecuted())
notifyInstructionExecuted(IR);
- return true;
+ return Stage::Continue;
}
void ExecuteStage::notifyInstructionExecuted(const InstRef &IR) {
diff --git a/tools/llvm-mca/ExecuteStage.h b/tools/llvm-mca/ExecuteStage.h
index 4914a9373e7..785d30382c0 100644
--- a/tools/llvm-mca/ExecuteStage.h
+++ b/tools/llvm-mca/ExecuteStage.h
@@ -46,7 +46,7 @@ public:
virtual bool hasWorkToComplete() const override final { return false; }
virtual void cycleStart() override final;
- virtual bool execute(InstRef &IR) override final;
+ virtual Status execute(InstRef &IR) override final;
void
notifyInstructionIssued(const InstRef &IR,
diff --git a/tools/llvm-mca/FetchStage.cpp b/tools/llvm-mca/FetchStage.cpp
index 3da117c0abc..acb5b05f347 100644
--- a/tools/llvm-mca/FetchStage.cpp
+++ b/tools/llvm-mca/FetchStage.cpp
@@ -19,14 +19,18 @@ namespace mca {
bool FetchStage::hasWorkToComplete() const { return SM.hasNext(); }
-bool FetchStage::execute(InstRef &IR) {
+Stage::Status FetchStage::execute(InstRef &IR) {
if (!SM.hasNext())
- return false;
+ return Stage::Stop;
const SourceRef SR = SM.peekNext();
- std::unique_ptr<Instruction> I = IB.createInstruction(*SR.second);
+ llvm::Expected<std::unique_ptr<Instruction>> InstOrErr =
+ IB.createInstruction(*SR.second);
+ if (!InstOrErr)
+ return InstOrErr.takeError();
+ std::unique_ptr<Instruction> I = std::move(*InstOrErr);
IR = InstRef(SR.first, I.get());
Instructions[IR.getSourceIndex()] = std::move(I);
- return true;
+ return Stage::Continue;
}
void FetchStage::postExecute() { SM.updateNext(); }
diff --git a/tools/llvm-mca/FetchStage.h b/tools/llvm-mca/FetchStage.h
index 620075d24fe..ab9668e81f2 100644
--- a/tools/llvm-mca/FetchStage.h
+++ b/tools/llvm-mca/FetchStage.h
@@ -35,7 +35,7 @@ public:
FetchStage &operator=(const FetchStage &Other) = delete;
bool hasWorkToComplete() const override final;
- bool execute(InstRef &IR) override final;
+ Status execute(InstRef &IR) override final;
void postExecute() override final;
void cycleEnd() override final;
};
diff --git a/tools/llvm-mca/InstrBuilder.cpp b/tools/llvm-mca/InstrBuilder.cpp
index 053b7b4e817..1688a56c0b6 100644
--- a/tools/llvm-mca/InstrBuilder.cpp
+++ b/tools/llvm-mca/InstrBuilder.cpp
@@ -155,8 +155,8 @@ static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc,
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 @@ void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
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 @@ void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
// 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 @@ void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
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 @@ void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
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 @@ void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
}
unsigned TotalUses = NumExplicitUses + NumImplicitUses;
if (!TotalUses)
- return;
+ return ErrorSuccess();
ID.Reads.resize(TotalUses);
for (unsigned CurrentUse = 0; CurrentUse < NumExplicitUses; ++CurrentUse) {
@@ -313,9 +319,11 @@ void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
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 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
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 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
<< " 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 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
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 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
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 @@ const InstrDesc &InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) {
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 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
// 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 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
++WriteIndex;
}
- return NewIS;
+ return std::move(NewIS);
}
} // namespace mca
diff --git a/tools/llvm-mca/InstrBuilder.h b/tools/llvm-mca/InstrBuilder.h
index b1f39d8d064..5888b08b3a3 100644
--- a/tools/llvm-mca/InstrBuilder.h
+++ b/tools/llvm-mca/InstrBuilder.h
@@ -22,6 +22,7 @@
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/Error.h"
namespace mca {
@@ -49,16 +50,18 @@ class InstrBuilder {
llvm::DenseMap<const llvm::MCInst *, std::unique_ptr<const InstrDesc>>
VariantDescriptors;
- const InstrDesc &createInstrDescImpl(const llvm::MCInst &MCI);
- const InstrDesc &getOrCreateInstrDesc(const llvm::MCInst &MCI);
+ llvm::Expected<const InstrDesc &>
+ createInstrDescImpl(const llvm::MCInst &MCI);
+ llvm::Expected<const InstrDesc &>
+ getOrCreateInstrDesc(const llvm::MCInst &MCI);
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);
+ llvm::Error populateWrites(InstrDesc &ID, const llvm::MCInst &MCI,
+ unsigned SchedClassID);
+ llvm::Error populateReads(InstrDesc &ID, const llvm::MCInst &MCI,
+ unsigned SchedClassID);
public:
InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii,
@@ -79,7 +82,8 @@ public:
void clear() { VariantDescriptors.shrink_and_clear(); }
- std::unique_ptr<Instruction> createInstruction(const llvm::MCInst &MCI);
+ llvm::Expected<std::unique_ptr<Instruction>>
+ createInstruction(const llvm::MCInst &MCI);
};
} // namespace mca
diff --git a/tools/llvm-mca/InstructionTables.cpp b/tools/llvm-mca/InstructionTables.cpp
index 9b9dbc37fbd..c786cfb63f4 100644
--- a/tools/llvm-mca/InstructionTables.cpp
+++ b/tools/llvm-mca/InstructionTables.cpp
@@ -21,7 +21,7 @@ namespace mca {
using namespace llvm;
-bool InstructionTables::execute(InstRef &IR) {
+Stage::Status InstructionTables::execute(InstRef &IR) {
ArrayRef<uint64_t> Masks = IB.getProcResourceMasks();
const InstrDesc &Desc = IR.getInstruction()->getDesc();
UsedResources.clear();
@@ -64,7 +64,7 @@ bool InstructionTables::execute(InstRef &IR) {
// Send a fake instruction issued event to all the views.
HWInstructionIssuedEvent Event(IR, UsedResources);
notifyEvent<HWInstructionIssuedEvent>(Event);
- return true;
+ return Stage::Continue;
}
} // namespace mca
diff --git a/tools/llvm-mca/InstructionTables.h b/tools/llvm-mca/InstructionTables.h
index 18e01998843..01ece0c8b22 100644
--- a/tools/llvm-mca/InstructionTables.h
+++ b/tools/llvm-mca/InstructionTables.h
@@ -36,7 +36,7 @@ public:
: Stage(), SM(Model), IB(Builder) {}
bool hasWorkToComplete() const override final { return false; }
- bool execute(InstRef &IR) override final;
+ Status execute(InstRef &IR) override final;
};
} // namespace mca
diff --git a/tools/llvm-mca/Pipeline.cpp b/tools/llvm-mca/Pipeline.cpp
index 7c937e7b48b..f099ec629b9 100644
--- a/tools/llvm-mca/Pipeline.cpp
+++ b/tools/llvm-mca/Pipeline.cpp
@@ -40,11 +40,15 @@ bool Pipeline::hasWorkToProcess() {
// This routine returns early if any stage returns 'false' after execute() is
// called on it.
-bool Pipeline::executeStages(InstRef &IR) {
- for (const std::unique_ptr<Stage> &S : Stages)
- if (!S->execute(IR))
- return false;
- return true;
+Stage::Status Pipeline::executeStages(InstRef &IR) {
+ for (const std::unique_ptr<Stage> &S : Stages) {
+ Stage::Status StatusOrErr = S->execute(IR);
+ if (!StatusOrErr)
+ return StatusOrErr.takeError();
+ else if (StatusOrErr.get() == Stage::Stop)
+ return Stage::Stop;
+ }
+ return Stage::Continue;
}
void Pipeline::preExecuteStages() {
@@ -57,16 +61,18 @@ void Pipeline::postExecuteStages() {
S->postExecute();
}
-void Pipeline::run() {
+llvm::Error Pipeline::run() {
while (hasWorkToProcess()) {
notifyCycleBegin();
- runCycle();
+ if (llvm::Error Err = runCycle())
+ return Err;
notifyCycleEnd();
++Cycles;
}
+ return llvm::ErrorSuccess();
}
-void Pipeline::runCycle() {
+llvm::Error Pipeline::runCycle() {
// Update the stages before we do any processing for this cycle.
InstRef IR;
for (auto &S : Stages)
@@ -76,13 +82,17 @@ void Pipeline::runCycle() {
// progress.
while (true) {
preExecuteStages();
- if (!executeStages(IR))
+ Stage::Status Val = executeStages(IR);
+ if (!Val)
+ return Val.takeError();
+ if (Val.get() == Stage::Stop)
break;
postExecuteStages();
}
for (auto &S : Stages)
S->cycleEnd();
+ return llvm::ErrorSuccess();
}
void Pipeline::notifyCycleBegin() {
diff --git a/tools/llvm-mca/Pipeline.h b/tools/llvm-mca/Pipeline.h
index 6916e422be3..5cf1afb7c11 100644
--- a/tools/llvm-mca/Pipeline.h
+++ b/tools/llvm-mca/Pipeline.h
@@ -19,6 +19,7 @@
#include "Scheduler.h"
#include "Stage.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/Error.h"
namespace mca {
@@ -60,9 +61,9 @@ class Pipeline {
unsigned Cycles;
void preExecuteStages();
- bool executeStages(InstRef &IR);
+ Stage::Status executeStages(InstRef &IR);
void postExecuteStages();
- void runCycle();
+ llvm::Error runCycle();
bool hasWorkToProcess();
void notifyCycleBegin();
@@ -71,7 +72,7 @@ class Pipeline {
public:
Pipeline() : Cycles(0) {}
void appendStage(std::unique_ptr<Stage> S) { Stages.push_back(std::move(S)); }
- void run();
+ llvm::Error run();
void addEventListener(HWEventListener *Listener);
};
} // namespace mca
diff --git a/tools/llvm-mca/RegisterFile.cpp b/tools/llvm-mca/RegisterFile.cpp
index 44de105b899..ea27a8b9b68 100644
--- a/tools/llvm-mca/RegisterFile.cpp
+++ b/tools/llvm-mca/RegisterFile.cpp
@@ -306,8 +306,14 @@ unsigned RegisterFile::isAvailable(ArrayRef<unsigned> Regs) const {
// microarchitectural registers in register file #0 was changed by the
// users via flag -reg-file-size. Alternatively, the scheduling model
// specified a too small number of registers for this register file.
- report_fatal_error(
- "Not enough microarchitectural registers in the register file");
+ LLVM_DEBUG(dbgs() << "Not enough registers in the register file.\n");
+
+ // FIXME: Normalize the instruction register count to match the
+ // NumPhysRegs value. This is a highly unusual case, and is not expected
+ // to occur. This normalization is hiding an inconsistency in either the
+ // scheduling model or in the value that the user might have specified
+ // for NumPhysRegs.
+ NumRegs = RMT.NumPhysRegs;
}
if (RMT.NumPhysRegs < (RMT.NumUsedPhysRegs + NumRegs))
diff --git a/tools/llvm-mca/RegisterFile.h b/tools/llvm-mca/RegisterFile.h
index 349e9789b6e..2e08b30f406 100644
--- a/tools/llvm-mca/RegisterFile.h
+++ b/tools/llvm-mca/RegisterFile.h
@@ -21,6 +21,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSchedule.h"
+#include "llvm/Support/Error.h"
namespace mca {
diff --git a/tools/llvm-mca/RetireStage.h b/tools/llvm-mca/RetireStage.h
index 8cf672d92c6..fc5f79ee79b 100644
--- a/tools/llvm-mca/RetireStage.h
+++ b/tools/llvm-mca/RetireStage.h
@@ -38,7 +38,7 @@ public:
return !RCU.isEmpty();
}
virtual void cycleStart() override final;
- virtual bool execute(InstRef &IR) override final { return true; }
+ virtual Status execute(InstRef &IR) override final { return Stage::Continue; }
void notifyInstructionRetired(const InstRef &IR);
void onInstructionExecuted(unsigned TokenID);
};
diff --git a/tools/llvm-mca/Stage.h b/tools/llvm-mca/Stage.h
index 9dbdcd89a33..15167129149 100644
--- a/tools/llvm-mca/Stage.h
+++ b/tools/llvm-mca/Stage.h
@@ -17,6 +17,7 @@
#define LLVM_TOOLS_LLVM_MCA_STAGE_H
#include "HWEventListener.h"
+#include "llvm/Support/Error.h"
#include <set>
namespace mca {
@@ -28,6 +29,19 @@ class Stage {
Stage &operator=(const Stage &Other) = delete;
std::set<HWEventListener *> Listeners;
+public:
+ /// A Stage's execute() returns Continue, Stop, or an error. Returning
+ /// Continue means that the stage successfully completed its 'execute'
+ /// action, and that the instruction being processed can be moved to the next
+ /// pipeline stage during this cycle. Continue allows the pipeline to
+ /// continue calling 'execute' on subsequent stages. Returning Stop
+ /// signifies that the stage ran into an error, and tells the pipeline to stop
+ /// passing the instruction to subsequent stages during this cycle. Any
+ /// failures that occur during 'execute' are represented by the error variant
+ /// that is provided by the Expected template.
+ enum State { Stop, Continue };
+ using Status = llvm::Expected<State>;
+
protected:
const std::set<HWEventListener *> &getListeners() const { return Listeners; }
@@ -60,7 +74,7 @@ public:
/// The primary action that this stage performs.
/// Returning false prevents successor stages from having their 'execute'
/// routine called. This can be called multiple times during a single cycle.
- virtual bool execute(InstRef &IR) = 0;
+ virtual Status execute(InstRef &IR) = 0;
/// Add a listener to receive callbacks during the execution of this stage.
void addListener(HWEventListener *Listener);
diff --git a/tools/llvm-mca/llvm-mca.cpp b/tools/llvm-mca/llvm-mca.cpp
index 5b91f4a8e4d..65c298cec1a 100644
--- a/tools/llvm-mca/llvm-mca.cpp
+++ b/tools/llvm-mca/llvm-mca.cpp
@@ -42,6 +42,7 @@
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
@@ -502,7 +503,9 @@ int main(int argc, char **argv) {
}
Printer.addView(
llvm::make_unique<mca::ResourcePressureView>(*STI, *IP, S));
- P->run();
+ auto Err = P->run();
+ if (Err)
+ report_fatal_error(toString(std::move(Err)));
Printer.printReport(TOF->os());
continue;
}
@@ -539,7 +542,9 @@ int main(int argc, char **argv) {
*STI, *IP, S, TimelineMaxIterations, TimelineMaxCycles));
}
- P->run();
+ auto Err = P->run();
+ if (Err)
+ report_fatal_error(toString(std::move(Err)));
Printer.printReport(TOF->os());
// Clear the InstrBuilder internal state in preparation for another round.