aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-mca
diff options
context:
space:
mode:
authorAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2018-07-09 12:30:55 +0000
committerAndrea Di Biagio <Andrea_DiBiagio@sn.scee.net>2018-07-09 12:30:55 +0000
commitd77ac0d3a5beca0cbc1517aa5994cfe24effa459 (patch)
tree460cc661a6a1d3695504e2e76b0ba36818e6ccc2 /tools/llvm-mca
parentceb3c09eb4cc3f2ab1aae2a5387525abab07b34f (diff)
[llvm-mca] report an error if the assembly sequence contains an unsupported instruction.
This is a short-term fix for PR38093. For now, we llvm::report_fatal_error if the instruction builder finds an unsupported instruction in the instruction stream. We need to revisit this fix once we start addressing PR38101. Essentially, we need a better framework for error handling. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@336543 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/llvm-mca')
-rw-r--r--tools/llvm-mca/InstrBuilder.cpp58
-rw-r--r--tools/llvm-mca/InstrBuilder.h11
-rw-r--r--tools/llvm-mca/llvm-mca.cpp2
3 files changed, 46 insertions, 25 deletions
diff --git a/tools/llvm-mca/InstrBuilder.cpp b/tools/llvm-mca/InstrBuilder.cpp
index 5b6b31b2eda..c0b25f783c8 100644
--- a/tools/llvm-mca/InstrBuilder.cpp
+++ b/tools/llvm-mca/InstrBuilder.cpp
@@ -17,8 +17,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
#define DEBUG_TYPE "llvm-mca"
@@ -155,10 +155,12 @@ static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc,
ID.MaxLatency = Latency < 0 ? 100U : static_cast<unsigned>(Latency);
}
-static void populateWrites(InstrDesc &ID, const MCInst &MCI,
- const MCInstrDesc &MCDesc,
- const MCSchedClassDesc &SCDesc,
- const MCSubtargetInfo &STI) {
+void 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);
+
// These are for now the (strong) assumptions made by this algorithm:
// * The number of explicit and implicit register definitions in a MCInst
// matches the number of explicit and implicit definitions according to
@@ -196,8 +198,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
const MCWriteLatencyEntry &WLE =
*STI.getWriteLatencyEntry(&SCDesc, CurrentDef);
// Conservatively default to MaxLatency.
- Write.Latency = WLE.Cycles < 0 ? ID.MaxLatency
- : static_cast<unsigned>(WLE.Cycles);
+ Write.Latency =
+ WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
Write.SClassOrWriteResourceID = WLE.WriteResourceID;
} else {
// Assign a default latency for this write.
@@ -226,8 +228,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
const MCWriteLatencyEntry &WLE =
*STI.getWriteLatencyEntry(&SCDesc, Index);
// Conservatively default to MaxLatency.
- Write.Latency = WLE.Cycles < 0 ? ID.MaxLatency
- : static_cast<unsigned>(WLE.Cycles);
+ Write.Latency =
+ WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
Write.SClassOrWriteResourceID = WLE.WriteResourceID;
} else {
// Assign a default latency for this write.
@@ -262,14 +264,13 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
}
}
-static void populateReads(InstrDesc &ID, const MCInst &MCI,
- const MCInstrDesc &MCDesc,
- const MCSchedClassDesc &SCDesc,
- const MCSubtargetInfo &STI) {
- unsigned SchedClassID = MCDesc.getSchedClass();
- unsigned i = 0;
+void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
+ unsigned SchedClassID) {
+ const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
unsigned NumExplicitDefs = MCDesc.getNumDefs();
+
// Skip explicit definitions.
+ unsigned i = 0;
for (; i < MCI.getNumOperands() && NumExplicitDefs; ++i) {
const MCOperand &Op = MCI.getOperand(i);
if (Op.isReg())
@@ -314,8 +315,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
assert(STI.getSchedModel().hasInstrSchedModel() &&
"Itineraries are not yet supported!");
- unsigned short Opcode = MCI.getOpcode();
// Obtain the instruction descriptor from the opcode.
+ unsigned short Opcode = MCI.getOpcode();
const MCInstrDesc &MCDesc = MCII.get(Opcode);
const MCSchedModel &SM = STI.getSchedModel();
@@ -332,10 +333,23 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
llvm::report_fatal_error("unable to resolve this variant class.");
}
+ // Check if this instruction is supported. Otherwise, report a fatal error.
+ const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
+ if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
+ std::string ToString;
+ llvm::raw_string_ostream OS(ToString);
+ WithColor::error() << "found an unsupported instruction in the input"
+ << " 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.");
+ }
+
// Create a new empty descriptor.
std::unique_ptr<InstrDesc> ID = llvm::make_unique<InstrDesc>();
-
- const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
ID->NumMicroOps = SCDesc.NumMicroOps;
if (MCDesc.isCall()) {
@@ -357,8 +371,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
initializeUsedResources(*ID, SCDesc, STI, ProcResourceMasks);
computeMaxLatency(*ID, MCDesc, SCDesc, STI);
- populateWrites(*ID, MCI, MCDesc, SCDesc, STI);
- populateReads(*ID, MCI, MCDesc, SCDesc, STI);
+ populateWrites(*ID, MCI, SchedClassID);
+ populateReads(*ID, MCI, SchedClassID);
LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n');
LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n');
@@ -428,8 +442,8 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
// Initialize writes.
unsigned WriteIndex = 0;
for (const WriteDescriptor &WD : D.Writes) {
- unsigned RegID =
- WD.isImplicitWrite() ? WD.RegisterID : MCI.getOperand(WD.OpIndex).getReg();
+ unsigned RegID = WD.isImplicitWrite() ? WD.RegisterID
+ : MCI.getOperand(WD.OpIndex).getReg();
// Check if this is a optional definition that references NoReg.
if (WD.IsOptionalDef && !RegID) {
++WriteIndex;
diff --git a/tools/llvm-mca/InstrBuilder.h b/tools/llvm-mca/InstrBuilder.h
index e5e80d7cf79..69a53b6fec2 100644
--- a/tools/llvm-mca/InstrBuilder.h
+++ b/tools/llvm-mca/InstrBuilder.h
@@ -17,6 +17,7 @@
#include "Instruction.h"
#include "Support.h"
+#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -41,6 +42,7 @@ class InstrBuilder {
const llvm::MCInstrInfo &MCII;
const llvm::MCRegisterInfo &MRI;
const llvm::MCInstrAnalysis &MCIA;
+ llvm::MCInstPrinter &MCIP;
llvm::SmallVector<uint64_t, 8> ProcResourceMasks;
llvm::DenseMap<unsigned short, std::unique_ptr<const InstrDesc>> Descriptors;
@@ -51,11 +53,16 @@ class InstrBuilder {
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);
+
public:
InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii,
const llvm::MCRegisterInfo &mri,
- const llvm::MCInstrAnalysis &mcia)
- : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia),
+ const llvm::MCInstrAnalysis &mcia, llvm::MCInstPrinter &mcip)
+ : STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), MCIP(mcip),
ProcResourceMasks(STI.getSchedModel().getNumProcResourceKinds()) {
computeProcResourceMasks(STI.getSchedModel(), ProcResourceMasks);
}
diff --git a/tools/llvm-mca/llvm-mca.cpp b/tools/llvm-mca/llvm-mca.cpp
index 9398a547fd4..97de338d960 100644
--- a/tools/llvm-mca/llvm-mca.cpp
+++ b/tools/llvm-mca/llvm-mca.cpp
@@ -460,7 +460,7 @@ int main(int argc, char **argv) {
Width = DispatchWidth;
// Create an instruction builder.
- mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA);
+ mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA, *IP);
// Create a context to control ownership of the pipeline hardware.
mca::Context MCA(*MRI, *STI);