17
17
#include " llvm/ADT/DenseMap.h"
18
18
#include " llvm/MC/MCInst.h"
19
19
#include " llvm/Support/Debug.h"
20
- #include " llvm/Support/raw_ostream.h"
21
20
#include " llvm/Support/WithColor.h"
21
+ #include " llvm/Support/raw_ostream.h"
22
22
23
23
#define DEBUG_TYPE " llvm-mca"
24
24
@@ -155,10 +155,12 @@ static void computeMaxLatency(InstrDesc &ID, const MCInstrDesc &MCDesc,
155
155
ID.MaxLatency = Latency < 0 ? 100U : static_cast <unsigned >(Latency);
156
156
}
157
157
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
+
162
164
// These are for now the (strong) assumptions made by this algorithm:
163
165
// * The number of explicit and implicit register definitions in a MCInst
164
166
// matches the number of explicit and implicit definitions according to
@@ -196,8 +198,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
196
198
const MCWriteLatencyEntry &WLE =
197
199
*STI.getWriteLatencyEntry (&SCDesc, CurrentDef);
198
200
// 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 );
201
203
Write.SClassOrWriteResourceID = WLE.WriteResourceID ;
202
204
} else {
203
205
// Assign a default latency for this write.
@@ -226,8 +228,8 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
226
228
const MCWriteLatencyEntry &WLE =
227
229
*STI.getWriteLatencyEntry (&SCDesc, Index);
228
230
// 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 );
231
233
Write.SClassOrWriteResourceID = WLE.WriteResourceID ;
232
234
} else {
233
235
// Assign a default latency for this write.
@@ -262,14 +264,13 @@ static void populateWrites(InstrDesc &ID, const MCInst &MCI,
262
264
}
263
265
}
264
266
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 ());
271
270
unsigned NumExplicitDefs = MCDesc.getNumDefs ();
271
+
272
272
// Skip explicit definitions.
273
+ unsigned i = 0 ;
273
274
for (; i < MCI.getNumOperands () && NumExplicitDefs; ++i) {
274
275
const MCOperand &Op = MCI.getOperand (i);
275
276
if (Op.isReg ())
@@ -314,8 +315,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
314
315
assert (STI.getSchedModel ().hasInstrSchedModel () &&
315
316
" Itineraries are not yet supported!" );
316
317
317
- unsigned short Opcode = MCI.getOpcode ();
318
318
// Obtain the instruction descriptor from the opcode.
319
+ unsigned short Opcode = MCI.getOpcode ();
319
320
const MCInstrDesc &MCDesc = MCII.get (Opcode);
320
321
const MCSchedModel &SM = STI.getSchedModel ();
321
322
@@ -332,10 +333,23 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
332
333
llvm::report_fatal_error (" unable to resolve this variant class." );
333
334
}
334
335
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
+
335
351
// Create a new empty descriptor.
336
352
std::unique_ptr<InstrDesc> ID = llvm::make_unique<InstrDesc>();
337
-
338
- const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc (SchedClassID);
339
353
ID->NumMicroOps = SCDesc.NumMicroOps ;
340
354
341
355
if (MCDesc.isCall ()) {
@@ -357,8 +371,8 @@ const InstrDesc &InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
357
371
358
372
initializeUsedResources (*ID, SCDesc, STI, ProcResourceMasks);
359
373
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 );
362
376
363
377
LLVM_DEBUG (dbgs () << " \t\t MaxLatency=" << ID->MaxLatency << ' \n ' );
364
378
LLVM_DEBUG (dbgs () << " \t\t NumMicroOps=" << ID->NumMicroOps << ' \n ' );
@@ -428,8 +442,8 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
428
442
// Initialize writes.
429
443
unsigned WriteIndex = 0 ;
430
444
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 ();
433
447
// Check if this is a optional definition that references NoReg.
434
448
if (WD.IsOptionalDef && !RegID) {
435
449
++WriteIndex;
0 commit comments