11d1330c5SRoman Lebedev //===-- SchedClassResolution.cpp --------------------------------*- C++ -*-===//
21d1330c5SRoman Lebedev //
31d1330c5SRoman Lebedev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41d1330c5SRoman Lebedev // See https://llvm.org/LICENSE.txt for license information.
51d1330c5SRoman Lebedev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61d1330c5SRoman Lebedev //
71d1330c5SRoman Lebedev //===----------------------------------------------------------------------===//
81d1330c5SRoman Lebedev
91d1330c5SRoman Lebedev #include "SchedClassResolution.h"
101d1330c5SRoman Lebedev #include "BenchmarkResult.h"
111d1330c5SRoman Lebedev #include "llvm/ADT/STLExtras.h"
121d1330c5SRoman Lebedev #include "llvm/MC/MCAsmInfo.h"
131d1330c5SRoman Lebedev #include "llvm/Support/FormatVariadic.h"
141d1330c5SRoman Lebedev #include <limits>
151d1330c5SRoman Lebedev #include <unordered_set>
161d1330c5SRoman Lebedev #include <vector>
171d1330c5SRoman Lebedev
181d1330c5SRoman Lebedev namespace llvm {
191d1330c5SRoman Lebedev namespace exegesis {
201d1330c5SRoman Lebedev
211d1330c5SRoman Lebedev // Return the non-redundant list of WriteProcRes used by the given sched class.
221d1330c5SRoman Lebedev // The scheduling model for LLVM is such that each instruction has a certain
231d1330c5SRoman Lebedev // number of uops which consume resources which are described by WriteProcRes
241d1330c5SRoman Lebedev // entries. Each entry describe how many cycles are spent on a specific ProcRes
251d1330c5SRoman Lebedev // kind.
261d1330c5SRoman Lebedev // For example, an instruction might have 3 uOps, one dispatching on P0
271d1330c5SRoman Lebedev // (ProcResIdx=1) and two on P06 (ProcResIdx = 7).
281d1330c5SRoman Lebedev // Note that LLVM additionally denormalizes resource consumption to include
291d1330c5SRoman Lebedev // usage of super resources by subresources. So in practice if there exists a
301d1330c5SRoman Lebedev // P016 (ProcResIdx=10), then the cycles consumed by P0 are also consumed by
311d1330c5SRoman Lebedev // P06 (ProcResIdx = 7) and P016 (ProcResIdx = 10), and the resources consumed
321d1330c5SRoman Lebedev // by P06 are also consumed by P016. In the figure below, parenthesized cycles
331d1330c5SRoman Lebedev // denote implied usage of superresources by subresources:
341d1330c5SRoman Lebedev // P0 P06 P016
351d1330c5SRoman Lebedev // uOp1 1 (1) (1)
361d1330c5SRoman Lebedev // uOp2 1 (1)
371d1330c5SRoman Lebedev // uOp3 1 (1)
381d1330c5SRoman Lebedev // =============================
391d1330c5SRoman Lebedev // 1 3 3
401d1330c5SRoman Lebedev // Eventually we end up with three entries for the WriteProcRes of the
411d1330c5SRoman Lebedev // instruction:
421d1330c5SRoman Lebedev // {ProcResIdx=1, Cycles=1} // P0
431d1330c5SRoman Lebedev // {ProcResIdx=7, Cycles=3} // P06
441d1330c5SRoman Lebedev // {ProcResIdx=10, Cycles=3} // P016
451d1330c5SRoman Lebedev //
461d1330c5SRoman Lebedev // Note that in this case, P016 does not contribute any cycles, so it would
471d1330c5SRoman Lebedev // be removed by this function.
481d1330c5SRoman Lebedev // FIXME: Move this to MCSubtargetInfo and use it in llvm-mca.
4950cdd56bSClement Courbet static SmallVector<MCWriteProcResEntry, 8>
getNonRedundantWriteProcRes(const MCSchedClassDesc & SCDesc,const MCSubtargetInfo & STI)5050cdd56bSClement Courbet getNonRedundantWriteProcRes(const MCSchedClassDesc &SCDesc,
5150cdd56bSClement Courbet const MCSubtargetInfo &STI) {
5250cdd56bSClement Courbet SmallVector<MCWriteProcResEntry, 8> Result;
531d1330c5SRoman Lebedev const auto &SM = STI.getSchedModel();
541d1330c5SRoman Lebedev const unsigned NumProcRes = SM.getNumProcResourceKinds();
551d1330c5SRoman Lebedev
561d1330c5SRoman Lebedev // This assumes that the ProcResDescs are sorted in topological order, which
571d1330c5SRoman Lebedev // is guaranteed by the tablegen backend.
5850cdd56bSClement Courbet SmallVector<float, 32> ProcResUnitUsage(NumProcRes);
591d1330c5SRoman Lebedev for (const auto *WPR = STI.getWriteProcResBegin(&SCDesc),
601d1330c5SRoman Lebedev *const WPREnd = STI.getWriteProcResEnd(&SCDesc);
611d1330c5SRoman Lebedev WPR != WPREnd; ++WPR) {
6250cdd56bSClement Courbet const MCProcResourceDesc *const ProcResDesc =
631d1330c5SRoman Lebedev SM.getProcResource(WPR->ProcResourceIdx);
641d1330c5SRoman Lebedev if (ProcResDesc->SubUnitsIdxBegin == nullptr) {
651d1330c5SRoman Lebedev // This is a ProcResUnit.
661d1330c5SRoman Lebedev Result.push_back({WPR->ProcResourceIdx, WPR->Cycles});
671d1330c5SRoman Lebedev ProcResUnitUsage[WPR->ProcResourceIdx] += WPR->Cycles;
681d1330c5SRoman Lebedev } else {
691d1330c5SRoman Lebedev // This is a ProcResGroup. First see if it contributes any cycles or if
701d1330c5SRoman Lebedev // it has cycles just from subunits.
711d1330c5SRoman Lebedev float RemainingCycles = WPR->Cycles;
721d1330c5SRoman Lebedev for (const auto *SubResIdx = ProcResDesc->SubUnitsIdxBegin;
731d1330c5SRoman Lebedev SubResIdx != ProcResDesc->SubUnitsIdxBegin + ProcResDesc->NumUnits;
741d1330c5SRoman Lebedev ++SubResIdx) {
751d1330c5SRoman Lebedev RemainingCycles -= ProcResUnitUsage[*SubResIdx];
761d1330c5SRoman Lebedev }
771d1330c5SRoman Lebedev if (RemainingCycles < 0.01f) {
781d1330c5SRoman Lebedev // The ProcResGroup contributes no cycles of its own.
791d1330c5SRoman Lebedev continue;
801d1330c5SRoman Lebedev }
811d1330c5SRoman Lebedev // The ProcResGroup contributes `RemainingCycles` cycles of its own.
821d1330c5SRoman Lebedev Result.push_back({WPR->ProcResourceIdx,
831d1330c5SRoman Lebedev static_cast<uint16_t>(std::round(RemainingCycles))});
841d1330c5SRoman Lebedev // Spread the remaining cycles over all subunits.
851d1330c5SRoman Lebedev for (const auto *SubResIdx = ProcResDesc->SubUnitsIdxBegin;
861d1330c5SRoman Lebedev SubResIdx != ProcResDesc->SubUnitsIdxBegin + ProcResDesc->NumUnits;
871d1330c5SRoman Lebedev ++SubResIdx) {
881d1330c5SRoman Lebedev ProcResUnitUsage[*SubResIdx] += RemainingCycles / ProcResDesc->NumUnits;
891d1330c5SRoman Lebedev }
901d1330c5SRoman Lebedev }
911d1330c5SRoman Lebedev }
921d1330c5SRoman Lebedev return Result;
931d1330c5SRoman Lebedev }
941d1330c5SRoman Lebedev
951d1330c5SRoman Lebedev // Distributes a pressure budget as evenly as possible on the provided subunits
961d1330c5SRoman Lebedev // given the already existing port pressure distribution.
971d1330c5SRoman Lebedev //
981d1330c5SRoman Lebedev // The algorithm is as follows: while there is remaining pressure to
991d1330c5SRoman Lebedev // distribute, find the subunits with minimal pressure, and distribute
1001d1330c5SRoman Lebedev // remaining pressure equally up to the pressure of the unit with
1011d1330c5SRoman Lebedev // second-to-minimal pressure.
1021d1330c5SRoman Lebedev // For example, let's assume we want to distribute 2*P1256
1031d1330c5SRoman Lebedev // (Subunits = [P1,P2,P5,P6]), and the starting DensePressure is:
1041d1330c5SRoman Lebedev // DensePressure = P0 P1 P2 P3 P4 P5 P6 P7
1051d1330c5SRoman Lebedev // 0.1 0.3 0.2 0.0 0.0 0.5 0.5 0.5
1061d1330c5SRoman Lebedev // RemainingPressure = 2.0
1071d1330c5SRoman Lebedev // We sort the subunits by pressure:
1081d1330c5SRoman Lebedev // Subunits = [(P2,p=0.2), (P1,p=0.3), (P5,p=0.5), (P6, p=0.5)]
1091d1330c5SRoman Lebedev // We'll first start by the subunits with minimal pressure, which are at
1101d1330c5SRoman Lebedev // the beginning of the sorted array. In this example there is one (P2).
1111d1330c5SRoman Lebedev // The subunit with second-to-minimal pressure is the next one in the
1121d1330c5SRoman Lebedev // array (P1). So we distribute 0.1 pressure to P2, and remove 0.1 cycles
1131d1330c5SRoman Lebedev // from the budget.
1141d1330c5SRoman Lebedev // Subunits = [(P2,p=0.3), (P1,p=0.3), (P5,p=0.5), (P5,p=0.5)]
1151d1330c5SRoman Lebedev // RemainingPressure = 1.9
1161d1330c5SRoman Lebedev // We repeat this process: distribute 0.2 pressure on each of the minimal
1171d1330c5SRoman Lebedev // P2 and P1, decrease budget by 2*0.2:
1181d1330c5SRoman Lebedev // Subunits = [(P2,p=0.5), (P1,p=0.5), (P5,p=0.5), (P5,p=0.5)]
1191d1330c5SRoman Lebedev // RemainingPressure = 1.5
1201d1330c5SRoman Lebedev // There are no second-to-minimal subunits so we just share the remaining
1211d1330c5SRoman Lebedev // budget (1.5 cycles) equally:
1221d1330c5SRoman Lebedev // Subunits = [(P2,p=0.875), (P1,p=0.875), (P5,p=0.875), (P5,p=0.875)]
1231d1330c5SRoman Lebedev // RemainingPressure = 0.0
1241d1330c5SRoman Lebedev // We stop as there is no remaining budget to distribute.
distributePressure(float RemainingPressure,SmallVector<uint16_t,32> Subunits,SmallVector<float,32> & DensePressure)1251d1330c5SRoman Lebedev static void distributePressure(float RemainingPressure,
12650cdd56bSClement Courbet SmallVector<uint16_t, 32> Subunits,
12750cdd56bSClement Courbet SmallVector<float, 32> &DensePressure) {
1281d1330c5SRoman Lebedev // Find the number of subunits with minimal pressure (they are at the
1291d1330c5SRoman Lebedev // front).
13050cdd56bSClement Courbet sort(Subunits, [&DensePressure](const uint16_t A, const uint16_t B) {
1311d1330c5SRoman Lebedev return DensePressure[A] < DensePressure[B];
1321d1330c5SRoman Lebedev });
1331d1330c5SRoman Lebedev const auto getPressureForSubunit = [&DensePressure,
1341d1330c5SRoman Lebedev &Subunits](size_t I) -> float & {
1351d1330c5SRoman Lebedev return DensePressure[Subunits[I]];
1361d1330c5SRoman Lebedev };
1371d1330c5SRoman Lebedev size_t NumMinimalSU = 1;
1381d1330c5SRoman Lebedev while (NumMinimalSU < Subunits.size() &&
1391d1330c5SRoman Lebedev getPressureForSubunit(NumMinimalSU) == getPressureForSubunit(0)) {
1401d1330c5SRoman Lebedev ++NumMinimalSU;
1411d1330c5SRoman Lebedev }
1421d1330c5SRoman Lebedev while (RemainingPressure > 0.0f) {
1431d1330c5SRoman Lebedev if (NumMinimalSU == Subunits.size()) {
1441d1330c5SRoman Lebedev // All units are minimal, just distribute evenly and be done.
1451d1330c5SRoman Lebedev for (size_t I = 0; I < NumMinimalSU; ++I) {
1461d1330c5SRoman Lebedev getPressureForSubunit(I) += RemainingPressure / NumMinimalSU;
1471d1330c5SRoman Lebedev }
1481d1330c5SRoman Lebedev return;
1491d1330c5SRoman Lebedev }
1501d1330c5SRoman Lebedev // Distribute the remaining pressure equally.
1511d1330c5SRoman Lebedev const float MinimalPressure = getPressureForSubunit(NumMinimalSU - 1);
1521d1330c5SRoman Lebedev const float SecondToMinimalPressure = getPressureForSubunit(NumMinimalSU);
1531d1330c5SRoman Lebedev assert(MinimalPressure < SecondToMinimalPressure);
1541d1330c5SRoman Lebedev const float Increment = SecondToMinimalPressure - MinimalPressure;
1551d1330c5SRoman Lebedev if (RemainingPressure <= NumMinimalSU * Increment) {
1561d1330c5SRoman Lebedev // There is not enough remaining pressure.
1571d1330c5SRoman Lebedev for (size_t I = 0; I < NumMinimalSU; ++I) {
1581d1330c5SRoman Lebedev getPressureForSubunit(I) += RemainingPressure / NumMinimalSU;
1591d1330c5SRoman Lebedev }
1601d1330c5SRoman Lebedev return;
1611d1330c5SRoman Lebedev }
1621d1330c5SRoman Lebedev // Bump all minimal pressure subunits to `SecondToMinimalPressure`.
1631d1330c5SRoman Lebedev for (size_t I = 0; I < NumMinimalSU; ++I) {
1641d1330c5SRoman Lebedev getPressureForSubunit(I) = SecondToMinimalPressure;
1651d1330c5SRoman Lebedev RemainingPressure -= SecondToMinimalPressure;
1661d1330c5SRoman Lebedev }
1671d1330c5SRoman Lebedev while (NumMinimalSU < Subunits.size() &&
1681d1330c5SRoman Lebedev getPressureForSubunit(NumMinimalSU) == SecondToMinimalPressure) {
1691d1330c5SRoman Lebedev ++NumMinimalSU;
1701d1330c5SRoman Lebedev }
1711d1330c5SRoman Lebedev }
1721d1330c5SRoman Lebedev }
1731d1330c5SRoman Lebedev
17450cdd56bSClement Courbet std::vector<std::pair<uint16_t, float>>
computeIdealizedProcResPressure(const MCSchedModel & SM,SmallVector<MCWriteProcResEntry,8> WPRS)17550cdd56bSClement Courbet computeIdealizedProcResPressure(const MCSchedModel &SM,
17650cdd56bSClement Courbet SmallVector<MCWriteProcResEntry, 8> WPRS) {
1771d1330c5SRoman Lebedev // DensePressure[I] is the port pressure for Proc Resource I.
17850cdd56bSClement Courbet SmallVector<float, 32> DensePressure(SM.getNumProcResourceKinds());
17950cdd56bSClement Courbet sort(WPRS, [](const MCWriteProcResEntry &A, const MCWriteProcResEntry &B) {
1801d1330c5SRoman Lebedev return A.ProcResourceIdx < B.ProcResourceIdx;
1811d1330c5SRoman Lebedev });
18250cdd56bSClement Courbet for (const MCWriteProcResEntry &WPR : WPRS) {
1831d1330c5SRoman Lebedev // Get units for the entry.
18450cdd56bSClement Courbet const MCProcResourceDesc *const ProcResDesc =
1851d1330c5SRoman Lebedev SM.getProcResource(WPR.ProcResourceIdx);
1861d1330c5SRoman Lebedev if (ProcResDesc->SubUnitsIdxBegin == nullptr) {
1871d1330c5SRoman Lebedev // This is a ProcResUnit.
1881d1330c5SRoman Lebedev DensePressure[WPR.ProcResourceIdx] += WPR.Cycles;
1891d1330c5SRoman Lebedev } else {
1901d1330c5SRoman Lebedev // This is a ProcResGroup.
19150cdd56bSClement Courbet SmallVector<uint16_t, 32> Subunits(ProcResDesc->SubUnitsIdxBegin,
1921d1330c5SRoman Lebedev ProcResDesc->SubUnitsIdxBegin +
1931d1330c5SRoman Lebedev ProcResDesc->NumUnits);
1941d1330c5SRoman Lebedev distributePressure(WPR.Cycles, Subunits, DensePressure);
1951d1330c5SRoman Lebedev }
1961d1330c5SRoman Lebedev }
1971d1330c5SRoman Lebedev // Turn dense pressure into sparse pressure by removing zero entries.
1981d1330c5SRoman Lebedev std::vector<std::pair<uint16_t, float>> Pressure;
1991d1330c5SRoman Lebedev for (unsigned I = 0, E = SM.getNumProcResourceKinds(); I < E; ++I) {
2001d1330c5SRoman Lebedev if (DensePressure[I] > 0.0f)
2011d1330c5SRoman Lebedev Pressure.emplace_back(I, DensePressure[I]);
2021d1330c5SRoman Lebedev }
2031d1330c5SRoman Lebedev return Pressure;
2041d1330c5SRoman Lebedev }
2051d1330c5SRoman Lebedev
ResolvedSchedClass(const MCSubtargetInfo & STI,unsigned ResolvedSchedClassId,bool WasVariant)20650cdd56bSClement Courbet ResolvedSchedClass::ResolvedSchedClass(const MCSubtargetInfo &STI,
2071d1330c5SRoman Lebedev unsigned ResolvedSchedClassId,
2081d1330c5SRoman Lebedev bool WasVariant)
2091d1330c5SRoman Lebedev : SchedClassId(ResolvedSchedClassId),
2101d1330c5SRoman Lebedev SCDesc(STI.getSchedModel().getSchedClassDesc(ResolvedSchedClassId)),
2111d1330c5SRoman Lebedev WasVariant(WasVariant),
2121d1330c5SRoman Lebedev NonRedundantWriteProcRes(getNonRedundantWriteProcRes(*SCDesc, STI)),
2131d1330c5SRoman Lebedev IdealizedProcResPressure(computeIdealizedProcResPressure(
2141d1330c5SRoman Lebedev STI.getSchedModel(), NonRedundantWriteProcRes)) {
2151d1330c5SRoman Lebedev assert((SCDesc == nullptr || !SCDesc->isVariant()) &&
2161d1330c5SRoman Lebedev "ResolvedSchedClass should never be variant");
2171d1330c5SRoman Lebedev }
2181d1330c5SRoman Lebedev
ResolveVariantSchedClassId(const MCSubtargetInfo & STI,const MCInstrInfo & InstrInfo,unsigned SchedClassId,const MCInst & MCI)21950cdd56bSClement Courbet static unsigned ResolveVariantSchedClassId(const MCSubtargetInfo &STI,
2208a7ca143SEvgeny Leviant const MCInstrInfo &InstrInfo,
2211d1330c5SRoman Lebedev unsigned SchedClassId,
22250cdd56bSClement Courbet const MCInst &MCI) {
2231d1330c5SRoman Lebedev const auto &SM = STI.getSchedModel();
2248a7ca143SEvgeny Leviant while (SchedClassId && SM.getSchedClassDesc(SchedClassId)->isVariant()) {
2258a7ca143SEvgeny Leviant SchedClassId = STI.resolveVariantSchedClass(SchedClassId, &MCI, &InstrInfo,
2268a7ca143SEvgeny Leviant SM.getProcessorID());
2278a7ca143SEvgeny Leviant }
2281d1330c5SRoman Lebedev return SchedClassId;
2291d1330c5SRoman Lebedev }
2301d1330c5SRoman Lebedev
2311d1330c5SRoman Lebedev std::pair<unsigned /*SchedClassId*/, bool /*WasVariant*/>
resolveSchedClassId(const MCSubtargetInfo & SubtargetInfo,const MCInstrInfo & InstrInfo,const MCInst & MCI)23250cdd56bSClement Courbet ResolvedSchedClass::resolveSchedClassId(const MCSubtargetInfo &SubtargetInfo,
23350cdd56bSClement Courbet const MCInstrInfo &InstrInfo,
23450cdd56bSClement Courbet const MCInst &MCI) {
2351d1330c5SRoman Lebedev unsigned SchedClassId = InstrInfo.get(MCI.getOpcode()).getSchedClass();
2361d1330c5SRoman Lebedev const bool WasVariant = SchedClassId && SubtargetInfo.getSchedModel()
2371d1330c5SRoman Lebedev .getSchedClassDesc(SchedClassId)
2381d1330c5SRoman Lebedev ->isVariant();
2398a7ca143SEvgeny Leviant SchedClassId =
2408a7ca143SEvgeny Leviant ResolveVariantSchedClassId(SubtargetInfo, InstrInfo, SchedClassId, MCI);
2411d1330c5SRoman Lebedev return std::make_pair(SchedClassId, WasVariant);
2421d1330c5SRoman Lebedev }
2431d1330c5SRoman Lebedev
2444d81e877SRoman Lebedev // Returns a ProxResIdx by id or name.
findProcResIdx(const MCSubtargetInfo & STI,const StringRef NameOrId)24550cdd56bSClement Courbet static unsigned findProcResIdx(const MCSubtargetInfo &STI,
24650cdd56bSClement Courbet const StringRef NameOrId) {
2474d81e877SRoman Lebedev // Interpret the key as an ProcResIdx.
2484d81e877SRoman Lebedev unsigned ProcResIdx = 0;
24950cdd56bSClement Courbet if (to_integer(NameOrId, ProcResIdx, 10))
2504d81e877SRoman Lebedev return ProcResIdx;
2514d81e877SRoman Lebedev // Interpret the key as a ProcRes name.
2524d81e877SRoman Lebedev const auto &SchedModel = STI.getSchedModel();
2534d81e877SRoman Lebedev for (int I = 0, E = SchedModel.getNumProcResourceKinds(); I < E; ++I) {
2544d81e877SRoman Lebedev if (NameOrId == SchedModel.getProcResource(I)->Name)
2554d81e877SRoman Lebedev return I;
2564d81e877SRoman Lebedev }
2574d81e877SRoman Lebedev return 0;
2584d81e877SRoman Lebedev }
2594d81e877SRoman Lebedev
getAsPoint(InstructionBenchmark::ModeE Mode,const MCSubtargetInfo & STI,ArrayRef<PerInstructionStats> Representative) const2604d81e877SRoman Lebedev std::vector<BenchmarkMeasure> ResolvedSchedClass::getAsPoint(
26150cdd56bSClement Courbet InstructionBenchmark::ModeE Mode, const MCSubtargetInfo &STI,
2624d81e877SRoman Lebedev ArrayRef<PerInstructionStats> Representative) const {
2634d81e877SRoman Lebedev const size_t NumMeasurements = Representative.size();
2644d81e877SRoman Lebedev
2654d81e877SRoman Lebedev std::vector<BenchmarkMeasure> SchedClassPoint(NumMeasurements);
2664d81e877SRoman Lebedev
2674d81e877SRoman Lebedev if (Mode == InstructionBenchmark::Latency) {
2684d81e877SRoman Lebedev assert(NumMeasurements == 1 && "Latency is a single measure.");
2694d81e877SRoman Lebedev BenchmarkMeasure &LatencyMeasure = SchedClassPoint[0];
2704d81e877SRoman Lebedev
2714d81e877SRoman Lebedev // Find the latency.
2724d81e877SRoman Lebedev LatencyMeasure.PerInstructionValue = 0.0;
2734d81e877SRoman Lebedev
2744d81e877SRoman Lebedev for (unsigned I = 0; I < SCDesc->NumWriteLatencyEntries; ++I) {
27550cdd56bSClement Courbet const MCWriteLatencyEntry *const WLE =
2764d81e877SRoman Lebedev STI.getWriteLatencyEntry(SCDesc, I);
2774d81e877SRoman Lebedev LatencyMeasure.PerInstructionValue =
2784d81e877SRoman Lebedev std::max<double>(LatencyMeasure.PerInstructionValue, WLE->Cycles);
2794d81e877SRoman Lebedev }
2804d81e877SRoman Lebedev } else if (Mode == InstructionBenchmark::Uops) {
281536c9a60SMark de Wever for (auto I : zip(SchedClassPoint, Representative)) {
2824d81e877SRoman Lebedev BenchmarkMeasure &Measure = std::get<0>(I);
2834d81e877SRoman Lebedev const PerInstructionStats &Stats = std::get<1>(I);
2844d81e877SRoman Lebedev
2854d81e877SRoman Lebedev StringRef Key = Stats.key();
2864d81e877SRoman Lebedev uint16_t ProcResIdx = findProcResIdx(STI, Key);
2874d81e877SRoman Lebedev if (ProcResIdx > 0) {
2884d81e877SRoman Lebedev // Find the pressure on ProcResIdx `Key`.
289*89e8eb94SKazu Hirata const auto ProcResPressureIt =
290*89e8eb94SKazu Hirata llvm::find_if(IdealizedProcResPressure,
2914d81e877SRoman Lebedev [ProcResIdx](const std::pair<uint16_t, float> &WPR) {
2924d81e877SRoman Lebedev return WPR.first == ProcResIdx;
2934d81e877SRoman Lebedev });
2944d81e877SRoman Lebedev Measure.PerInstructionValue =
2954d81e877SRoman Lebedev ProcResPressureIt == IdealizedProcResPressure.end()
2964d81e877SRoman Lebedev ? 0.0
2974d81e877SRoman Lebedev : ProcResPressureIt->second;
2984d81e877SRoman Lebedev } else if (Key == "NumMicroOps") {
2994d81e877SRoman Lebedev Measure.PerInstructionValue = SCDesc->NumMicroOps;
3004d81e877SRoman Lebedev } else {
30150cdd56bSClement Courbet errs() << "expected `key` to be either a ProcResIdx or a ProcRes "
3024d81e877SRoman Lebedev "name, got "
3034d81e877SRoman Lebedev << Key << "\n";
3044d81e877SRoman Lebedev return {};
3054d81e877SRoman Lebedev }
3064d81e877SRoman Lebedev }
3074d81e877SRoman Lebedev } else if (Mode == InstructionBenchmark::InverseThroughput) {
3084d81e877SRoman Lebedev assert(NumMeasurements == 1 && "Inverse Throughput is a single measure.");
3094d81e877SRoman Lebedev BenchmarkMeasure &RThroughputMeasure = SchedClassPoint[0];
3104d81e877SRoman Lebedev
3114d81e877SRoman Lebedev RThroughputMeasure.PerInstructionValue =
3124d81e877SRoman Lebedev MCSchedModel::getReciprocalThroughput(STI, *SCDesc);
3134d81e877SRoman Lebedev } else {
3144d81e877SRoman Lebedev llvm_unreachable("unimplemented measurement matching mode");
3154d81e877SRoman Lebedev }
3164d81e877SRoman Lebedev
3174d81e877SRoman Lebedev return SchedClassPoint;
3184d81e877SRoman Lebedev }
3194d81e877SRoman Lebedev
3201d1330c5SRoman Lebedev } // namespace exegesis
3211d1330c5SRoman Lebedev } // namespace llvm
322