1 //===--------------------- InstructionInfoView.cpp --------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// This file implements the InstructionInfoView API.
12 //===----------------------------------------------------------------------===//
14 #include "Views/InstructionInfoView.h"
15 #include "llvm/Support/FormattedStream.h"
16 #include "llvm/Support/JSON.h"
21 void InstructionInfoView::printView(raw_ostream
&OS
) const {
23 raw_string_ostream
TempStream(Buffer
);
25 ArrayRef
<llvm::MCInst
> Source
= getSource();
29 IIVDVec
IIVD(Source
.size());
32 TempStream
<< "\n\nInstruction Info:\n";
33 TempStream
<< "[1]: #uOps\n[2]: Latency\n[3]: RThroughput\n"
34 << "[4]: MayLoad\n[5]: MayStore\n[6]: HasSideEffects (U)\n";
36 TempStream
<< "[7]: LoadBarrier\n[8]: StoreBarrier\n";
40 TempStream
<< "[9]: Encoding Size\n";
41 TempStream
<< "\n[1] [2] [3] [4] [5] [6] [7] [8] "
42 << "[9] Encodings: Instructions:\n";
44 TempStream
<< "[7]: Encoding Size\n";
45 TempStream
<< "\n[1] [2] [3] [4] [5] [6] [7] "
46 << "Encodings: Instructions:\n";
50 TempStream
<< "\n[1] [2] [3] [4] [5] [6] [7] [8] "
53 TempStream
<< "\n[1] [2] [3] [4] [5] [6] "
58 for (const auto &[Index
, IIVDEntry
, Inst
] : enumerate(IIVD
, Source
)) {
59 TempStream
<< ' ' << IIVDEntry
.NumMicroOpcodes
<< " ";
60 if (IIVDEntry
.NumMicroOpcodes
< 10)
62 else if (IIVDEntry
.NumMicroOpcodes
< 100)
64 TempStream
<< IIVDEntry
.Latency
<< " ";
65 if (IIVDEntry
.Latency
< 10)
67 else if (IIVDEntry
.Latency
< 100)
70 if (IIVDEntry
.RThroughput
) {
71 double RT
= *IIVDEntry
.RThroughput
;
72 TempStream
<< format("%.2f", RT
) << ' ';
80 TempStream
<< (IIVDEntry
.mayLoad
? " * " : " ");
81 TempStream
<< (IIVDEntry
.mayStore
? " * " : " ");
82 TempStream
<< (IIVDEntry
.hasUnmodeledSideEffects
? " U " : " ");
85 TempStream
<< (LoweredInsts
[Index
]->isALoadBarrier() ? " * "
87 TempStream
<< (LoweredInsts
[Index
]->isAStoreBarrier() ? " * "
92 StringRef
Encoding(CE
.getEncoding(Index
));
93 unsigned EncodingSize
= Encoding
.size();
94 TempStream
<< " " << EncodingSize
95 << (EncodingSize
< 10 ? " " : " ");
97 formatted_raw_ostream
FOS(TempStream
);
98 for (unsigned i
= 0, e
= Encoding
.size(); i
!= e
; ++i
)
99 FOS
<< format("%02x ", (uint8_t)Encoding
[i
]);
104 TempStream
<< printInstructionString(Inst
) << '\n';
111 void InstructionInfoView::collectData(
112 MutableArrayRef
<InstructionInfoViewData
> IIVD
) const {
113 const llvm::MCSubtargetInfo
&STI
= getSubTargetInfo();
114 const MCSchedModel
&SM
= STI
.getSchedModel();
115 for (const auto I
: zip(getSource(), IIVD
)) {
116 const MCInst
&Inst
= std::get
<0>(I
);
117 InstructionInfoViewData
&IIVDEntry
= std::get
<1>(I
);
118 const MCInstrDesc
&MCDesc
= MCII
.get(Inst
.getOpcode());
120 // Obtain the scheduling class information from the instruction
122 auto IVecIt
= InstToInstruments
.find(&Inst
);
123 unsigned SchedClassID
=
124 IVecIt
== InstToInstruments
.end()
125 ? MCDesc
.getSchedClass()
126 : IM
.getSchedClassID(MCII
, Inst
, IVecIt
->second
);
127 unsigned CPUID
= SM
.getProcessorID();
129 // Try to solve variant scheduling classes.
130 while (SchedClassID
&& SM
.getSchedClassDesc(SchedClassID
)->isVariant())
132 STI
.resolveVariantSchedClass(SchedClassID
, &Inst
, &MCII
, CPUID
);
134 const MCSchedClassDesc
&SCDesc
= *SM
.getSchedClassDesc(SchedClassID
);
135 IIVDEntry
.NumMicroOpcodes
= SCDesc
.NumMicroOps
;
136 IIVDEntry
.Latency
= MCSchedModel::computeInstrLatency(STI
, SCDesc
);
137 // Add extra latency due to delays in the forwarding data paths.
138 IIVDEntry
.Latency
+= MCSchedModel::getForwardingDelayCycles(
139 STI
.getReadAdvanceEntries(SCDesc
));
140 IIVDEntry
.RThroughput
= MCSchedModel::getReciprocalThroughput(STI
, SCDesc
);
141 IIVDEntry
.mayLoad
= MCDesc
.mayLoad();
142 IIVDEntry
.mayStore
= MCDesc
.mayStore();
143 IIVDEntry
.hasUnmodeledSideEffects
= MCDesc
.hasUnmodeledSideEffects();
147 // Construct a JSON object from a single InstructionInfoViewData object.
149 InstructionInfoView::toJSON(const InstructionInfoViewData
&IIVD
) const {
150 json::Object
JO({{"NumMicroOpcodes", IIVD
.NumMicroOpcodes
},
151 {"Latency", IIVD
.Latency
},
152 {"mayLoad", IIVD
.mayLoad
},
153 {"mayStore", IIVD
.mayStore
},
154 {"hasUnmodeledSideEffects", IIVD
.hasUnmodeledSideEffects
}});
155 JO
.try_emplace("RThroughput", IIVD
.RThroughput
.value_or(0.0));
159 json::Value
InstructionInfoView::toJSON() const {
160 ArrayRef
<llvm::MCInst
> Source
= getSource();
162 return json::Value(0);
164 IIVDVec
IIVD(Source
.size());
167 json::Array InstInfo
;
168 for (const auto &I
: enumerate(IIVD
)) {
169 const InstructionInfoViewData
&IIVDEntry
= I
.value();
170 json::Object JO
= toJSON(IIVDEntry
);
171 JO
.try_emplace("Instruction", (unsigned)I
.index());
172 InstInfo
.push_back(std::move(JO
));
174 return json::Object({{"InstructionList", json::Value(std::move(InstInfo
))}});