forked from OSchip/llvm-project
[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
This commit is contained in:
parent
1a3caef148
commit
4bcf369d9b
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue