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