xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/TargetSchedule.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- llvm/Target/TargetSchedule.cpp - Sched Machine Model ---------------===//
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 //
90b57cec5SDimitry Andric // This file implements a wrapper around MCSchedModel that allows the interface
100b57cec5SDimitry Andric // to benefit from information currently only available in TargetInstrInfo.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSchedule.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCInstrItineraries.h"
220b57cec5SDimitry Andric #include "llvm/MC/MCSchedule.h"
230b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
260b57cec5SDimitry Andric #include <algorithm>
270b57cec5SDimitry Andric #include <cassert>
280b57cec5SDimitry Andric #include <cstdint>
29bdd1243dSDimitry Andric #include <numeric>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric using namespace llvm;
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric static cl::opt<bool> EnableSchedModel("schedmodel", cl::Hidden, cl::init(true),
340b57cec5SDimitry Andric   cl::desc("Use TargetSchedModel for latency lookup"));
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric static cl::opt<bool> EnableSchedItins("scheditins", cl::Hidden, cl::init(true),
370b57cec5SDimitry Andric   cl::desc("Use InstrItineraryData for latency lookup"));
380b57cec5SDimitry Andric 
39*5f757f3fSDimitry Andric static cl::opt<bool> ForceEnableIntervals(
40*5f757f3fSDimitry Andric     "sched-model-force-enable-intervals", cl::Hidden, cl::init(false),
41*5f757f3fSDimitry Andric     cl::desc("Force the use of resource intervals in the schedule model"));
42*5f757f3fSDimitry Andric 
hasInstrSchedModel() const430b57cec5SDimitry Andric bool TargetSchedModel::hasInstrSchedModel() const {
440b57cec5SDimitry Andric   return EnableSchedModel && SchedModel.hasInstrSchedModel();
450b57cec5SDimitry Andric }
460b57cec5SDimitry Andric 
hasInstrItineraries() const470b57cec5SDimitry Andric bool TargetSchedModel::hasInstrItineraries() const {
480b57cec5SDimitry Andric   return EnableSchedItins && !InstrItins.isEmpty();
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
init(const TargetSubtargetInfo * TSInfo)510b57cec5SDimitry Andric void TargetSchedModel::init(const TargetSubtargetInfo *TSInfo) {
520b57cec5SDimitry Andric   STI = TSInfo;
530b57cec5SDimitry Andric   SchedModel = TSInfo->getSchedModel();
540b57cec5SDimitry Andric   TII = TSInfo->getInstrInfo();
550b57cec5SDimitry Andric   STI->initInstrItins(InstrItins);
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   unsigned NumRes = SchedModel.getNumProcResourceKinds();
580b57cec5SDimitry Andric   ResourceFactors.resize(NumRes);
590b57cec5SDimitry Andric   ResourceLCM = SchedModel.IssueWidth;
600b57cec5SDimitry Andric   for (unsigned Idx = 0; Idx < NumRes; ++Idx) {
610b57cec5SDimitry Andric     unsigned NumUnits = SchedModel.getProcResource(Idx)->NumUnits;
620b57cec5SDimitry Andric     if (NumUnits > 0)
63bdd1243dSDimitry Andric       ResourceLCM = std::lcm(ResourceLCM, NumUnits);
640b57cec5SDimitry Andric   }
650b57cec5SDimitry Andric   MicroOpFactor = ResourceLCM / SchedModel.IssueWidth;
660b57cec5SDimitry Andric   for (unsigned Idx = 0; Idx < NumRes; ++Idx) {
670b57cec5SDimitry Andric     unsigned NumUnits = SchedModel.getProcResource(Idx)->NumUnits;
680b57cec5SDimitry Andric     ResourceFactors[Idx] = NumUnits ? (ResourceLCM / NumUnits) : 0;
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric /// Returns true only if instruction is specified as single issue.
mustBeginGroup(const MachineInstr * MI,const MCSchedClassDesc * SC) const730b57cec5SDimitry Andric bool TargetSchedModel::mustBeginGroup(const MachineInstr *MI,
740b57cec5SDimitry Andric                                      const MCSchedClassDesc *SC) const {
750b57cec5SDimitry Andric   if (hasInstrSchedModel()) {
760b57cec5SDimitry Andric     if (!SC)
770b57cec5SDimitry Andric       SC = resolveSchedClass(MI);
780b57cec5SDimitry Andric     if (SC->isValid())
790b57cec5SDimitry Andric       return SC->BeginGroup;
800b57cec5SDimitry Andric   }
810b57cec5SDimitry Andric   return false;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
mustEndGroup(const MachineInstr * MI,const MCSchedClassDesc * SC) const840b57cec5SDimitry Andric bool TargetSchedModel::mustEndGroup(const MachineInstr *MI,
850b57cec5SDimitry Andric                                      const MCSchedClassDesc *SC) const {
860b57cec5SDimitry Andric   if (hasInstrSchedModel()) {
870b57cec5SDimitry Andric     if (!SC)
880b57cec5SDimitry Andric       SC = resolveSchedClass(MI);
890b57cec5SDimitry Andric     if (SC->isValid())
900b57cec5SDimitry Andric       return SC->EndGroup;
910b57cec5SDimitry Andric   }
920b57cec5SDimitry Andric   return false;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
getNumMicroOps(const MachineInstr * MI,const MCSchedClassDesc * SC) const950b57cec5SDimitry Andric unsigned TargetSchedModel::getNumMicroOps(const MachineInstr *MI,
960b57cec5SDimitry Andric                                           const MCSchedClassDesc *SC) const {
970b57cec5SDimitry Andric   if (hasInstrItineraries()) {
980b57cec5SDimitry Andric     int UOps = InstrItins.getNumMicroOps(MI->getDesc().getSchedClass());
990b57cec5SDimitry Andric     return (UOps >= 0) ? UOps : TII->getNumMicroOps(&InstrItins, *MI);
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric   if (hasInstrSchedModel()) {
1020b57cec5SDimitry Andric     if (!SC)
1030b57cec5SDimitry Andric       SC = resolveSchedClass(MI);
1040b57cec5SDimitry Andric     if (SC->isValid())
1050b57cec5SDimitry Andric       return SC->NumMicroOps;
1060b57cec5SDimitry Andric   }
1070b57cec5SDimitry Andric   return MI->isTransient() ? 0 : 1;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric // The machine model may explicitly specify an invalid latency, which
1110b57cec5SDimitry Andric // effectively means infinite latency. Since users of the TargetSchedule API
1120b57cec5SDimitry Andric // don't know how to handle this, we convert it to a very large latency that is
1130b57cec5SDimitry Andric // easy to distinguish when debugging the DAG but won't induce overflow.
capLatency(int Cycles)1140b57cec5SDimitry Andric static unsigned capLatency(int Cycles) {
1150b57cec5SDimitry Andric   return Cycles >= 0 ? Cycles : 1000;
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric /// Return the MCSchedClassDesc for this instruction. Some SchedClasses require
1190b57cec5SDimitry Andric /// evaluation of predicates that depend on instruction operands or flags.
1200b57cec5SDimitry Andric const MCSchedClassDesc *TargetSchedModel::
resolveSchedClass(const MachineInstr * MI) const1210b57cec5SDimitry Andric resolveSchedClass(const MachineInstr *MI) const {
1220b57cec5SDimitry Andric   // Get the definition's scheduling class descriptor from this machine model.
1230b57cec5SDimitry Andric   unsigned SchedClass = MI->getDesc().getSchedClass();
1240b57cec5SDimitry Andric   const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SchedClass);
1250b57cec5SDimitry Andric   if (!SCDesc->isValid())
1260b57cec5SDimitry Andric     return SCDesc;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric #ifndef NDEBUG
1290b57cec5SDimitry Andric   unsigned NIter = 0;
1300b57cec5SDimitry Andric #endif
1310b57cec5SDimitry Andric   while (SCDesc->isVariant()) {
1320b57cec5SDimitry Andric     assert(++NIter < 6 && "Variants are nested deeper than the magic number");
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric     SchedClass = STI->resolveSchedClass(SchedClass, MI, this);
1350b57cec5SDimitry Andric     SCDesc = SchedModel.getSchedClassDesc(SchedClass);
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric   return SCDesc;
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric /// Find the def index of this operand. This index maps to the machine model and
1410b57cec5SDimitry Andric /// is independent of use operands. Def operands may be reordered with uses or
1420b57cec5SDimitry Andric /// merged with uses without affecting the def index (e.g. before/after
1430b57cec5SDimitry Andric /// regalloc). However, an instruction's def operands must never be reordered
1440b57cec5SDimitry Andric /// with respect to each other.
findDefIdx(const MachineInstr * MI,unsigned DefOperIdx)1450b57cec5SDimitry Andric static unsigned findDefIdx(const MachineInstr *MI, unsigned DefOperIdx) {
1460b57cec5SDimitry Andric   unsigned DefIdx = 0;
1470b57cec5SDimitry Andric   for (unsigned i = 0; i != DefOperIdx; ++i) {
1480b57cec5SDimitry Andric     const MachineOperand &MO = MI->getOperand(i);
1490b57cec5SDimitry Andric     if (MO.isReg() && MO.isDef())
1500b57cec5SDimitry Andric       ++DefIdx;
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric   return DefIdx;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric /// Find the use index of this operand. This is independent of the instruction's
1560b57cec5SDimitry Andric /// def operands.
1570b57cec5SDimitry Andric ///
1580b57cec5SDimitry Andric /// Note that uses are not determined by the operand's isUse property, which
1590b57cec5SDimitry Andric /// is simply the inverse of isDef. Here we consider any readsReg operand to be
1600b57cec5SDimitry Andric /// a "use". The machine model allows an operand to be both a Def and Use.
findUseIdx(const MachineInstr * MI,unsigned UseOperIdx)1610b57cec5SDimitry Andric static unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) {
1620b57cec5SDimitry Andric   unsigned UseIdx = 0;
1630b57cec5SDimitry Andric   for (unsigned i = 0; i != UseOperIdx; ++i) {
1640b57cec5SDimitry Andric     const MachineOperand &MO = MI->getOperand(i);
1650b57cec5SDimitry Andric     if (MO.isReg() && MO.readsReg() && !MO.isDef())
1660b57cec5SDimitry Andric       ++UseIdx;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric   return UseIdx;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
171*5f757f3fSDimitry Andric // Top-level API for clients that know the operand indices. This doesn't need to
172*5f757f3fSDimitry Andric // return std::optional<unsigned>, as it always returns a valid latency.
computeOperandLatency(const MachineInstr * DefMI,unsigned DefOperIdx,const MachineInstr * UseMI,unsigned UseOperIdx) const1730b57cec5SDimitry Andric unsigned TargetSchedModel::computeOperandLatency(
1740b57cec5SDimitry Andric   const MachineInstr *DefMI, unsigned DefOperIdx,
1750b57cec5SDimitry Andric   const MachineInstr *UseMI, unsigned UseOperIdx) const {
1760b57cec5SDimitry Andric 
177*5f757f3fSDimitry Andric   const unsigned InstrLatency = computeInstrLatency(DefMI);
178*5f757f3fSDimitry Andric   const unsigned DefaultDefLatency = TII->defaultDefLatency(SchedModel, *DefMI);
179*5f757f3fSDimitry Andric 
1800b57cec5SDimitry Andric   if (!hasInstrSchedModel() && !hasInstrItineraries())
181*5f757f3fSDimitry Andric     return DefaultDefLatency;
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   if (hasInstrItineraries()) {
184*5f757f3fSDimitry Andric     std::optional<unsigned> OperLatency;
1850b57cec5SDimitry Andric     if (UseMI) {
1860b57cec5SDimitry Andric       OperLatency = TII->getOperandLatency(&InstrItins, *DefMI, DefOperIdx,
1870b57cec5SDimitry Andric                                            *UseMI, UseOperIdx);
1880b57cec5SDimitry Andric     }
1890b57cec5SDimitry Andric     else {
1900b57cec5SDimitry Andric       unsigned DefClass = DefMI->getDesc().getSchedClass();
1910b57cec5SDimitry Andric       OperLatency = InstrItins.getOperandCycle(DefClass, DefOperIdx);
1920b57cec5SDimitry Andric     }
1930b57cec5SDimitry Andric 
194*5f757f3fSDimitry Andric     // Expected latency is the max of InstrLatency and DefaultDefLatency, if we
195*5f757f3fSDimitry Andric     // didn't find an operand latency.
196*5f757f3fSDimitry Andric     return OperLatency ? *OperLatency
197*5f757f3fSDimitry Andric                        : std::max(InstrLatency, DefaultDefLatency);
1980b57cec5SDimitry Andric   }
199*5f757f3fSDimitry Andric 
2000b57cec5SDimitry Andric   // hasInstrSchedModel()
2010b57cec5SDimitry Andric   const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
2020b57cec5SDimitry Andric   unsigned DefIdx = findDefIdx(DefMI, DefOperIdx);
2030b57cec5SDimitry Andric   if (DefIdx < SCDesc->NumWriteLatencyEntries) {
2040b57cec5SDimitry Andric     // Lookup the definition's write latency in SubtargetInfo.
2050b57cec5SDimitry Andric     const MCWriteLatencyEntry *WLEntry =
2060b57cec5SDimitry Andric       STI->getWriteLatencyEntry(SCDesc, DefIdx);
2070b57cec5SDimitry Andric     unsigned WriteID = WLEntry->WriteResourceID;
2080b57cec5SDimitry Andric     unsigned Latency = capLatency(WLEntry->Cycles);
2090b57cec5SDimitry Andric     if (!UseMI)
2100b57cec5SDimitry Andric       return Latency;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric     // Lookup the use's latency adjustment in SubtargetInfo.
2130b57cec5SDimitry Andric     const MCSchedClassDesc *UseDesc = resolveSchedClass(UseMI);
2140b57cec5SDimitry Andric     if (UseDesc->NumReadAdvanceEntries == 0)
2150b57cec5SDimitry Andric       return Latency;
2160b57cec5SDimitry Andric     unsigned UseIdx = findUseIdx(UseMI, UseOperIdx);
2170b57cec5SDimitry Andric     int Advance = STI->getReadAdvanceCycles(UseDesc, UseIdx, WriteID);
2180b57cec5SDimitry Andric     if (Advance > 0 && (unsigned)Advance > Latency) // unsigned wrap
2190b57cec5SDimitry Andric       return 0;
2200b57cec5SDimitry Andric     return Latency - Advance;
2210b57cec5SDimitry Andric   }
2220b57cec5SDimitry Andric   // If DefIdx does not exist in the model (e.g. implicit defs), then return
2230b57cec5SDimitry Andric   // unit latency (defaultDefLatency may be too conservative).
2240b57cec5SDimitry Andric #ifndef NDEBUG
225bdd1243dSDimitry Andric   if (SCDesc->isValid() && !DefMI->getOperand(DefOperIdx).isImplicit() &&
226bdd1243dSDimitry Andric       !DefMI->getDesc().operands()[DefOperIdx].isOptionalDef() &&
227bdd1243dSDimitry Andric       SchedModel.isComplete()) {
2280b57cec5SDimitry Andric     errs() << "DefIdx " << DefIdx << " exceeds machine model writes for "
2290b57cec5SDimitry Andric            << *DefMI << " (Try with MCSchedModel.CompleteModel set to false)";
2300b57cec5SDimitry Andric     llvm_unreachable("incomplete machine model");
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric #endif
2330b57cec5SDimitry Andric   // FIXME: Automatically giving all implicit defs defaultDefLatency is
2340b57cec5SDimitry Andric   // undesirable. We should only do it for defs that are known to the MC
2350b57cec5SDimitry Andric   // desc like flags. Truly implicit defs should get 1 cycle latency.
236*5f757f3fSDimitry Andric   return DefMI->isTransient() ? 0 : DefaultDefLatency;
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric unsigned
computeInstrLatency(const MCSchedClassDesc & SCDesc) const2400b57cec5SDimitry Andric TargetSchedModel::computeInstrLatency(const MCSchedClassDesc &SCDesc) const {
2410b57cec5SDimitry Andric   return capLatency(MCSchedModel::computeInstrLatency(*STI, SCDesc));
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
computeInstrLatency(unsigned Opcode) const2440b57cec5SDimitry Andric unsigned TargetSchedModel::computeInstrLatency(unsigned Opcode) const {
2450b57cec5SDimitry Andric   assert(hasInstrSchedModel() && "Only call this function with a SchedModel");
2460b57cec5SDimitry Andric   unsigned SCIdx = TII->get(Opcode).getSchedClass();
2470b57cec5SDimitry Andric   return capLatency(SchedModel.computeInstrLatency(*STI, SCIdx));
2480b57cec5SDimitry Andric }
2490b57cec5SDimitry Andric 
computeInstrLatency(const MCInst & Inst) const2500b57cec5SDimitry Andric unsigned TargetSchedModel::computeInstrLatency(const MCInst &Inst) const {
2510b57cec5SDimitry Andric   if (hasInstrSchedModel())
2520b57cec5SDimitry Andric     return capLatency(SchedModel.computeInstrLatency(*STI, *TII, Inst));
2530b57cec5SDimitry Andric   return computeInstrLatency(Inst.getOpcode());
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric unsigned
computeInstrLatency(const MachineInstr * MI,bool UseDefaultDefLatency) const2570b57cec5SDimitry Andric TargetSchedModel::computeInstrLatency(const MachineInstr *MI,
2580b57cec5SDimitry Andric                                       bool UseDefaultDefLatency) const {
2590b57cec5SDimitry Andric   // For the itinerary model, fall back to the old subtarget hook.
2600b57cec5SDimitry Andric   // Allow subtargets to compute Bundle latencies outside the machine model.
2610b57cec5SDimitry Andric   if (hasInstrItineraries() || MI->isBundle() ||
2620b57cec5SDimitry Andric       (!hasInstrSchedModel() && !UseDefaultDefLatency))
2630b57cec5SDimitry Andric     return TII->getInstrLatency(&InstrItins, *MI);
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   if (hasInstrSchedModel()) {
2660b57cec5SDimitry Andric     const MCSchedClassDesc *SCDesc = resolveSchedClass(MI);
2670b57cec5SDimitry Andric     if (SCDesc->isValid())
2680b57cec5SDimitry Andric       return computeInstrLatency(*SCDesc);
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric   return TII->defaultDefLatency(SchedModel, *MI);
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric unsigned TargetSchedModel::
computeOutputLatency(const MachineInstr * DefMI,unsigned DefOperIdx,const MachineInstr * DepMI) const2740b57cec5SDimitry Andric computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
2750b57cec5SDimitry Andric                      const MachineInstr *DepMI) const {
2760b57cec5SDimitry Andric   if (!SchedModel.isOutOfOrder())
2770b57cec5SDimitry Andric     return 1;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   // Out-of-order processor can dispatch WAW dependencies in the same cycle.
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   // Treat predication as a data dependency for out-of-order cpus. In-order
2820b57cec5SDimitry Andric   // cpus do not need to treat predicated writes specially.
2830b57cec5SDimitry Andric   //
2840b57cec5SDimitry Andric   // TODO: The following hack exists because predication passes do not
2850b57cec5SDimitry Andric   // correctly append imp-use operands, and readsReg() strangely returns false
2860b57cec5SDimitry Andric   // for predicated defs.
2878bcb0991SDimitry Andric   Register Reg = DefMI->getOperand(DefOperIdx).getReg();
2880b57cec5SDimitry Andric   const MachineFunction &MF = *DefMI->getMF();
2890b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2900b57cec5SDimitry Andric   if (!DepMI->readsRegister(Reg, TRI) && TII->isPredicated(*DepMI))
2910b57cec5SDimitry Andric     return computeInstrLatency(DefMI);
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   // If we have a per operand scheduling model, check if this def is writing
2940b57cec5SDimitry Andric   // an unbuffered resource. If so, it treated like an in-order cpu.
2950b57cec5SDimitry Andric   if (hasInstrSchedModel()) {
2960b57cec5SDimitry Andric     const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
2970b57cec5SDimitry Andric     if (SCDesc->isValid()) {
2980b57cec5SDimitry Andric       for (const MCWriteProcResEntry *PRI = STI->getWriteProcResBegin(SCDesc),
2990b57cec5SDimitry Andric              *PRE = STI->getWriteProcResEnd(SCDesc); PRI != PRE; ++PRI) {
3000b57cec5SDimitry Andric         if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->BufferSize)
3010b57cec5SDimitry Andric           return 1;
3020b57cec5SDimitry Andric       }
3030b57cec5SDimitry Andric     }
3040b57cec5SDimitry Andric   }
3050b57cec5SDimitry Andric   return 0;
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric double
computeReciprocalThroughput(const MachineInstr * MI) const3090b57cec5SDimitry Andric TargetSchedModel::computeReciprocalThroughput(const MachineInstr *MI) const {
3100b57cec5SDimitry Andric   if (hasInstrItineraries()) {
3110b57cec5SDimitry Andric     unsigned SchedClass = MI->getDesc().getSchedClass();
3120b57cec5SDimitry Andric     return MCSchedModel::getReciprocalThroughput(SchedClass,
3130b57cec5SDimitry Andric                                                  *getInstrItineraries());
3140b57cec5SDimitry Andric   }
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric   if (hasInstrSchedModel())
3170b57cec5SDimitry Andric     return MCSchedModel::getReciprocalThroughput(*STI, *resolveSchedClass(MI));
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   return 0.0;
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric double
computeReciprocalThroughput(unsigned Opcode) const3230b57cec5SDimitry Andric TargetSchedModel::computeReciprocalThroughput(unsigned Opcode) const {
3240b57cec5SDimitry Andric   unsigned SchedClass = TII->get(Opcode).getSchedClass();
3250b57cec5SDimitry Andric   if (hasInstrItineraries())
3260b57cec5SDimitry Andric     return MCSchedModel::getReciprocalThroughput(SchedClass,
3270b57cec5SDimitry Andric                                                  *getInstrItineraries());
3280b57cec5SDimitry Andric   if (hasInstrSchedModel()) {
3290b57cec5SDimitry Andric     const MCSchedClassDesc &SCDesc = *SchedModel.getSchedClassDesc(SchedClass);
3300b57cec5SDimitry Andric     if (SCDesc.isValid() && !SCDesc.isVariant())
3310b57cec5SDimitry Andric       return MCSchedModel::getReciprocalThroughput(*STI, SCDesc);
3320b57cec5SDimitry Andric   }
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric   return 0.0;
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric double
computeReciprocalThroughput(const MCInst & MI) const3380b57cec5SDimitry Andric TargetSchedModel::computeReciprocalThroughput(const MCInst &MI) const {
3390b57cec5SDimitry Andric   if (hasInstrSchedModel())
3400b57cec5SDimitry Andric     return SchedModel.getReciprocalThroughput(*STI, *TII, MI);
3410b57cec5SDimitry Andric   return computeReciprocalThroughput(MI.getOpcode());
3420b57cec5SDimitry Andric }
3430b57cec5SDimitry Andric 
enableIntervals() const344*5f757f3fSDimitry Andric bool TargetSchedModel::enableIntervals() const {
345*5f757f3fSDimitry Andric   if (ForceEnableIntervals)
346*5f757f3fSDimitry Andric     return true;
347*5f757f3fSDimitry Andric 
348*5f757f3fSDimitry Andric   return SchedModel.EnableIntervals;
349*5f757f3fSDimitry Andric }
350