diff options
author | Matt Davis <Matthew.Davis@sony.com> | 2018-08-13 18:11:48 +0000 |
---|---|---|
committer | Matt Davis <Matthew.Davis@sony.com> | 2018-08-13 18:11:48 +0000 |
commit | fd195ce798b4b3a3ec67bd9c5120bd430bc2b007 (patch) | |
tree | 901d3510c9b46e65553f27e4f4a5950e4868fb66 /tools/llvm-mca | |
parent | 09af9d2e29f653220dd11ccda9e67d31cf79343f (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.cpp | 6 | ||||
-rw-r--r-- | tools/llvm-mca/DispatchStage.h | 2 | ||||
-rw-r--r-- | tools/llvm-mca/ExecuteStage.cpp | 8 | ||||
-rw-r--r-- | tools/llvm-mca/ExecuteStage.h | 2 | ||||
-rw-r--r-- | tools/llvm-mca/FetchStage.cpp | 12 | ||||
-rw-r--r-- | tools/llvm-mca/FetchStage.h | 2 | ||||
-rw-r--r-- | tools/llvm-mca/InstrBuilder.cpp | 72 | ||||
-rw-r--r-- | tools/llvm-mca/InstrBuilder.h | 18 | ||||
-rw-r--r-- | tools/llvm-mca/InstructionTables.cpp | 4 | ||||
-rw-r--r-- | tools/llvm-mca/InstructionTables.h | 2 | ||||
-rw-r--r-- | tools/llvm-mca/Pipeline.cpp | 28 | ||||
-rw-r--r-- | tools/llvm-mca/Pipeline.h | 7 | ||||
-rw-r--r-- | tools/llvm-mca/RegisterFile.cpp | 10 | ||||
-rw-r--r-- | tools/llvm-mca/RegisterFile.h | 1 | ||||
-rw-r--r-- | tools/llvm-mca/RetireStage.h | 2 | ||||
-rw-r--r-- | tools/llvm-mca/Stage.h | 16 | ||||
-rw-r--r-- | tools/llvm-mca/llvm-mca.cpp | 9 |
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. |