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" 16e8d8bef9SDimitry 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 25e8d8bef9SDimitry Andric ArrayRef<llvm::MCInst> Source = getSource(); 26e8d8bef9SDimitry Andric if (!Source.size()) 27e8d8bef9SDimitry Andric return; 28e8d8bef9SDimitry Andric 29e8d8bef9SDimitry Andric IIVDVec IIVD(Source.size()); 30e8d8bef9SDimitry 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 43e8d8bef9SDimitry Andric for (const auto &I : enumerate(zip(IIVD, Source))) { 44e8d8bef9SDimitry Andric const InstructionInfoViewData &IIVDEntry = std::get<0>(I.value()); 450b57cec5SDimitry Andric 46e8d8bef9SDimitry Andric TempStream << ' ' << IIVDEntry.NumMicroOpcodes << " "; 47e8d8bef9SDimitry Andric if (IIVDEntry.NumMicroOpcodes < 10) 480b57cec5SDimitry Andric TempStream << " "; 49e8d8bef9SDimitry Andric else if (IIVDEntry.NumMicroOpcodes < 100) 500b57cec5SDimitry Andric TempStream << ' '; 51e8d8bef9SDimitry Andric TempStream << IIVDEntry.Latency << " "; 52e8d8bef9SDimitry Andric if (IIVDEntry.Latency < 10) 530b57cec5SDimitry Andric TempStream << " "; 54e8d8bef9SDimitry Andric else if (IIVDEntry.Latency < 100) 550b57cec5SDimitry Andric TempStream << ' '; 560b57cec5SDimitry Andric 57e8d8bef9SDimitry Andric if (IIVDEntry.RThroughput.hasValue()) { 58e8d8bef9SDimitry 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 } 67e8d8bef9SDimitry Andric TempStream << (IIVDEntry.mayLoad ? " * " : " "); 68e8d8bef9SDimitry Andric TempStream << (IIVDEntry.mayStore ? " * " : " "); 69e8d8bef9SDimitry Andric TempStream << (IIVDEntry.hasUnmodeledSideEffects ? " U " : " "); 700b57cec5SDimitry Andric 718bcb0991SDimitry Andric if (PrintEncodings) { 72e8d8bef9SDimitry 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 84e8d8bef9SDimitry Andric const MCInst &Inst = std::get<1>(I.value()); 85e8d8bef9SDimitry Andric TempStream << printInstructionString(Inst) << '\n'; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric TempStream.flush(); 890b57cec5SDimitry Andric OS << Buffer; 900b57cec5SDimitry Andric } 91e8d8bef9SDimitry Andric 92e8d8bef9SDimitry Andric void InstructionInfoView::collectData( 93e8d8bef9SDimitry Andric MutableArrayRef<InstructionInfoViewData> IIVD) const { 94e8d8bef9SDimitry Andric const llvm::MCSubtargetInfo &STI = getSubTargetInfo(); 95e8d8bef9SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 96*fe6060f1SDimitry Andric for (const auto I : zip(getSource(), IIVD)) { 97e8d8bef9SDimitry Andric const MCInst &Inst = std::get<0>(I); 98e8d8bef9SDimitry Andric InstructionInfoViewData &IIVDEntry = std::get<1>(I); 99e8d8bef9SDimitry Andric const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode()); 100e8d8bef9SDimitry Andric 101e8d8bef9SDimitry Andric // Obtain the scheduling class information from the instruction. 102e8d8bef9SDimitry Andric unsigned SchedClassID = MCDesc.getSchedClass(); 103e8d8bef9SDimitry Andric unsigned CPUID = SM.getProcessorID(); 104e8d8bef9SDimitry Andric 105e8d8bef9SDimitry Andric // Try to solve variant scheduling classes. 106e8d8bef9SDimitry Andric while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant()) 107e8d8bef9SDimitry Andric SchedClassID = 108e8d8bef9SDimitry Andric STI.resolveVariantSchedClass(SchedClassID, &Inst, &MCII, CPUID); 109e8d8bef9SDimitry Andric 110e8d8bef9SDimitry Andric const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); 111e8d8bef9SDimitry Andric IIVDEntry.NumMicroOpcodes = SCDesc.NumMicroOps; 112e8d8bef9SDimitry Andric IIVDEntry.Latency = MCSchedModel::computeInstrLatency(STI, SCDesc); 113e8d8bef9SDimitry Andric // Add extra latency due to delays in the forwarding data paths. 114e8d8bef9SDimitry Andric IIVDEntry.Latency += MCSchedModel::getForwardingDelayCycles( 115e8d8bef9SDimitry Andric STI.getReadAdvanceEntries(SCDesc)); 116e8d8bef9SDimitry Andric IIVDEntry.RThroughput = MCSchedModel::getReciprocalThroughput(STI, SCDesc); 117e8d8bef9SDimitry Andric IIVDEntry.mayLoad = MCDesc.mayLoad(); 118e8d8bef9SDimitry Andric IIVDEntry.mayStore = MCDesc.mayStore(); 119e8d8bef9SDimitry Andric IIVDEntry.hasUnmodeledSideEffects = MCDesc.hasUnmodeledSideEffects(); 120e8d8bef9SDimitry Andric } 121e8d8bef9SDimitry Andric } 122e8d8bef9SDimitry Andric 123e8d8bef9SDimitry Andric // Construct a JSON object from a single InstructionInfoViewData object. 124e8d8bef9SDimitry Andric json::Object 125e8d8bef9SDimitry Andric InstructionInfoView::toJSON(const InstructionInfoViewData &IIVD) const { 126e8d8bef9SDimitry Andric json::Object JO({{"NumMicroOpcodes", IIVD.NumMicroOpcodes}, 127e8d8bef9SDimitry Andric {"Latency", IIVD.Latency}, 128e8d8bef9SDimitry Andric {"mayLoad", IIVD.mayLoad}, 129e8d8bef9SDimitry Andric {"mayStore", IIVD.mayStore}, 130e8d8bef9SDimitry Andric {"hasUnmodeledSideEffects", IIVD.hasUnmodeledSideEffects}}); 131e8d8bef9SDimitry Andric JO.try_emplace("RThroughput", IIVD.RThroughput.getValueOr(0.0)); 132e8d8bef9SDimitry Andric return JO; 133e8d8bef9SDimitry Andric } 134e8d8bef9SDimitry Andric 135e8d8bef9SDimitry Andric json::Value InstructionInfoView::toJSON() const { 136e8d8bef9SDimitry Andric ArrayRef<llvm::MCInst> Source = getSource(); 137e8d8bef9SDimitry Andric if (!Source.size()) 138e8d8bef9SDimitry Andric return json::Value(0); 139e8d8bef9SDimitry Andric 140e8d8bef9SDimitry Andric IIVDVec IIVD(Source.size()); 141e8d8bef9SDimitry Andric collectData(IIVD); 142e8d8bef9SDimitry Andric 143e8d8bef9SDimitry Andric json::Array InstInfo; 144e8d8bef9SDimitry Andric for (const auto &I : enumerate(IIVD)) { 145e8d8bef9SDimitry Andric const InstructionInfoViewData &IIVDEntry = I.value(); 146e8d8bef9SDimitry Andric json::Object JO = toJSON(IIVDEntry); 147e8d8bef9SDimitry Andric JO.try_emplace("Instruction", (unsigned)I.index()); 148e8d8bef9SDimitry Andric InstInfo.push_back(std::move(JO)); 149e8d8bef9SDimitry Andric } 150*fe6060f1SDimitry Andric return json::Object({{"InstructionList", json::Value(std::move(InstInfo))}}); 151e8d8bef9SDimitry Andric } 1520b57cec5SDimitry Andric } // namespace mca. 1530b57cec5SDimitry Andric } // namespace llvm 154