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"; 3504eeddc0SDimitry Andric if (PrintBarriers) { 3604eeddc0SDimitry Andric TempStream << "[7]: LoadBarrier\n[8]: StoreBarrier\n"; 3704eeddc0SDimitry Andric } 388bcb0991SDimitry Andric if (PrintEncodings) { 3904eeddc0SDimitry Andric if (PrintBarriers) { 4004eeddc0SDimitry Andric TempStream << "[9]: Encoding Size\n"; 4104eeddc0SDimitry Andric TempStream << "\n[1] [2] [3] [4] [5] [6] [7] [8] " 4204eeddc0SDimitry Andric << "[9] Encodings: Instructions:\n"; 4304eeddc0SDimitry Andric } else { 448bcb0991SDimitry Andric TempStream << "[7]: Encoding Size\n"; 458bcb0991SDimitry Andric TempStream << "\n[1] [2] [3] [4] [5] [6] [7] " 468bcb0991SDimitry Andric << "Encodings: Instructions:\n"; 4704eeddc0SDimitry Andric } 488bcb0991SDimitry Andric } else { 4904eeddc0SDimitry Andric if (PrintBarriers) { 5004eeddc0SDimitry Andric TempStream << "\n[1] [2] [3] [4] [5] [6] [7] [8] " 5104eeddc0SDimitry Andric << "Instructions:\n"; 5204eeddc0SDimitry Andric } else { 5304eeddc0SDimitry Andric TempStream << "\n[1] [2] [3] [4] [5] [6] " 5404eeddc0SDimitry Andric << "Instructions:\n"; 5504eeddc0SDimitry Andric } 568bcb0991SDimitry Andric } 570b57cec5SDimitry Andric 5804eeddc0SDimitry Andric int Index = 0; 59e8d8bef9SDimitry Andric for (const auto &I : enumerate(zip(IIVD, Source))) { 60e8d8bef9SDimitry Andric const InstructionInfoViewData &IIVDEntry = std::get<0>(I.value()); 610b57cec5SDimitry Andric 62e8d8bef9SDimitry Andric TempStream << ' ' << IIVDEntry.NumMicroOpcodes << " "; 63e8d8bef9SDimitry Andric if (IIVDEntry.NumMicroOpcodes < 10) 640b57cec5SDimitry Andric TempStream << " "; 65e8d8bef9SDimitry Andric else if (IIVDEntry.NumMicroOpcodes < 100) 660b57cec5SDimitry Andric TempStream << ' '; 67e8d8bef9SDimitry Andric TempStream << IIVDEntry.Latency << " "; 68e8d8bef9SDimitry Andric if (IIVDEntry.Latency < 10) 690b57cec5SDimitry Andric TempStream << " "; 70e8d8bef9SDimitry Andric else if (IIVDEntry.Latency < 100) 710b57cec5SDimitry Andric TempStream << ' '; 720b57cec5SDimitry Andric 7381ad6265SDimitry Andric if (IIVDEntry.RThroughput) { 74*bdd1243dSDimitry Andric double RT = *IIVDEntry.RThroughput; 750b57cec5SDimitry Andric TempStream << format("%.2f", RT) << ' '; 760b57cec5SDimitry Andric if (RT < 10.0) 770b57cec5SDimitry Andric TempStream << " "; 780b57cec5SDimitry Andric else if (RT < 100.0) 790b57cec5SDimitry Andric TempStream << ' '; 800b57cec5SDimitry Andric } else { 810b57cec5SDimitry Andric TempStream << " - "; 820b57cec5SDimitry Andric } 83e8d8bef9SDimitry Andric TempStream << (IIVDEntry.mayLoad ? " * " : " "); 84e8d8bef9SDimitry Andric TempStream << (IIVDEntry.mayStore ? " * " : " "); 85e8d8bef9SDimitry Andric TempStream << (IIVDEntry.hasUnmodeledSideEffects ? " U " : " "); 860b57cec5SDimitry Andric 8704eeddc0SDimitry Andric if (PrintBarriers) { 8804eeddc0SDimitry Andric TempStream << (LoweredInsts[Index]->isALoadBarrier() ? " * " 8904eeddc0SDimitry Andric : " "); 9004eeddc0SDimitry Andric TempStream << (LoweredInsts[Index]->isAStoreBarrier() ? " * " 9104eeddc0SDimitry Andric : " "); 9204eeddc0SDimitry Andric } 9304eeddc0SDimitry Andric 948bcb0991SDimitry Andric if (PrintEncodings) { 95e8d8bef9SDimitry Andric StringRef Encoding(CE.getEncoding(I.index())); 968bcb0991SDimitry Andric unsigned EncodingSize = Encoding.size(); 978bcb0991SDimitry Andric TempStream << " " << EncodingSize 988bcb0991SDimitry Andric << (EncodingSize < 10 ? " " : " "); 998bcb0991SDimitry Andric TempStream.flush(); 1008bcb0991SDimitry Andric formatted_raw_ostream FOS(TempStream); 1018bcb0991SDimitry Andric for (unsigned i = 0, e = Encoding.size(); i != e; ++i) 1028bcb0991SDimitry Andric FOS << format("%02x ", (uint8_t)Encoding[i]); 1038bcb0991SDimitry Andric FOS.PadToColumn(30); 1048bcb0991SDimitry Andric FOS.flush(); 1058bcb0991SDimitry Andric } 1068bcb0991SDimitry Andric 107e8d8bef9SDimitry Andric const MCInst &Inst = std::get<1>(I.value()); 108e8d8bef9SDimitry Andric TempStream << printInstructionString(Inst) << '\n'; 10904eeddc0SDimitry Andric ++Index; 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric TempStream.flush(); 1130b57cec5SDimitry Andric OS << Buffer; 1140b57cec5SDimitry Andric } 115e8d8bef9SDimitry Andric 116e8d8bef9SDimitry Andric void InstructionInfoView::collectData( 117e8d8bef9SDimitry Andric MutableArrayRef<InstructionInfoViewData> IIVD) const { 118e8d8bef9SDimitry Andric const llvm::MCSubtargetInfo &STI = getSubTargetInfo(); 119e8d8bef9SDimitry Andric const MCSchedModel &SM = STI.getSchedModel(); 120fe6060f1SDimitry Andric for (const auto I : zip(getSource(), IIVD)) { 121e8d8bef9SDimitry Andric const MCInst &Inst = std::get<0>(I); 122e8d8bef9SDimitry Andric InstructionInfoViewData &IIVDEntry = std::get<1>(I); 123e8d8bef9SDimitry Andric const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode()); 124e8d8bef9SDimitry Andric 125e8d8bef9SDimitry Andric // Obtain the scheduling class information from the instruction. 126e8d8bef9SDimitry Andric unsigned SchedClassID = MCDesc.getSchedClass(); 127e8d8bef9SDimitry Andric unsigned CPUID = SM.getProcessorID(); 128e8d8bef9SDimitry Andric 129e8d8bef9SDimitry Andric // Try to solve variant scheduling classes. 130e8d8bef9SDimitry Andric while (SchedClassID && SM.getSchedClassDesc(SchedClassID)->isVariant()) 131e8d8bef9SDimitry Andric SchedClassID = 132e8d8bef9SDimitry Andric STI.resolveVariantSchedClass(SchedClassID, &Inst, &MCII, CPUID); 133e8d8bef9SDimitry Andric 134e8d8bef9SDimitry Andric const MCSchedClassDesc &SCDesc = *SM.getSchedClassDesc(SchedClassID); 135e8d8bef9SDimitry Andric IIVDEntry.NumMicroOpcodes = SCDesc.NumMicroOps; 136e8d8bef9SDimitry Andric IIVDEntry.Latency = MCSchedModel::computeInstrLatency(STI, SCDesc); 137e8d8bef9SDimitry Andric // Add extra latency due to delays in the forwarding data paths. 138e8d8bef9SDimitry Andric IIVDEntry.Latency += MCSchedModel::getForwardingDelayCycles( 139e8d8bef9SDimitry Andric STI.getReadAdvanceEntries(SCDesc)); 140e8d8bef9SDimitry Andric IIVDEntry.RThroughput = MCSchedModel::getReciprocalThroughput(STI, SCDesc); 141e8d8bef9SDimitry Andric IIVDEntry.mayLoad = MCDesc.mayLoad(); 142e8d8bef9SDimitry Andric IIVDEntry.mayStore = MCDesc.mayStore(); 143e8d8bef9SDimitry Andric IIVDEntry.hasUnmodeledSideEffects = MCDesc.hasUnmodeledSideEffects(); 144e8d8bef9SDimitry Andric } 145e8d8bef9SDimitry Andric } 146e8d8bef9SDimitry Andric 147e8d8bef9SDimitry Andric // Construct a JSON object from a single InstructionInfoViewData object. 148e8d8bef9SDimitry Andric json::Object 149e8d8bef9SDimitry Andric InstructionInfoView::toJSON(const InstructionInfoViewData &IIVD) const { 150e8d8bef9SDimitry Andric json::Object JO({{"NumMicroOpcodes", IIVD.NumMicroOpcodes}, 151e8d8bef9SDimitry Andric {"Latency", IIVD.Latency}, 152e8d8bef9SDimitry Andric {"mayLoad", IIVD.mayLoad}, 153e8d8bef9SDimitry Andric {"mayStore", IIVD.mayStore}, 154e8d8bef9SDimitry Andric {"hasUnmodeledSideEffects", IIVD.hasUnmodeledSideEffects}}); 15581ad6265SDimitry Andric JO.try_emplace("RThroughput", IIVD.RThroughput.value_or(0.0)); 156e8d8bef9SDimitry Andric return JO; 157e8d8bef9SDimitry Andric } 158e8d8bef9SDimitry Andric 159e8d8bef9SDimitry Andric json::Value InstructionInfoView::toJSON() const { 160e8d8bef9SDimitry Andric ArrayRef<llvm::MCInst> Source = getSource(); 161e8d8bef9SDimitry Andric if (!Source.size()) 162e8d8bef9SDimitry Andric return json::Value(0); 163e8d8bef9SDimitry Andric 164e8d8bef9SDimitry Andric IIVDVec IIVD(Source.size()); 165e8d8bef9SDimitry Andric collectData(IIVD); 166e8d8bef9SDimitry Andric 167e8d8bef9SDimitry Andric json::Array InstInfo; 168e8d8bef9SDimitry Andric for (const auto &I : enumerate(IIVD)) { 169e8d8bef9SDimitry Andric const InstructionInfoViewData &IIVDEntry = I.value(); 170e8d8bef9SDimitry Andric json::Object JO = toJSON(IIVDEntry); 171e8d8bef9SDimitry Andric JO.try_emplace("Instruction", (unsigned)I.index()); 172e8d8bef9SDimitry Andric InstInfo.push_back(std::move(JO)); 173e8d8bef9SDimitry Andric } 174fe6060f1SDimitry Andric return json::Object({{"InstructionList", json::Value(std::move(InstInfo))}}); 175e8d8bef9SDimitry Andric } 1760b57cec5SDimitry Andric } // namespace mca. 1770b57cec5SDimitry Andric } // namespace llvm 178