Skip to content

Commit 5f79f75

Browse files
[llvm-mca] Add -skip-unsupported-instructions option (#89733)
Prior to this patch, if llvm-mca encountered an instruction which parses but has no scheduler info, the instruction is always reported as unsupported, and llvm-mca halts with an error. However, it would still be useful to allow MCA to continue even in the case of instructions lacking scheduling information. Obviously if scheduling information is lacking, it's not possible to give an accurate analysis for those instructions, and therefore a warning is emitted. A user could previously have worked around such unsupported instructions manually by deleting such instructions from the input, but this provides them a way of doing this for bulk inputs where they may not have a list of such unsupported instructions to drop up front. Note that this behaviour of instructions with no scheduling information under -skip-unsupported-instructions is analagous to current instructions which fail to parse: those are currently dropped from the input with a message printed, after which the analysis continues. ~Testing the feature is a little awkward currently, it relies on an instruction which is currently marked as unsupported, which may not remain so; should the situation change it would be necessary to find an alternative unsupported instruction or drop the test.~ A test is added to check that analysis still reports an error if all instructions are removed from the input, to mirror the current behaviour of giving an error if no instructions are supplied.
1 parent e1622e1 commit 5f79f75

File tree

5 files changed

+116
-10
lines changed

5 files changed

+116
-10
lines changed

llvm/lib/MCA/InstrBuilder.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,7 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI,
542542
const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);
543543
if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
544544
return make_error<InstructionError<MCInst>>(
545-
"found an unsupported instruction in the input assembly sequence.",
546-
MCI);
545+
"found an unsupported instruction in the input assembly sequence", MCI);
547546
}
548547

549548
LLVM_DEBUG(dbgs() << "\n\t\tOpcode Name= " << MCII.getName(Opcode) << '\n');
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -skip-unsupported-instructions %s |& FileCheck --check-prefixes=CHECK-ALL,CHECK-SKIP %s
2+
# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s |& FileCheck --check-prefixes=CHECK-ALL,CHECK-ERROR %s
3+
4+
# Test defends that if all instructions are skipped leaving an empty input, an error is printed.
5+
6+
bzhi %eax, %ebx, %ecx
7+
8+
# CHECK-ALL-NOT: error
9+
10+
# CHECK-ERROR: error: found an unsupported instruction in the input assembly sequence, use -skip-unsupported-instructions to ignore.
11+
12+
# CHECK-SKIP: warning: found an unsupported instruction in the input assembly sequence, skipping with -skip-unsupported-instructions, note accuracy will be impacted:
13+
# CHECK-SKIP: note: instruction: bzhil %eax, %ebx, %ecx
14+
# CHECK-SKIP: error: no assembly instructions found.
Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,55 @@
1-
# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s 2>&1 | FileCheck %s
1+
# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -skip-unsupported-instructions -timeline %s |& FileCheck --check-prefix=CHECK-SKIP %s
2+
# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s |& FileCheck --check-prefix=CHECK-ERROR %s
3+
4+
# Test checks that unsupported instructions exit with an error, unless -skip-unsupported-instructions is passed, in which case the remaining instructions should be analysed.
5+
6+
# CHECK-SKIP: warning: found an unsupported instruction in the input assembly sequence, skipping with -skip-unsupported-instructions, note accuracy will be impacted:
7+
# CHECK-ERROR: error: found an unsupported instruction in the input assembly sequence, use -skip-unsupported-instructions to ignore.
28

39
bzhi %eax, %ebx, %ecx
410

