[llvm] r339594 - [llvm-mca] Propagate fatal llvm-mca errors from library classes to driver.

Matt Davis via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 13 11:11:49 PDT 2018


Author: mattd
Date: Mon Aug 13 11:11:48 2018
New Revision: 339594

URL: http://llvm.org/viewvc/llvm-project?rev=339594&view=rev
Log:
[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

Modified:
    llvm/trunk/tools/llvm-mca/DispatchStage.cpp
    llvm/trunk/tools/llvm-mca/DispatchStage.h
    llvm/trunk/tools/llvm-mca/ExecuteStage.cpp
    llvm/trunk/tools/llvm-mca/ExecuteStage.h
    llvm/trunk/tools/llvm-mca/FetchStage.cpp
    llvm/trunk/tools/llvm-mca/FetchStage.h
    llvm/trunk/tools/llvm-mca/InstrBuilder.cpp
    llvm/trunk/tools/llvm-mca/InstrBuilder.h
    llvm/trunk/tools/llvm-mca/InstructionTables.cpp
    llvm/trunk/tools/llvm-mca/InstructionTables.h
    llvm/trunk/tools/llvm-mca/Pipeline.cpp
    llvm/trunk/tools/llvm-mca/Pipeline.h
    llvm/trunk/tools/llvm-mca/RegisterFile.cpp
    llvm/trunk/tools/llvm-mca/RegisterFile.h
    llvm/trunk/tools/llvm-mca/RetireStage.h
    llvm/trunk/tools/llvm-mca/Stage.h
    llvm/trunk/tools/llvm-mca/llvm-mca.cpp

Modified: llvm/trunk/tools/llvm-mca/DispatchStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/DispatchStage.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/DispatchStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/DispatchStage.cpp Mon Aug 13 11:11:48 2018
@@ -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

Modified: llvm/trunk/tools/llvm-mca/DispatchStage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/DispatchStage.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/DispatchStage.h (original)
+++ llvm/trunk/tools/llvm-mca/DispatchStage.h Mon Aug 13 11:11:48 2018
@@ -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

Modified: llvm/trunk/tools/llvm-mca/ExecuteStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/ExecuteStage.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/ExecuteStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/ExecuteStage.cpp Mon Aug 13 11:11:48 2018
@@ -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) {

Modified: llvm/trunk/tools/llvm-mca/ExecuteStage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/ExecuteStage.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/ExecuteStage.h (original)
+++ llvm/trunk/tools/llvm-mca/ExecuteStage.h Mon Aug 13 11:11:48 2018
@@ -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,

Modified: llvm/trunk/tools/llvm-mca/FetchStage.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/FetchStage.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/FetchStage.cpp (original)
+++ llvm/trunk/tools/llvm-mca/FetchStage.cpp Mon Aug 13 11:11:48 2018
@@ -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(); }

Modified: llvm/trunk/tools/llvm-mca/FetchStage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/FetchStage.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/FetchStage.h (original)
+++ llvm/trunk/tools/llvm-mca/FetchStage.h Mon Aug 13 11:11:48 2018
@@ -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;
 };

Modified: llvm/trunk/tools/llvm-mca/InstrBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/InstrBuilder.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/InstrBuilder.cpp (original)
+++ llvm/trunk/tools/llvm-mca/InstrBuilder.cpp Mon Aug 13 11:11:48 2018
@@ -155,8 +155,8 @@ static void computeMaxLatency(InstrDesc
   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(InstrD
     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(InstrD
     // 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(InstrD
     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(InstrDe
       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(InstrDe
   }
   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(InstrDe
     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::createIns
     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::createIns
                        << " 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::createIns
 
   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::createIns
   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::getOrCrea
   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 MC
 
   // 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 MC
     ++WriteIndex;
   }
 
-  return NewIS;
+  return std::move(NewIS);
 }
 } // namespace mca

Modified: llvm/trunk/tools/llvm-mca/InstrBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/InstrBuilder.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/InstrBuilder.h (original)
+++ llvm/trunk/tools/llvm-mca/InstrBuilder.h Mon Aug 13 11:11:48 2018
@@ -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
 

Modified: llvm/trunk/tools/llvm-mca/InstructionTables.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/InstructionTables.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/InstructionTables.cpp (original)
+++ llvm/trunk/tools/llvm-mca/InstructionTables.cpp Mon Aug 13 11:11:48 2018
@@ -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
   // Send a fake instruction issued event to all the views.
   HWInstructionIssuedEvent Event(IR, UsedResources);
   notifyEvent<HWInstructionIssuedEvent>(Event);
-  return true;
+  return Stage::Continue;
 }
 
 } // namespace mca

Modified: llvm/trunk/tools/llvm-mca/InstructionTables.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/InstructionTables.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/InstructionTables.h (original)
+++ llvm/trunk/tools/llvm-mca/InstructionTables.h Mon Aug 13 11:11:48 2018
@@ -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
 

Modified: llvm/trunk/tools/llvm-mca/Pipeline.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Pipeline.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Pipeline.cpp (original)
+++ llvm/trunk/tools/llvm-mca/Pipeline.cpp Mon Aug 13 11:11:48 2018
@@ -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() {

Modified: llvm/trunk/tools/llvm-mca/Pipeline.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Pipeline.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Pipeline.h (original)
+++ llvm/trunk/tools/llvm-mca/Pipeline.h Mon Aug 13 11:11:48 2018
@@ -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

Modified: llvm/trunk/tools/llvm-mca/RegisterFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/RegisterFile.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/RegisterFile.cpp (original)
+++ llvm/trunk/tools/llvm-mca/RegisterFile.cpp Mon Aug 13 11:11:48 2018
@@ -306,8 +306,14 @@ unsigned RegisterFile::isAvailable(Array
       // 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))

Modified: llvm/trunk/tools/llvm-mca/RegisterFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/RegisterFile.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/RegisterFile.h (original)
+++ llvm/trunk/tools/llvm-mca/RegisterFile.h Mon Aug 13 11:11:48 2018
@@ -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 {
 

Modified: llvm/trunk/tools/llvm-mca/RetireStage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/RetireStage.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/RetireStage.h (original)
+++ llvm/trunk/tools/llvm-mca/RetireStage.h Mon Aug 13 11:11:48 2018
@@ -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);
 };

Modified: llvm/trunk/tools/llvm-mca/Stage.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/Stage.h?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/Stage.h (original)
+++ llvm/trunk/tools/llvm-mca/Stage.h Mon Aug 13 11:11:48 2018
@@ -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);

Modified: llvm/trunk/tools/llvm-mca/llvm-mca.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-mca/llvm-mca.cpp?rev=339594&r1=339593&r2=339594&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-mca/llvm-mca.cpp (original)
+++ llvm/trunk/tools/llvm-mca/llvm-mca.cpp Mon Aug 13 11:11:48 2018
@@ -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.




More information about the llvm-commits mailing list