From 797f06e19b6f17217a69dea4d6ce900625432595 Mon Sep 17 00:00:00 2001 From: Quentin Colombet Date: Wed, 2 Oct 2013 22:07:57 +0000 Subject: [PATCH] [llvm-c][Disassembler] Add an option to print latency information in disassembled output alongside the instructions. E.g., on a vector shuffle operation with a memory operand, disassembled outputs are: * Without the option: vpshufd $-0x79, (%rsp), %xmm0 * With the option: vpshufd $-0x79, (%rsp), %xmm0 ## Latency: 5 The printed latency is extracted from the schedule model available in the disassembler context. Thus, this option has no effect if there is not a scheduling model for the target. This boils down to one may need to specify the CPU string, so that this option could have an effect. Note: Latency < 2 are not printed. This part of . git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191859 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm-c/Disassembler.h | 2 + lib/MC/MCDisassembler/Disassembler.cpp | 58 ++++++++++++++++++++++++++ lib/MC/MCDisassembler/Disassembler.h | 5 +++ 3 files changed, 65 insertions(+) diff --git a/include/llvm-c/Disassembler.h b/include/llvm-c/Disassembler.h index 0c5bd5c5e85..4732e51a970 100644 --- a/include/llvm-c/Disassembler.h +++ b/include/llvm-c/Disassembler.h @@ -172,6 +172,8 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DC, uint64_t Options); #define LLVMDisassembler_Option_AsmPrinterVariant 4 /* The option to set comment on instructions */ #define LLVMDisassembler_Option_SetInstrComments 8 + /* The option to print latency information alongside instructions */ +#define LLVMDisassembler_Option_PrintLatency 16 /** * Dispose of a disassembler context. diff --git a/lib/MC/MCDisassembler/Disassembler.cpp b/lib/MC/MCDisassembler/Disassembler.cpp index 86b1cf170a3..406ee5b7db9 100644 --- a/lib/MC/MCDisassembler/Disassembler.cpp +++ b/lib/MC/MCDisassembler/Disassembler.cpp @@ -174,6 +174,52 @@ static void emitComments(LLVMDisasmContext *DC, DC->CommentStream.resync(); } +/// \brief Gets latency information for \p Inst, based on \p DC information. +/// \return The maximum expected latency over all the definitions or -1 +/// if no information are available. +static int getLatency(LLVMDisasmContext *DC, const MCInst &Inst) { + // Try to compute scheduling information. + const MCSubtargetInfo *STI = DC->getSubtargetInfo(); + const MCSchedModel *SCModel = STI->getSchedModel(); + const int NoInformationAvailable = -1; + + // Check if we have a scheduling model for instructions. + if (!SCModel || !SCModel->hasInstrSchedModel()) + return NoInformationAvailable; + + // Get the scheduling class of the requested instruction. + const MCInstrDesc& Desc = DC->getInstrInfo()->get(Inst.getOpcode()); + unsigned SCClass = Desc.getSchedClass(); + const MCSchedClassDesc *SCDesc = SCModel->getSchedClassDesc(SCClass); + if (!SCDesc || !SCDesc->isValid()) + return NoInformationAvailable; + + // Compute output latency. + int Latency = 0; + for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries; + DefIdx != DefEnd; ++DefIdx) { + // Lookup the definition's write latency in SubtargetInfo. + const MCWriteLatencyEntry *WLEntry = STI->getWriteLatencyEntry(SCDesc, + DefIdx); + Latency = std::max(Latency, WLEntry->Cycles); + } + + return Latency; +} + + +/// \brief Emits latency information in DC->CommentStream for \p Inst, based +/// on the information available in \p DC. +static void emitLatency(LLVMDisasmContext *DC, const MCInst &Inst) { + int Latency = getLatency(DC, Inst); + + // Report only interesting latency. + if (Latency < 2) + return; + + DC->CommentStream << "Latency: " << Latency << '\n'; +} + // // LLVMDisasmInstruction() disassembles a single instruction using the // disassembler context specified in the parameter DC. The bytes of the @@ -217,6 +263,9 @@ size_t LLVMDisasmInstruction(LLVMDisasmContextRef DCR, uint8_t *Bytes, formatted_raw_ostream FormattedOS(OS); IP->printInst(&Inst, FormattedOS, AnnotationsStr); + if (DC->getOptions() & LLVMDisassembler_Option_PrintLatency) + emitLatency(DC, Inst); + emitComments(DC, FormattedOS); assert(OutStringSize != 0 && "Output buffer cannot be zero size"); @@ -239,12 +288,14 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; MCInstPrinter *IP = DC->getIP(); IP->setUseMarkup(1); + DC->addOptions(LLVMDisassembler_Option_UseMarkup); Options &= ~LLVMDisassembler_Option_UseMarkup; } if (Options & LLVMDisassembler_Option_PrintImmHex){ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; MCInstPrinter *IP = DC->getIP(); IP->setPrintImmHex(1); + DC->addOptions(LLVMDisassembler_Option_PrintImmHex); Options &= ~LLVMDisassembler_Option_PrintImmHex; } if (Options & LLVMDisassembler_Option_AsmPrinterVariant){ @@ -260,6 +311,7 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ AsmPrinterVariant, *MAI, *MII, *MRI, *STI); if (IP) { DC->setIP(IP); + DC->addOptions(LLVMDisassembler_Option_AsmPrinterVariant); Options &= ~LLVMDisassembler_Option_AsmPrinterVariant; } } @@ -267,7 +319,13 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DCR, uint64_t Options){ LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; MCInstPrinter *IP = DC->getIP(); IP->setCommentStream(DC->CommentStream); + DC->addOptions(LLVMDisassembler_Option_SetInstrComments); Options &= ~LLVMDisassembler_Option_SetInstrComments; } + if (Options & LLVMDisassembler_Option_PrintLatency) { + LLVMDisasmContext *DC = (LLVMDisasmContext *)DCR; + DC->addOptions(LLVMDisassembler_Option_PrintLatency); + Options &= ~LLVMDisassembler_Option_PrintLatency; + } return (Options == 0); } diff --git a/lib/MC/MCDisassembler/Disassembler.h b/lib/MC/MCDisassembler/Disassembler.h index 6eb59d0c57b..05c92dff17c 100644 --- a/lib/MC/MCDisassembler/Disassembler.h +++ b/lib/MC/MCDisassembler/Disassembler.h @@ -73,6 +73,8 @@ private: llvm::OwningPtr DisAsm; // The instruction printer for the target architecture. llvm::OwningPtr IP; + // The options used to set up the disassembler. + uint64_t Options; public: // Comment stream and backing vector. @@ -90,6 +92,7 @@ public: MCInstPrinter *iP) : TripleName(tripleName), DisInfo(disInfo), TagType(tagType), GetOpInfo(getOpInfo), SymbolLookUp(symbolLookUp), TheTarget(theTarget), + Options(0), CommentStream(CommentsToEmit) { MAI.reset(mAI); MRI.reset(mRI); @@ -114,6 +117,8 @@ public: const MCSubtargetInfo *getSubtargetInfo() const { return MSI.get(); } MCInstPrinter *getIP() { return IP.get(); } void setIP(MCInstPrinter *NewIP) { IP.reset(NewIP); } + uint64_t getOptions() const { return Options; } + void addOptions(uint64_t Options) { this->Options |= Options; } }; } // namespace llvm