5-
# CHECK: error: found an unsupported instruction in the input assembly sequence.
6-
# CHECK-NEXT: note: instruction: bzhil %eax, %ebx, %ecx
11+
# Supported instruction that may be analysed.
12+
add %eax, %eax
13+
14+
# CHECK-SKIP: Iterations: 100
15+
# CHECK-SKIP: Instructions: 100
16+
# CHECK-SKIP: Total Cycles: 103
17+
# CHECK-SKIP: Total uOps: 100
18+
19+
# CHECK-SKIP: Dispatch Width: 2
20+
# CHECK-SKIP: uOps Per Cycle: 0.97
21+
# CHECK-SKIP: IPC: 0.97
22+
# CHECK-SKIP: Block RThroughput: 0.5
23+
24+
# CHECK-SKIP: Instruction Info:
25+
# CHECK-SKIP: [1]: #uOps
26+
# CHECK-SKIP: [2]: Latency
27+
# CHECK-SKIP: [3]: RThroughput
28+
# CHECK-SKIP: [4]: MayLoad
29+
# CHECK-SKIP: [5]: MayStore
30+
# CHECK-SKIP: [6]: HasSideEffects (U)
31+
32+
# CHECK-SKIP: [1] [2] [3] [4] [5] [6] Instructions:
33+
# CHECK-SKIP: 1 1 0.50 addl %eax, %eax
34+
35+
# CHECK-SKIP: Timeline view:
36+
37+
# CHECK-SKIP: [0,0] DeER . . . addl %eax, %eax
38+
# CHECK-SKIP: [1,0] D=eER. . . addl %eax, %eax
39+
# CHECK-SKIP: [2,0] .D=eER . . addl %eax, %eax
40+
# CHECK-SKIP: [3,0] .D==eER . . addl %eax, %eax
41+
# CHECK-SKIP: [4,0] . D==eER . . addl %eax, %eax
42+
# CHECK-SKIP: [5,0] . D===eER . . addl %eax, %eax
43+
# CHECK-SKIP: [6,0] . D===eER. . addl %eax, %eax
44+
# CHECK-SKIP: [7,0] . D====eER . addl %eax, %eax
45+
# CHECK-SKIP: [8,0] . D====eER. addl %eax, %eax
46+
# CHECK-SKIP: [9,0] . D=====eER addl %eax, %eax
47+
48+
# CHECK-SKIP: Average Wait times (based on the timeline view):
49+
# CHECK-SKIP: [0]: Executions
50+
# CHECK-SKIP: [1]: Average time spent waiting in a scheduler's queue
51+
# CHECK-SKIP: [2]: Average time spent waiting in a scheduler's queue while ready
52+
# CHECK-SKIP: [3]: Average time elapsed from WB until retire stage
53+
54+
# CHECK-SKIP: [0] [1] [2] [3]
55+
# CHECK-SKIP: 0. 10 3.5 0.1 0.0 addl %eax, %eax

llvm/tools/llvm-mca/CodeRegion.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#define LLVM_TOOLS_LLVM_MCA_CODEREGION_H
6060

6161
#include "llvm/ADT/ArrayRef.h"
62+
#include "llvm/ADT/SmallPtrSet.h"
6263
#include "llvm/ADT/SmallVector.h"
6364
#include "llvm/ADT/StringMap.h"
6465
#include "llvm/ADT/StringRef.h"
@@ -97,6 +98,20 @@ class CodeRegion {
9798
Instructions.emplace_back(Instruction);
9899
}
99100

101+
// Remove the given instructions from the set, for unsupported instructions
102+
// being skipped. Returns an ArrayRef for the updated vector of Instructions.
103+
[[nodiscard]] llvm::ArrayRef<llvm::MCInst>
104+
dropInstructions(const llvm::SmallPtrSetImpl<const llvm::MCInst *> &Insts) {
105+
if (Insts.empty())
106+
return Instructions;
107+
Instructions.erase(std::remove_if(Instructions.begin(), Instructions.end(),
108+
[&Insts](const llvm::MCInst &Inst) {
109+
return Insts.contains(&Inst);
110+
}),
111+
Instructions.end());
112+
return Instructions;
113+
}
114+
100115
llvm::SMLoc startLoc() const { return RangeStart; }
101116
llvm::SMLoc endLoc() const { return RangeEnd; }
102117

