10b57cec5SDimitry Andric //===--------------------- InstructionInfoView.cpp --------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric /// \file 90b57cec5SDimitry Andric /// 100b57cec5SDimitry Andric /// This file implements the InstructionInfoView API. 110b57cec5SDimitry Andric /// 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "Views/InstructionInfoView.h" 158bcb0991SDimitry Andric #include "llvm/Support/FormattedStream.h" 16*e8d8bef9SDimitry Andric #include "llvm/Support/JSON.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric namespace llvm { 190b57cec5SDimitry Andric namespace mca { 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric void InstructionInfoView::printView(raw_ostream &OS) const { 220b57cec5SDimitry Andric std::string Buffer; 230b57cec5SDimitry Andric raw_string_ostream TempStream(Buffer); 240b57cec5SDimitry Andric 25*e8d8bef9SDimitry Andric ArrayRef<llvm::MCInst> Source = getSource(); 26*e8d8bef9SDimitry Andric if (!Source.size()) 27*e8d8bef9SDimitry Andric return; 28*e8d8bef9SDimitry Andric 29*e8d8bef9SDimitry Andric IIVDVec IIVD(Source.size()); 30*e8d8bef9SDimitry Andric collectData(IIVD); 310b57cec5SDimitry Andric 320b57cec5SDimitry Andric TempStream << "\n\nInstruction Info:\n"; 330b57cec5SDimitry Andric TempStream << "[1]: #uOps\n[2]: Latency\n[3]: RThroughput\n" 348bcb0991SDimitry Andric << "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n"; 358bcb0991SDimitry Andric if (PrintEncodings) { 368bcb0991SDimitry Andric TempStream << "[7]: Encoding Size\n"; 378bcb0991SDimitry Andric TempStream << "\n[1] [2] [3] [4] [5] [6] [7] " 388bcb0991SDimitry Andric << "Encodings: Instructions:\n"; 398bcb0991SDimitry Andric } else { 408bcb0991SDimitry Andric TempStream << "\n[1] [2] [3] [4] [5] [6] Instructions:\n"; 418bcb0991SDimitry Andric } 420b57cec5SDimitry Andric 43*e8d8bef9SDimitry Andric for (const auto &I : enumerate(zip(IIVD, Source))) { 44*e8d8bef9SDimitry Andric const InstructionInfoViewData &IIVDEntry = std::get<0>(I.value()); 450b57cec5SDimitry Andric 46*e8d8bef9SDimitry Andric TempStream << ' ' << IIVDEntry.NumMicroOpcodes << " "; 47*e8d8bef9SDimitry Andric if (IIVDEntry.NumMicroOpcodes < 10) 480b57cec5SDimitry Andric TempStream << " "; 49*e8d8bef9SDimitry Andric else if (IIVDEntry.NumMicroOpcodes < 100) 500b57cec5SDimitry Andric TempStream << ' '; 51*e8d8bef9SDimitry Andric TempStream << IIVDEntry.Latency << " "; 52*e8d8bef9SDimitry Andric if (IIVDEntry.Latency < 10) 530b57cec5SDimitry Andric TempStream << " "; 54*e8d8bef9SDimitry Andric else if (IIVDEntry.Latency < 100) 550b57cec5SDimitry Andric TempStream << ' '; 560b57cec5SDimitry Andric 57*e8d8bef9SDimitry Andric if (IIVDEntry.RThroughput.hasValue()) { 58*e8d8bef9SDimitry Andric double RT = IIVDEntry.RThroughput.getValue(); 590b57cec5SDimitry Andric TempStream << format("%.2f", RT) << ' '; 600b57cec5SDimitry Andric if (RT < 10.0) 610b57cec5SDimitry Andric TempStream << " "; 620b57cec5SDimitry Andric else if (RT < 100.0) 630b57cec5SDimitry Andric TempStream << ' '; 640b57cec5SDimitry Andric } else { 650b57cec5SDimitry Andric TempStream << " - "; 660b57cec5SDimitry Andric } 67*e8d8bef9SDimitry Andric TempStream << (IIVDEntry.mayLoad ? " * " : " "); 68*e8d8bef9SDimitry Andric TempStream << (IIVDEntry.mayStore ? " * " : " "); 69*e8d8bef9SDimitry Andric TempStream << (IIVDEntry.hasUnmodeledSideEffects ? " U " : " "); 700b57cec5SDimitry Andric 718bcb0991SDimitry Andric if (PrintEncodings) { 72*e8d8bef9SDimitry Andric StringRef Encoding(CE.getEncoding(I.index())); 738bcb0991SDimitry Andric unsigned EncodingSize = Encoding.size(); 748bcb0991SDimitry Andric TempStream << " " << EncodingSize 758bcb0991SDimitry Andric << (EncodingSize < 10 ? " " : " "); 768bcb0991SDimitry Andric TempStream.flush(); 778bcb0991SDimitry Andric formatted_raw_ostream FOS(TempStream); 788bcb0991SDimitry Andric for (unsigned i = 0, e = Encoding.size(); i != e; ++i) 798bcb0991SDimitry Andric FOS << format("%02x ", (uint8_t)Encoding[i]); 808bcb0991SDimitry Andric FOS.PadToColumn(30); 818bcb0991SDimitry Andric FOS.flush(); 828bcb0991SDimitry Andric } 838bcb0991SDimitry Andric 84*e8d8bef9SDimitry Andric const MCInst &Inst = std::get<1>(I.value()); 85*e8d8bef9SDimitry Andric TempStream << printInstructionString(Inst) << '\n'; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric TempStream.flush(); 890b57cec5SDimitry Andric OS << Buffer; 900b57cec5SDimitry Andric } 91*e8d8bef9SDimitry Andric 92*e8d8bef9SDimitry Andric void InstructionInfoView::collectData( 93*e8d8bef9SDimitry Andric MutableArrayRef<InstructionInfoViewData> IIVD) const { 94*e8d8bef9SDimitry Andric const llvm::MCSubtargetInfo &STI = getSubTargetInfo(); 95*e8d8bef9SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 96*e8d8bef9SDimitry Andric for (const auto &I : zip(getSource(), IIVD)) { 97*e8d8bef9SDimitry Andric const MCInst &Inst = std::get<0>(I); 98*e8d8bef9SDimitry Andric InstructionInfoViewData &IIVDEntry = std::get<1>(I); 99*e8d8bef9SDimitry Andric const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode()); 100*e8d8bef9SDimitry Andric 101*e8d8bef9SDimitry Andric // Obtain the scheduling class information from the instruction. 102*e8d8bef9SDimitry Andric unsigned SchedClassID = MCDesc.getSchedClass(); 103*e8d8bef9SDimitry Andric unsigned CPUID = SM.getProcessorID(); 104*e8d8bef9SDimitry Andric 105*e8d8bef9SDimitry Andric // Try to solve variant scheduling classes. 106*e8d8bef9SDimitry Andric while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant()) 107*e8d8bef9SDimitry Andric SchedClassID = 108*e8d8bef9SDimitry Andric STI.resolveVariantSchedClass(SchedClassID, &Inst, &MCII, CPUID); 109*e8d8bef9SDimitry Andric 110*e8d8bef9SDimitry Andric const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); 111*e8d8bef9SDimitry Andric IIVDEntry.NumMicroOpcodes = SCDesc.NumMicroOps; 112*e8d8bef9SDimitry Andric IIVDEntry.Latency = MCSchedModel::computeInstrLatency(STI, SCDesc); 113*e8d8bef9SDimitry Andric // Add extra latency due to delays in the forwarding data paths. 114*e8d8bef9SDimitry Andric IIVDEntry.Latency += MCSchedModel::getForwardingDelayCycles( 115*e8d8bef9SDimitry Andric STI.getReadAdvanceEntries(SCDesc)); 116*e8d8bef9SDimitry Andric IIVDEntry.RThroughput = MCSchedModel::getReciprocalThroughput(STI, SCDesc); 117*e8d8bef9SDimitry Andric IIVDEntry.mayLoad = MCDesc.mayLoad(); 118*e8d8bef9SDimitry Andric IIVDEntry.mayStore = MCDesc.mayStore(); 119*e8d8bef9SDimitry Andric IIVDEntry.hasUnmodeledSideEffects = MCDesc.hasUnmodeledSideEffects(); 120*e8d8bef9SDimitry Andric } 121*e8d8bef9SDimitry Andric } 122*e8d8bef9SDimitry Andric 123*e8d8bef9SDimitry Andric // Construct a JSON object from a single InstructionInfoViewData object. 124*e8d8bef9SDimitry Andric json::Object 125*e8d8bef9SDimitry Andric InstructionInfoView::toJSON(const InstructionInfoViewData &IIVD) const { 126*e8d8bef9SDimitry Andric json::Object JO({{"NumMicroOpcodes", IIVD.NumMicroOpcodes}, 127*e8d8bef9SDimitry Andric {"Latency", IIVD.Latency}, 128*e8d8bef9SDimitry Andric {"mayLoad", IIVD.mayLoad}, 129*e8d8bef9SDimitry Andric {"mayStore", IIVD.mayStore}, 130*e8d8bef9SDimitry Andric {"hasUnmodeledSideEffects", IIVD.hasUnmodeledSideEffects}}); 131*e8d8bef9SDimitry Andric JO.try_emplace("RThroughput", IIVD.RThroughput.getValueOr(0.0)); 132*e8d8bef9SDimitry Andric return JO; 133*e8d8bef9SDimitry Andric } 134*e8d8bef9SDimitry Andric 135*e8d8bef9SDimitry Andric json::Value InstructionInfoView::toJSON() const { 136*e8d8bef9SDimitry Andric ArrayRef<llvm::MCInst> Source = getSource(); 137*e8d8bef9SDimitry Andric if (!Source.size()) 138*e8d8bef9SDimitry Andric return json::Value(0); 139*e8d8bef9SDimitry Andric 140*e8d8bef9SDimitry Andric IIVDVec IIVD(Source.size()); 141*e8d8bef9SDimitry Andric collectData(IIVD); 142*e8d8bef9SDimitry Andric 143*e8d8bef9SDimitry Andric json::Array InstInfo; 144*e8d8bef9SDimitry Andric for (const auto &I : enumerate(IIVD)) { 145*e8d8bef9SDimitry Andric const InstructionInfoViewData &IIVDEntry = I.value(); 146*e8d8bef9SDimitry Andric json::Object JO = toJSON(IIVDEntry); 147*e8d8bef9SDimitry Andric JO.try_emplace("Instruction", (unsigned)I.index()); 148*e8d8bef9SDimitry Andric InstInfo.push_back(std::move(JO)); 149*e8d8bef9SDimitry Andric } 150*e8d8bef9SDimitry Andric return json::Value(std::move(InstInfo)); 151*e8d8bef9SDimitry Andric } 1520b57cec5SDimitry Andric } // namespace mca. 1530b57cec5SDimitry Andric } // namespace llvm 154