Index: llvm/tools/llvm-mca/Views/InstructionInfoView.h =================================================================== --- llvm/tools/llvm-mca/Views/InstructionInfoView.h +++ llvm/tools/llvm-mca/Views/InstructionInfoView.h @@ -36,6 +36,7 @@ #include "Views/View.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstPrinter.h" #include "llvm/MC/MCInstrInfo.h" @@ -57,6 +58,19 @@ llvm::ArrayRef Source; llvm::MCInstPrinter &MCIP; + struct InstructionInfoViewData { + unsigned NumMicroOpcodes = 0; + unsigned Latency = 0; + Optional RThroughput = 0.0; + bool mayLoad = false; + bool mayStore = false; + bool hasUnmodeledSideEffects = false; + }; + using IIVDVec = SmallVector; + + /// Place the data into the array of InstructionInfoViewData IIVD. + void collectData(MutableArrayRef IIVD) const; + public: InstructionInfoView(const llvm::MCSubtargetInfo &ST, const llvm::MCInstrInfo &II, CodeEmitter &C, Index: llvm/tools/llvm-mca/Views/InstructionInfoView.cpp =================================================================== --- llvm/tools/llvm-mca/Views/InstructionInfoView.cpp +++ llvm/tools/llvm-mca/Views/InstructionInfoView.cpp @@ -20,11 +20,15 @@ void InstructionInfoView::printView(raw_ostream &OS) const { std::string Buffer; raw_string_ostream TempStream(Buffer); - const MCSchedModel &SM = STI.getSchedModel(); - std::string Instruction; raw_string_ostream InstrStream(Instruction); + if (!Source.size()) + return; + + IIVDVec IIVD(Source.size()); + collectData(IIVD); + TempStream << "\n\nInstruction Info:\n"; TempStream << "[1]: #uOps\n[2]: Latency\n[3]: RThroughput\n" << "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n"; @@ -36,40 +40,22 @@ TempStream << "\n[1] [2] [3] [4] [5] [6] Instructions:\n"; } - for (unsigned I = 0, E = Source.size(); I < E; ++I) { - const MCInst &Inst = Source[I]; - const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode()); - - // Obtain the scheduling class information from the instruction. - unsigned SchedClassID = MCDesc.getSchedClass(); - unsigned CPUID = SM.getProcessorID(); - - // Try to solve variant scheduling classes. - while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant()) - SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &Inst, CPUID); - - const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); - unsigned NumMicroOpcodes = SCDesc.NumMicroOps; - unsigned Latency = MCSchedModel::computeInstrLatency(STI, SCDesc); - // Add extra latency due to delays in the forwarding data paths. - Latency += MCSchedModel::getForwardingDelayCycles( - STI.getReadAdvanceEntries(SCDesc)); - Optional RThroughput = - MCSchedModel::getReciprocalThroughput(STI, SCDesc); + for (auto I : enumerate(zip(IIVD, Source))) { + const InstructionInfoViewData &IIVDEntry = std::get<0>(I.value()); - TempStream << ' ' << NumMicroOpcodes << " "; - if (NumMicroOpcodes < 10) + TempStream << ' ' << IIVDEntry.NumMicroOpcodes << " "; + if (IIVDEntry.NumMicroOpcodes < 10) TempStream << " "; - else if (NumMicroOpcodes < 100) + else if (IIVDEntry.NumMicroOpcodes < 100) TempStream << ' '; - TempStream << Latency << " "; - if (Latency < 10) + TempStream << IIVDEntry.Latency << " "; + if (IIVDEntry.Latency < 10) TempStream << " "; - else if (Latency < 100) + else if (IIVDEntry.Latency < 100) TempStream << ' '; - if (RThroughput.hasValue()) { - double RT = RThroughput.getValue(); + if (IIVDEntry.RThroughput.hasValue()) { + double RT = IIVDEntry.RThroughput.getValue(); TempStream << format("%.2f", RT) << ' '; if (RT < 10.0) TempStream << " "; @@ -78,12 +64,12 @@ } else { TempStream << " - "; } - TempStream << (MCDesc.mayLoad() ? " * " : " "); - TempStream << (MCDesc.mayStore() ? " * " : " "); - TempStream << (MCDesc.hasUnmodeledSideEffects() ? " U " : " "); + TempStream << (IIVDEntry.mayLoad ? " * " : " "); + TempStream << (IIVDEntry.mayStore ? " * " : " "); + TempStream << (IIVDEntry.hasUnmodeledSideEffects ? " U " : " "); if (PrintEncodings) { - StringRef Encoding(CE.getEncoding(I)); + StringRef Encoding(CE.getEncoding(I.index())); unsigned EncodingSize = Encoding.size(); TempStream << " " << EncodingSize << (EncodingSize < 10 ? " " : " "); @@ -95,6 +81,7 @@ FOS.flush(); } + const MCInst &Inst = std::get<1>(I.value()); MCIP.printInst(&Inst, 0, "", STI, InstrStream); InstrStream.flush(); @@ -108,5 +95,34 @@ TempStream.flush(); OS << Buffer; } + +void InstructionInfoView::collectData( + MutableArrayRef IIVD) const { + const MCSchedModel &SM = STI.getSchedModel(); + for (auto I : zip(Source, IIVD)) { + const MCInst &Inst = std::get<0>(I); + InstructionInfoViewData &IIVDEntry = std::get<1>(I); + const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode()); + + // Obtain the scheduling class information from the instruction. + unsigned SchedClassID = MCDesc.getSchedClass(); + unsigned CPUID = SM.getProcessorID(); + + // Try to solve variant scheduling classes. + while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant()) + SchedClassID = STI.resolveVariantSchedClass(SchedClassID, &Inst, CPUID); + + const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); + IIVDEntry.NumMicroOpcodes = SCDesc.NumMicroOps; + IIVDEntry.Latency = MCSchedModel::computeInstrLatency(STI, SCDesc); + // Add extra latency due to delays in the forwarding data paths. + IIVDEntry.Latency += MCSchedModel::getForwardingDelayCycles( + STI.getReadAdvanceEntries(SCDesc)); + IIVDEntry.RThroughput = MCSchedModel::getReciprocalThroughput(STI, SCDesc); + IIVDEntry.mayLoad = MCDesc.mayLoad(); + IIVDEntry.mayStore = MCDesc.mayStore(); + IIVDEntry.hasUnmodeledSideEffects = MCDesc.hasUnmodeledSideEffects(); + } +} } // namespace mca. } // namespace llvm Index: llvm/tools/llvm-mca/Views/SummaryView.h =================================================================== --- llvm/tools/llvm-mca/Views/SummaryView.h +++ llvm/tools/llvm-mca/Views/SummaryView.h @@ -46,6 +46,18 @@ // The total number of micro opcodes contributed by a block of instructions. unsigned NumMicroOps; + struct DisplayValues { + unsigned Instructions; + unsigned Iterations; + unsigned TotalInstructions; + unsigned TotalCycles; + unsigned DispatchWidth; + unsigned TotalUOps; + double IPC; + double UOpsPerCycle; + double BlockRThroughput; + }; + // For each processor resource, this vector stores the cumulative number of // resource cycles consumed by the analyzed code block. llvm::SmallVector ProcResourceUsage; @@ -65,6 +77,9 @@ // - Total Resource Cycles / #Units (for every resource consumed). double getBlockRThroughput() const; + /// Compute the data we want to print out in the object DV. + void collectData(DisplayValues &DV) const; + public: SummaryView(const llvm::MCSchedModel &Model, llvm::ArrayRef S, unsigned Width); Index: llvm/tools/llvm-mca/Views/SummaryView.cpp =================================================================== --- llvm/tools/llvm-mca/Views/SummaryView.cpp +++ llvm/tools/llvm-mca/Views/SummaryView.cpp @@ -63,32 +63,38 @@ } void SummaryView::printView(raw_ostream &OS) const { - unsigned Instructions = Source.size(); - unsigned Iterations = (LastInstructionIdx / Instructions) + 1; - unsigned TotalInstructions = Instructions * Iterations; - unsigned TotalUOps = NumMicroOps * Iterations; - double IPC = (double)TotalInstructions / TotalCycles; - double UOpsPerCycle = (double)TotalUOps / TotalCycles; - double BlockRThroughput = computeBlockRThroughput( - SM, DispatchWidth, NumMicroOps, ProcResourceUsage); - std::string Buffer; raw_string_ostream TempStream(Buffer); - TempStream << "Iterations: " << Iterations; - TempStream << "\nInstructions: " << TotalInstructions; - TempStream << "\nTotal Cycles: " << TotalCycles; - TempStream << "\nTotal uOps: " << TotalUOps << '\n'; - TempStream << "\nDispatch Width: " << DispatchWidth; + DisplayValues DV; + + collectData(DV); + TempStream << "Iterations: " << DV.Iterations; + TempStream << "\nInstructions: " << DV.TotalInstructions; + TempStream << "\nTotal Cycles: " << DV.TotalCycles; + TempStream << "\nTotal uOps: " << DV.TotalUOps << '\n'; + TempStream << "\nDispatch Width: " << DV.DispatchWidth; TempStream << "\nuOps Per Cycle: " - << format("%.2f", floor((UOpsPerCycle * 100) + 0.5) / 100); + << format("%.2f", floor((DV.UOpsPerCycle * 100) + 0.5) / 100); TempStream << "\nIPC: " - << format("%.2f", floor((IPC * 100) + 0.5) / 100); + << format("%.2f", floor((DV.IPC * 100) + 0.5) / 100); TempStream << "\nBlock RThroughput: " - << format("%.1f", floor((BlockRThroughput * 10) + 0.5) / 10) + << format("%.1f", floor((DV.BlockRThroughput * 10) + 0.5) / 10) << '\n'; TempStream.flush(); OS << Buffer; } +void SummaryView::collectData(DisplayValues &DV) const { + DV.Instructions = Source.size(); + DV.Iterations = (LastInstructionIdx / DV.Instructions) + 1; + DV.TotalInstructions = DV.Instructions * DV.Iterations; + DV.TotalCycles = TotalCycles; + DV.DispatchWidth = DispatchWidth; + DV.TotalUOps = NumMicroOps * DV.Iterations; + DV.UOpsPerCycle = (double)DV.TotalUOps / TotalCycles; + DV.IPC = (double)DV.TotalInstructions / TotalCycles; + DV.BlockRThroughput = computeBlockRThroughput(SM, DispatchWidth, NumMicroOps, + ProcResourceUsage); +} } // namespace mca. } // namespace llvm