Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit d77ac0d

Browse files
committed
[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
1 parent ceb3c09 commit d77ac0d

File tree

4 files changed

+52
-25
lines changed

4 files changed

+52
-25
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s 2>&1 | FileCheck %s
2+
3+
bzhi %eax, %ebx, %ecx
4+
5+
# CHECK: error: found an unsupported instruction in the input assembly sequence.
6+
# CHECK-NEXT: note: instruction: bzhil %eax, %ebx, %ecx

tools/llvm-mca/InstrBuilder.cpp

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
#include "llvm/ADT/DenseMap.h"
1818
#include "llvm/MC/MCInst.h"
1919
#include "llvm/Support/Debug.h"
20-
#include "llvm/Support/raw_ostream.h"
2120
#include "llvm/Support/WithColor.h"
21+
#include "llvm/Support/raw_ostream.h"
2222

2323
#define DEBUG_TYPE "llvm-mca"
2424

@@ -155,10 +155,12 @@ static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc,
155155
ID.MaxLatency = Latency < 0 ? 100U : static_cast<unsigned>(Latency);
156156
}
157157

158-
static void populateWrites(InstrDesc &ID, const MCInst &MCI,
159-
const MCInstrDesc &MCDesc,
160-
const MCSchedClassDesc &SCDesc,
161-
const MCSubtargetInfo &STI) {
158+
void InstrBuilder::populateWrites(InstrDesc &ID, const MCInst &MCI,
159+
unsigned SchedClassID) {
160+
const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
161+
const MCSchedModel &SM = STI.getSchedModel();
162+
const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
163+
162164
// These are for now the (strong) assumptions made by this algorithm:
163165
// * The number of explicit and implicit register definitions in a MCInst
164166
// matches the number of explicit and implicit definitions according to
@@ -196,8 +198,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
196198
const MCWriteLatencyEntry &WLE =
197199
*STI.getWriteLatencyEntry(&SCDesc, CurrentDef);
198200
// Conservatively default to MaxLatency.
199-
Write.Latency = WLE.Cycles < 0 ? ID.MaxLatency
200-
: static_cast<unsigned>(WLE.Cycles);
201+
Write.Latency =
202+
WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
201203
Write.SClassOrWriteResourceID = WLE.WriteResourceID;
202204
} else {
203205
// Assign a default latency for this write.
@@ -226,8 +228,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
226228
const MCWriteLatencyEntry &WLE =
227229
*STI.getWriteLatencyEntry(&SCDesc, Index);
228230
// Conservatively default to MaxLatency.
229-
Write.Latency = WLE.Cycles < 0 ? ID.MaxLatency
230-
: static_cast<unsigned>(WLE.Cycles);
231+
Write.Latency =
232+
WLE.Cycles < 0 ? ID.MaxLatency : static_cast<unsigned>(WLE.Cycles);
231233
Write.SClassOrWriteResourceID = WLE.WriteResourceID;
232234
} else {
233235
// Assign a default latency for this write.
@@ -262,14 +264,13 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
262264
}
263265
}
264266

