diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp index 1a82e45763a26..2e3ebe3d9073b 100644 --- a/llvm/lib/MCA/InstrBuilder.cpp +++ b/llvm/lib/MCA/InstrBuilder.cpp @@ -542,8 +542,7 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI, const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) { return make_error>( - "found an unsupported instruction in the input assembly sequence.", - MCI); + "found an unsupported instruction in the input assembly sequence", MCI); } LLVM_DEBUG(dbgs() << "\n\t\tOpcode Name= " << MCII.getName(Opcode) << '\n'); diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/skip-unsupported-instructions-none-remain.s b/llvm/test/tools/llvm-mca/X86/BtVer2/skip-unsupported-instructions-none-remain.s new file mode 100644 index 0000000000000..a8f78159c1990 --- /dev/null +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/skip-unsupported-instructions-none-remain.s @@ -0,0 +1,14 @@ +# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -skip-unsupported-instructions %s |& FileCheck --check-prefixes=CHECK-ALL,CHECK-SKIP %s +# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s |& FileCheck --check-prefixes=CHECK-ALL,CHECK-ERROR %s + +# Test defends that if all instructions are skipped leaving an empty input, an error is printed. + +bzhi %eax, %ebx, %ecx + +# CHECK-ALL-NOT: error + +# CHECK-ERROR: error: found an unsupported instruction in the input assembly sequence, use -skip-unsupported-instructions to ignore. + +# CHECK-SKIP: warning: found an unsupported instruction in the input assembly sequence, skipping with -skip-unsupported-instructions, note accuracy will be impacted: +# CHECK-SKIP: note: instruction: bzhil %eax, %ebx, %ecx +# CHECK-SKIP: error: no assembly instructions found. diff --git a/llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s b/llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s index bb88e951c1298..eec6de6648a69 100644 --- a/llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s +++ b/llvm/test/tools/llvm-mca/X86/BtVer2/unsupported-instruction.s @@ -1,6 +1,55 @@ -# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s 2>&1 | FileCheck %s +# RUN: llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 -skip-unsupported-instructions -timeline %s |& FileCheck --check-prefix=CHECK-SKIP %s +# RUN: not llvm-mca -mtriple=x86_64-unknown-unknown -mcpu=btver2 %s |& FileCheck --check-prefix=CHECK-ERROR %s + +# Test checks that unsupported instructions exit with an error, unless -skip-unsupported-instructions is passed, in which case the remaining instructions should be analysed. + +# CHECK-SKIP: warning: found an unsupported instruction in the input assembly sequence, skipping with -skip-unsupported-instructions, note accuracy will be impacted: +# CHECK-ERROR: error: found an unsupported instruction in the input assembly sequence, use -skip-unsupported-instructions to ignore. bzhi %eax, %ebx, %ecx -# CHECK: error: found an unsupported instruction in the input assembly sequence. -# CHECK-NEXT: note: instruction: bzhil %eax, %ebx, %ecx +# Supported instruction that may be analysed. +add %eax, %eax + +# CHECK-SKIP: Iterations: 100 +# CHECK-SKIP: Instructions: 100 +# CHECK-SKIP: Total Cycles: 103 +# CHECK-SKIP: Total uOps: 100 + +# CHECK-SKIP: Dispatch Width: 2 +# CHECK-SKIP: uOps Per Cycle: 0.97 +# CHECK-SKIP: IPC: 0.97 +# CHECK-SKIP: Block RThroughput: 0.5 + +# CHECK-SKIP: Instruction Info: +# CHECK-SKIP: [1]: #uOps +# CHECK-SKIP: [2]: Latency +# CHECK-SKIP: [3]: RThroughput +# CHECK-SKIP: [4]: MayLoad +# CHECK-SKIP: [5]: MayStore +# CHECK-SKIP: [6]: HasSideEffects (U) + +# CHECK-SKIP: [1] [2] [3] [4] [5] [6] Instructions: +# CHECK-SKIP: 1 1 0.50 addl %eax, %eax + +# CHECK-SKIP: Timeline view: + +# CHECK-SKIP: [0,0] DeER . . . addl %eax, %eax +# CHECK-SKIP: [1,0] D=eER. . . addl %eax, %eax +# CHECK-SKIP: [2,0] .D=eER . . addl %eax, %eax +# CHECK-SKIP: [3,0] .D==eER . . addl %eax, %eax +# CHECK-SKIP: [4,0] . D==eER . . addl %eax, %eax +# CHECK-SKIP: [5,0] . D===eER . . addl %eax, %eax +# CHECK-SKIP: [6,0] . D===eER. . addl %eax, %eax +# CHECK-SKIP: [7,0] . D====eER . addl %eax, %eax +# CHECK-SKIP: [8,0] . D====eER. addl %eax, %eax +# CHECK-SKIP: [9,0] . D=====eER addl %eax, %eax + +# CHECK-SKIP: Average Wait times (based on the timeline view): +# CHECK-SKIP: [0]: Executions +# CHECK-SKIP: [1]: Average time spent waiting in a scheduler's queue +# CHECK-SKIP: [2]: Average time spent waiting in a scheduler's queue while ready +# CHECK-SKIP: [3]: Average time elapsed from WB until retire stage + +# CHECK-SKIP: [0] [1] [2] [3] +# CHECK-SKIP: 0. 10 3.5 0.1 0.0 addl %eax, %eax diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h index ce107fd8f3b62..5a2e8baa1f3e7 100644 --- a/llvm/tools/llvm-mca/CodeRegion.h +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -59,6 +59,7 @@ #define LLVM_TOOLS_LLVM_MCA_CODEREGION_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -97,6 +98,20 @@ class CodeRegion { Instructions.emplace_back(Instruction); } + // Remove the given instructions from the set, for unsupported instructions + // being skipped. Returns an ArrayRef for the updated vector of Instructions. + [[nodiscard]] llvm::ArrayRef + dropInstructions(const llvm::SmallPtrSetImpl &Insts) { + if (Insts.empty()) + return Instructions; + Instructions.erase(std::remove_if(Instructions.begin(), Instructions.end(), + [&Insts](const llvm::MCInst &Inst) { + return Insts.contains(&Inst); + }), + Instructions.end()); + return Instructions; + } + llvm::SMLoc startLoc() const { return RangeStart; } llvm::SMLoc endLoc() const { return RangeEnd; } diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index eb71cffba6dd2..e037c06b12a35 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -237,6 +237,11 @@ static cl::opt DisableInstrumentManager( "ignores instruments.)."), cl::cat(ViewOptions), cl::init(false)); +static cl::opt SkipUnsupportedInstructions( + "skip-unsupported-instructions", + cl::desc("Make unsupported instruction errors into warnings."), + cl::cat(ViewOptions), cl::init(false)); + namespace { const Target *getTarget(const char *ProgName) { @@ -558,6 +563,7 @@ int main(int argc, char **argv) { assert(MAB && "Unable to create asm backend!"); json::Object JSONOutput; + int NonEmptyRegions = 0; for (const std::unique_ptr &Region : Regions) { // Skip empty code regions. if (Region->empty()) @@ -571,14 +577,13 @@ int main(int argc, char **argv) { IPP->resetState(); - DenseMap> - InstToInstruments; + DenseMap> InstToInstruments; SmallVector> LoweredSequence; + SmallPtrSet DroppedInsts; for (const MCInst &MCI : Insts) { SMLoc Loc = MCI.getLoc(); const SmallVector Instruments = InstrumentRegions.getActiveInstruments(Loc); - InstToInstruments.insert({&MCI, Instruments}); Expected> Inst = IB.createInstruction(MCI, Instruments); @@ -588,7 +593,15 @@ int main(int argc, char **argv) { [&IP, &STI](const mca::InstructionError &IE) { std::string InstructionStr; raw_string_ostream SS(InstructionStr); - WithColor::error() << IE.Message << '\n'; + if (SkipUnsupportedInstructions) + WithColor::warning() + << IE.Message + << ", skipping with -skip-unsupported-instructions, " + "note accuracy will be impacted:\n"; + else + WithColor::error() + << IE.Message + << ", use -skip-unsupported-instructions to ignore.\n"; IP->printInst(&IE.Inst, 0, "", *STI, SS); SS.flush(); WithColor::note() @@ -597,14 +610,25 @@ int main(int argc, char **argv) { // Default case. WithColor::error() << toString(std::move(NewE)); } + if (SkipUnsupportedInstructions) { + DroppedInsts.insert(&MCI); + continue; + } return 1; } IPP->postProcessInstruction(Inst.get(), MCI); - + InstToInstruments.insert({&MCI, Instruments}); LoweredSequence.emplace_back(std::move(Inst.get())); } + Insts = Region->dropInstructions(DroppedInsts); + + // Skip empty regions. + if (Insts.empty()) + continue; + NonEmptyRegions++; + mca::CircularSourceMgr S(LoweredSequence, PrintInstructionTables ? 1 : Iterations); @@ -759,6 +783,11 @@ int main(int argc, char **argv) { ++RegionIdx; } + if (NonEmptyRegions == 0) { + WithColor::error() << "no assembly instructions found.\n"; + return 1; + } + if (PrintJson) TOF->os() << formatv("{0:2}", json::Value(std::move(JSONOutput))) << "\n";