llvm/tools/llvm-mca/llvm-mca.cpp

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ static cl::opt<bool> DisableInstrumentManager(
237237
"ignores instruments.)."),
238238
cl::cat(ViewOptions), cl::init(false));
239239

240+
static cl::opt<bool> SkipUnsupportedInstructions(
241+
"skip-unsupported-instructions",
242+
cl::desc("Make unsupported instruction errors into warnings."),
243+
cl::cat(ViewOptions), cl::init(false));
244+
240245
namespace {
241246

242247
const Target *getTarget(const char *ProgName) {
@@ -558,6 +563,7 @@ int main(int argc, char **argv) {
558563
assert(MAB && "Unable to create asm backend!");
559564

560565
json::Object JSONOutput;
566+
int NonEmptyRegions = 0;
561567
for (const std::unique_ptr<mca::AnalysisRegion> &Region : Regions) {
562568
// Skip empty code regions.
563569
if (Region->empty())
@@ -571,14 +577,13 @@ int main(int argc, char **argv) {
571577

572578
IPP->resetState();
573579

574-
DenseMap<const MCInst *, SmallVector<mca::Instrument *>>
575-
InstToInstruments;
580+
DenseMap<const MCInst *, SmallVector<mca::Instrument *>> InstToInstruments;
576581
SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence;
582+
SmallPtrSet<const MCInst *, 16> DroppedInsts;
577583
for (const MCInst &MCI : Insts) {
578584
SMLoc Loc = MCI.getLoc();
579585
const SmallVector<mca::Instrument *> Instruments =
580586
InstrumentRegions.getActiveInstruments(Loc);
581-
InstToInstruments.insert({&MCI, Instruments});
582587

583588
Expected<std::unique_ptr<mca::Instruction>> Inst =
584589
IB.createInstruction(MCI, Instruments);
@@ -588,7 +593,15 @@ int main(int argc, char **argv) {
588593
[&IP, &STI](const mca::InstructionError<MCInst> &IE) {
589594
std::string InstructionStr;
590595
raw_string_ostream SS(InstructionStr);
591-
WithColor::error() << IE.Message << '\n';
596+
if (SkipUnsupportedInstructions)
597+
WithColor::warning()
598+
<< IE.Message
599+
<< ", skipping with -skip-unsupported-instructions, "
600+
"note accuracy will be impacted:\n";
601+
else
602+
WithColor::error()
603+
<< IE.Message
604+
<< ", use -skip-unsupported-instructions to ignore.\n";
592605
IP->printInst(&IE.Inst, 0, "", *STI, SS);
593606
SS.flush();
594607
WithColor::note()
@@ -597,14 +610,25 @@ int main(int argc, char **argv) {
597610
// Default case.
598611
WithColor::error() << toString(std::move(NewE));
599612
}
613+
if (SkipUnsupportedInstructions) {
614+
DroppedInsts.insert(&MCI);
615+
continue;
616+
}
600617
return 1;
601618
}
602619

603620
IPP->postProcessInstruction(Inst.get(), MCI);
604-
621+
InstToInstruments.insert({&MCI, Instruments});
605622
LoweredSequence.emplace_back(std::move(Inst.get()));
606623
}
607624

625+
Insts = Region->dropInstructions(DroppedInsts);
626+
627+
// Skip empty regions.
628+
if (Insts.empty())
629+
continue;
630+
NonEmptyRegions++;
631+
608632
mca::CircularSourceMgr S(LoweredSequence,
609633
PrintInstructionTables ? 1 : Iterations);
610634

@@ -759,6 +783,11 @@ int main(int argc, char **argv) {
759783
++RegionIdx;
760784
}
761785

786+
if (NonEmptyRegions == 0) {
787+
WithColor::error() << "no assembly instructions found.\n";
788+
return 1;
789+
}
790+
762791
if (PrintJson)
763792
TOF->os() << formatv("{0:2}", json::Value(std::move(JSONOutput))) << "\n";
764793

0 commit comments

Comments
 (0)