265-
static void populateReads(InstrDesc &ID, const MCInst &MCI,
266-
const MCInstrDesc &MCDesc,
267-
const MCSchedClassDesc &SCDesc,
268-
const MCSubtargetInfo &STI) {
269-
unsigned SchedClassID = MCDesc.getSchedClass();
270-
unsigned i = 0;
267+
void InstrBuilder::populateReads(InstrDesc &ID, const MCInst &MCI,
268+
unsigned SchedClassID) {
269+
const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
271270
unsigned NumExplicitDefs = MCDesc.getNumDefs();
271+
272272
// Skip explicit definitions.
273+
unsigned i = 0;
273274
for (; i < MCI.getNumOperands() && NumExplicitDefs; ++i) {
274275
const MCOperand &Op = MCI.getOperand(i);
275276
if (Op.isReg())
@@ -314,8 +315,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
314315
assert(STI.getSchedModel().hasInstrSchedModel() &&
315316
"Itineraries are not yet supported!");
316317

317-
unsigned short Opcode = MCI.getOpcode();
318318
// Obtain the instruction descriptor from the opcode.
319+
unsigned short Opcode = MCI.getOpcode();
319320
const MCInstrDesc &MCDesc = MCII.get(Opcode);
320321
const MCSchedModel &SM = STI.getSchedModel();
321322

@@ -332,10 +333,23 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
332333
llvm::report_fatal_error("unable to resolve this variant class.");
333334
}
334335

336+
// Check if this instruction is supported. Otherwise, report a fatal error.
337+
const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
338+
if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
339+
std::string ToString;
340+
llvm::raw_string_ostream OS(ToString);
341+
WithColor::error() << "found an unsupported instruction in the input"
342+
<< " assembly sequence.\n";
343+
MCIP.printInst(&MCI, OS, "", STI);
344+
OS.flush();
345+
346+
WithColor::note() << "instruction: " << ToString << '\n';
347+
llvm::report_fatal_error(
348+
"Don't know how to analyze unsupported instructions.");
349+
}
350+
335351
// Create a new empty descriptor.
336352
std::unique_ptr<InstrDesc> ID = llvm::make_unique<InstrDesc>();
337-
338-
const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
339353
ID->NumMicroOps = SCDesc.NumMicroOps;
340354

341355
if (MCDesc.isCall()) {
@@ -357,8 +371,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
357371

358372
initializeUsedResources(*ID, SCDesc, STI, ProcResourceMasks);
359373
computeMaxLatency(*ID, MCDesc, SCDesc, STI);
360-
populateWrites(*ID, MCI, MCDesc, SCDesc, STI);
361-
populateReads(*ID, MCI, MCDesc, SCDesc, STI);
374+
populateWrites(*ID, MCI, SchedClassID);
375+
populateReads(*ID, MCI, SchedClassID);
362376

363377
LLVM_DEBUG(dbgs() << "\t\tMaxLatency=" << ID->MaxLatency << '\n');
364378
LLVM_DEBUG(dbgs() << "\t\tNumMicroOps=" << ID->NumMicroOps << '\n');
@@ -428,8 +442,8 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
428442
// Initialize writes.
429443
unsigned WriteIndex = 0;
430444
for (const WriteDescriptor &WD : D.Writes) {
431-
unsigned RegID =
432-
WD.isImplicitWrite() ? WD.RegisterID : MCI.getOperand(WD.OpIndex).getReg();
445+
unsigned RegID = WD.isImplicitWrite() ? WD.RegisterID
446+
: MCI.getOperand(WD.OpIndex).getReg();
433447
// Check if this is a optional definition that references NoReg.
434448
if (WD.IsOptionalDef && !RegID) {
435449
++WriteIndex;

tools/llvm-mca/InstrBuilder.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "Instruction.h"
1919
#include "Support.h"
20+
#include "llvm/MC/MCInstPrinter.h"
2021
#include "llvm/MC/MCInstrAnalysis.h"
2122
#include "llvm/MC/MCInstrInfo.h"
2223
#include "llvm/MC/MCRegisterInfo.h"
@@ -41,6 +42,7 @@ class InstrBuilder {
4142
const llvm::MCInstrInfo &MCII;
4243
const llvm::MCRegisterInfo &MRI;
4344
const llvm::MCInstrAnalysis &MCIA;
45+
llvm::MCInstPrinter &MCIP;
4446
llvm::SmallVector<uint64_t, 8> ProcResourceMasks;
4547

4648
llvm::DenseMap<unsigned short, std::unique_ptr<const InstrDesc>> Descriptors;
@@ -51,11 +53,16 @@ class InstrBuilder {
5153
InstrBuilder(const InstrBuilder &) = delete;
5254
InstrBuilder &operator=(const InstrBuilder &) = delete;
5355

56+
void populateWrites(InstrDesc &ID, const llvm::MCInst &MCI,
57+
unsigned SchedClassID);
58+
void populateReads(InstrDesc &ID, const llvm::MCInst &MCI,
59+
unsigned SchedClassID);
60+
5461
public:
5562
InstrBuilder(const llvm::MCSubtargetInfo &sti, const llvm::MCInstrInfo &mcii,
5663
const llvm::MCRegisterInfo &mri,
57-
const llvm::MCInstrAnalysis &mcia)
58-
: STI(sti), MCII(mcii), MRI(mri), MCIA(mcia),
64+
const llvm::MCInstrAnalysis &mcia, llvm::MCInstPrinter &mcip)
65+
: STI(sti), MCII(mcii), MRI(mri), MCIA(mcia), MCIP(mcip),
5966
ProcResourceMasks(STI.getSchedModel().getNumProcResourceKinds()) {
6067
computeProcResourceMasks(STI.getSchedModel(), ProcResourceMasks);
6168
}

tools/llvm-mca/llvm-mca.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ int main(int argc, char **argv) {
460460
Width = DispatchWidth;
461461

462462
// Create an instruction builder.
463-
mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA);
463+
mca::InstrBuilder IB(*STI, *MCII, *MRI, *MCIA, *IP);
464464

465465
// Create a context to control ownership of the pipeline hardware.
466466
mca::Context MCA(*MRI, *STI);

0 commit comments

Comments
 (0)