Path: blob/main/contrib/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
35290 views
//===--------------------- InstructionInfoView.cpp --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// This file implements the InstructionInfoView API.10///11//===----------------------------------------------------------------------===//1213#include "Views/InstructionInfoView.h"14#include "llvm/Support/FormattedStream.h"15#include "llvm/Support/JSON.h"1617namespace llvm {18namespace mca {1920void InstructionInfoView::printView(raw_ostream &OS) const {21std::string Buffer;22raw_string_ostream TempStream(Buffer);2324ArrayRef<llvm::MCInst> Source = getSource();25if (!Source.size())26return;2728IIVDVec IIVD(Source.size());29collectData(IIVD);3031TempStream << "\n\nInstruction Info:\n";32TempStream << "[1]: #uOps\n[2]: Latency\n[3]: RThroughput\n"33<< "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n";34if (PrintBarriers) {35TempStream << "[7]: LoadBarrier\n[8]: StoreBarrier\n";36}37if (PrintEncodings) {38if (PrintBarriers) {39TempStream << "[9]: Encoding Size\n";40TempStream << "\n[1] [2] [3] [4] [5] [6] [7] [8] "41<< "[9] Encodings: Instructions:\n";42} else {43TempStream << "[7]: Encoding Size\n";44TempStream << "\n[1] [2] [3] [4] [5] [6] [7] "45<< "Encodings: Instructions:\n";46}47} else {48if (PrintBarriers) {49TempStream << "\n[1] [2] [3] [4] [5] [6] [7] [8] "50<< "Instructions:\n";51} else {52TempStream << "\n[1] [2] [3] [4] [5] [6] "53<< "Instructions:\n";54}55}5657for (const auto &[Index, IIVDEntry, Inst] : enumerate(IIVD, Source)) {58TempStream << ' ' << IIVDEntry.NumMicroOpcodes << " ";59if (IIVDEntry.NumMicroOpcodes < 10)60TempStream << " ";61else if (IIVDEntry.NumMicroOpcodes < 100)62TempStream << ' ';63TempStream << IIVDEntry.Latency << " ";64if (IIVDEntry.Latency < 10)65TempStream << " ";66else if (IIVDEntry.Latency < 100)67TempStream << ' ';6869if (IIVDEntry.RThroughput) {70double RT = *IIVDEntry.RThroughput;71TempStream << format("%.2f", RT) << ' ';72if (RT < 10.0)73TempStream << " ";74else if (RT < 100.0)75TempStream << ' ';76} else {77TempStream << " - ";78}79TempStream << (IIVDEntry.mayLoad ? " * " : " ");80TempStream << (IIVDEntry.mayStore ? " * " : " ");81TempStream << (IIVDEntry.hasUnmodeledSideEffects ? " U " : " ");8283if (PrintBarriers) {84TempStream << (LoweredInsts[Index]->isALoadBarrier() ? " * "85: " ");86TempStream << (LoweredInsts[Index]->isAStoreBarrier() ? " * "87: " ");88}8990if (PrintEncodings) {91StringRef Encoding(CE.getEncoding(Index));92unsigned EncodingSize = Encoding.size();93TempStream << " " << EncodingSize94<< (EncodingSize < 10 ? " " : " ");95TempStream.flush();96formatted_raw_ostream FOS(TempStream);97for (unsigned i = 0, e = Encoding.size(); i != e; ++i)98FOS << format("%02x ", (uint8_t)Encoding[i]);99FOS.PadToColumn(30);100FOS.flush();101}102103TempStream << printInstructionString(Inst) << '\n';104}105106TempStream.flush();107OS << Buffer;108}109110void InstructionInfoView::collectData(111MutableArrayRef<InstructionInfoViewData> IIVD) const {112const llvm::MCSubtargetInfo &STI = getSubTargetInfo();113const MCSchedModel &SM = STI.getSchedModel();114for (const auto I : zip(getSource(), IIVD)) {115const MCInst &Inst = std::get<0>(I);116InstructionInfoViewData &IIVDEntry = std::get<1>(I);117const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode());118119// Obtain the scheduling class information from the instruction120// and instruments.121auto IVecIt = InstToInstruments.find(&Inst);122unsigned SchedClassID =123IVecIt == InstToInstruments.end()124? MCDesc.getSchedClass()125: IM.getSchedClassID(MCII, Inst, IVecIt->second);126unsigned CPUID = SM.getProcessorID();127128// Try to solve variant scheduling classes.129while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant())130SchedClassID =131STI.resolveVariantSchedClass(SchedClassID, &Inst, &MCII, CPUID);132133const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID);134IIVDEntry.NumMicroOpcodes = SCDesc.NumMicroOps;135IIVDEntry.Latency = MCSchedModel::computeInstrLatency(STI, SCDesc);136// Add extra latency due to delays in the forwarding data paths.137IIVDEntry.Latency += MCSchedModel::getForwardingDelayCycles(138STI.getReadAdvanceEntries(SCDesc));139IIVDEntry.RThroughput = MCSchedModel::getReciprocalThroughput(STI, SCDesc);140IIVDEntry.mayLoad = MCDesc.mayLoad();141IIVDEntry.mayStore = MCDesc.mayStore();142IIVDEntry.hasUnmodeledSideEffects = MCDesc.hasUnmodeledSideEffects();143}144}145146// Construct a JSON object from a single InstructionInfoViewData object.147json::Object148InstructionInfoView::toJSON(const InstructionInfoViewData &IIVD) const {149json::Object JO({{"NumMicroOpcodes", IIVD.NumMicroOpcodes},150{"Latency", IIVD.Latency},151{"mayLoad", IIVD.mayLoad},152{"mayStore", IIVD.mayStore},153{"hasUnmodeledSideEffects", IIVD.hasUnmodeledSideEffects}});154JO.try_emplace("RThroughput", IIVD.RThroughput.value_or(0.0));155return JO;156}157158json::Value InstructionInfoView::toJSON() const {159ArrayRef<llvm::MCInst> Source = getSource();160if (!Source.size())161return json::Value(0);162163IIVDVec IIVD(Source.size());164collectData(IIVD);165166json::Array InstInfo;167for (const auto &I : enumerate(IIVD)) {168const InstructionInfoViewData &IIVDEntry = I.value();169json::Object JO = toJSON(IIVDEntry);170JO.try_emplace("Instruction", (unsigned)I.index());171InstInfo.push_back(std::move(JO));172}173return json::Object({{"InstructionList", json::Value(std::move(InstInfo))}});174}175} // namespace mca.176} // namespace llvm177178179