199ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//===-- llvm/Target/TargetSchedule.cpp - Sched Machine Model ----*- C++ -*-===//
299ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//
399ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//                     The LLVM Compiler Infrastructure
499ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//
599ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick// This file is distributed under the University of Illinois Open Source
699ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick// License. See LICENSE.TXT for details.
799ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//
899ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//===----------------------------------------------------------------------===//
999ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//
1099ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick// This file implements a wrapper around MCSchedModel that allows the interface
1199ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick// to benefit from information currently only available in TargetInstrInfo.
1299ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//
1399ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick//===----------------------------------------------------------------------===//
1499ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick
1599ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick#include "llvm/CodeGen/TargetSchedule.h"
16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/CommandLine.h"
17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/raw_ostream.h"
1899ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick#include "llvm/Target/TargetInstrInfo.h"
1934301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick#include "llvm/Target/TargetRegisterInfo.h"
2099ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick#include "llvm/Target/TargetSubtargetInfo.h"
2199ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick
2299ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trickusing namespace llvm;
2399ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick
2472fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trickstatic cl::opt<bool> EnableSchedModel("schedmodel", cl::Hidden, cl::init(true),
2599ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick  cl::desc("Use TargetSchedModel for latency lookup"));
2699ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick
2734301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trickstatic cl::opt<bool> EnableSchedItins("scheditins", cl::Hidden, cl::init(true),
2834301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  cl::desc("Use InstrItineraryData for latency lookup"));
2934301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
3042bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trickbool TargetSchedModel::hasInstrSchedModel() const {
3142bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trick  return EnableSchedModel && SchedModel.hasInstrSchedModel();
3242bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trick}
3342bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trick
3442bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trickbool TargetSchedModel::hasInstrItineraries() const {
3542bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trick  return EnableSchedItins && !InstrItins.isEmpty();
3642bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trick}
3742bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trick
388d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trickstatic unsigned gcd(unsigned Dividend, unsigned Divisor) {
398d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  // Dividend and Divisor will be naturally swapped as needed.
408d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  while(Divisor) {
418d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    unsigned Rem = Dividend % Divisor;
428d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    Dividend = Divisor;
438d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    Divisor = Rem;
448d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  };
458d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  return Dividend;
468d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick}
478d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trickstatic unsigned lcm(unsigned A, unsigned B) {
488d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  unsigned LCM = (uint64_t(A) * B) / gcd(A, B);
498d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  assert((LCM >= A && LCM >= B) && "LCM overflow");
508d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  return LCM;
518d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick}
528d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick
5399ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trickvoid TargetSchedModel::init(const MCSchedModel &sm,
5499ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick                            const TargetSubtargetInfo *sti,
5599ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick                            const TargetInstrInfo *tii) {
5699ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick  SchedModel = sm;
5799ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick  STI = sti;
5899ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick  TII = tii;
5999ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick  STI->initInstrItins(InstrItins);
608d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick
618d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  unsigned NumRes = SchedModel.getNumProcResourceKinds();
628d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  ResourceFactors.resize(NumRes);
638d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  ResourceLCM = SchedModel.IssueWidth;
648d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  for (unsigned Idx = 0; Idx < NumRes; ++Idx) {
658d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    unsigned NumUnits = SchedModel.getProcResource(Idx)->NumUnits;
668d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    if (NumUnits > 0)
678d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick      ResourceLCM = lcm(ResourceLCM, NumUnits);
688d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  }
698d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  MicroOpFactor = ResourceLCM / SchedModel.IssueWidth;
708d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  for (unsigned Idx = 0; Idx < NumRes; ++Idx) {
718d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    unsigned NumUnits = SchedModel.getProcResource(Idx)->NumUnits;
728d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    ResourceFactors[Idx] = NumUnits ? (ResourceLCM / NumUnits) : 0;
738d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick  }
7499ab6c6035aec3c0e9b0cc5b76a4666fc5fd7b7bAndrew Trick}
7534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
768d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trickunsigned TargetSchedModel::getNumMicroOps(const MachineInstr *MI,
778d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick                                          const MCSchedClassDesc *SC) const {
78412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  if (hasInstrItineraries()) {
79412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick    int UOps = InstrItins.getNumMicroOps(MI->getDesc().getSchedClass());
80412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick    return (UOps >= 0) ? UOps : TII->getNumMicroOps(&InstrItins, MI);
81412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  }
824903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick  if (hasInstrSchedModel()) {
838d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    if (!SC)
848d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick      SC = resolveSchedClass(MI);
858d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick    if (SC->isValid())
868d4abb2446f80986ad5136bbec30c5da18cd6f4bAndrew Trick      return SC->NumMicroOps;
874903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick  }
884903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick  return MI->isTransient() ? 0 : 1;
89412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick}
90412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick
91fdd6fa89b960088b368231ec08e56a0c0b1e6930Andrew Trick// The machine model may explicitly specify an invalid latency, which
92fdd6fa89b960088b368231ec08e56a0c0b1e6930Andrew Trick// effectively means infinite latency. Since users of the TargetSchedule API
93fdd6fa89b960088b368231ec08e56a0c0b1e6930Andrew Trick// don't know how to handle this, we convert it to a very large latency that is
94fdd6fa89b960088b368231ec08e56a0c0b1e6930Andrew Trick// easy to distinguish when debugging the DAG but won't induce overflow.
95b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trickstatic unsigned capLatency(int Cycles) {
96fdd6fa89b960088b368231ec08e56a0c0b1e6930Andrew Trick  return Cycles >= 0 ? Cycles : 1000;
97fdd6fa89b960088b368231ec08e56a0c0b1e6930Andrew Trick}
98fdd6fa89b960088b368231ec08e56a0c0b1e6930Andrew Trick
9934301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// Return the MCSchedClassDesc for this instruction. Some SchedClasses require
10034301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// evaluation of predicates that depend on instruction operands or flags.
10134301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trickconst MCSchedClassDesc *TargetSchedModel::
10234301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew TrickresolveSchedClass(const MachineInstr *MI) const {
10334301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
10434301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  // Get the definition's scheduling class descriptor from this machine model.
10534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  unsigned SchedClass = MI->getDesc().getSchedClass();
10634301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SchedClass);
1076a22dba4854a8b3d7427f8493f663c1b52df4477Andrew Trick  if (!SCDesc->isValid())
1086a22dba4854a8b3d7427f8493f663c1b52df4477Andrew Trick    return SCDesc;
10934301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
11034301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick#ifndef NDEBUG
11134301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  unsigned NIter = 0;
11234301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick#endif
11334301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  while (SCDesc->isVariant()) {
11434301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick    assert(++NIter < 6 && "Variants are nested deeper than the magic number");
11534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
11634301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick    SchedClass = STI->resolveSchedClass(SchedClass, MI, this);
11734301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick    SCDesc = SchedModel.getSchedClassDesc(SchedClass);
11834301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  }
11934301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  return SCDesc;
12034301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick}
12134301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
12234301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// Find the def index of this operand. This index maps to the machine model and
12334301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// is independent of use operands. Def operands may be reordered with uses or
12434301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// merged with uses without affecting the def index (e.g. before/after
12534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// regalloc). However, an instruction's def operands must never be reordered
12634301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// with respect to each other.
12734301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trickstatic unsigned findDefIdx(const MachineInstr *MI, unsigned DefOperIdx) {
12834301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  unsigned DefIdx = 0;
12934301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  for (unsigned i = 0; i != DefOperIdx; ++i) {
13034301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick    const MachineOperand &MO = MI->getOperand(i);
13134301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick    if (MO.isReg() && MO.isDef())
13234301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick      ++DefIdx;
13334301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  }
13434301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  return DefIdx;
13534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick}
13634301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
13734301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// Find the use index of this operand. This is independent of the instruction's
13834301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick/// def operands.
1393918cade8f7c0a9ff4e3c5799a55846d8f6e3fd4Andrew Trick///
1403918cade8f7c0a9ff4e3c5799a55846d8f6e3fd4Andrew Trick/// Note that uses are not determined by the operand's isUse property, which
1413918cade8f7c0a9ff4e3c5799a55846d8f6e3fd4Andrew Trick/// is simply the inverse of isDef. Here we consider any readsReg operand to be
1423918cade8f7c0a9ff4e3c5799a55846d8f6e3fd4Andrew Trick/// a "use". The machine model allows an operand to be both a Def and Use.
14334301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trickstatic unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) {
14434301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  unsigned UseIdx = 0;
14534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  for (unsigned i = 0; i != UseOperIdx; ++i) {
14634301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick    const MachineOperand &MO = MI->getOperand(i);
1473918cade8f7c0a9ff4e3c5799a55846d8f6e3fd4Andrew Trick    if (MO.isReg() && MO.readsReg())
14834301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick      ++UseIdx;
14934301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  }
15034301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  return UseIdx;
15134301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick}
15234301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
15334301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick// Top-level API for clients that know the operand indices.
15434301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trickunsigned TargetSchedModel::computeOperandLatency(
15534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  const MachineInstr *DefMI, unsigned DefOperIdx,
156b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick  const MachineInstr *UseMI, unsigned UseOperIdx) const {
15734301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
158b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick  if (!hasInstrSchedModel() && !hasInstrItineraries())
15937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return TII->defaultDefLatency(SchedModel, DefMI);
16034301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
16142bb106118db51393c2524c8b0c7f7ba6674cfd7Andrew Trick  if (hasInstrItineraries()) {
16272fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    int OperLatency = 0;
16372fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    if (UseMI) {
164b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick      OperLatency = TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx,
165b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick                                           UseMI, UseOperIdx);
16634301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick    }
16772fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    else {
16872fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick      unsigned DefClass = DefMI->getDesc().getSchedClass();
16972fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick      OperLatency = InstrItins.getOperandCycle(DefClass, DefOperIdx);
1703918cade8f7c0a9ff4e3c5799a55846d8f6e3fd4Andrew Trick    }
17172fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    if (OperLatency >= 0)
17272fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick      return OperLatency;
17334301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick
17472fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    // No operand latency was found.
17572fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    unsigned InstrLatency = TII->getInstrLatency(&InstrItins, DefMI);
17672fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick
17772fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    // Expected latency is the max of the stage latency and itinerary props.
178c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick    // Rather than directly querying InstrItins stage latency, we call a TII
179c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick    // hook to allow subtargets to specialize latency. This hook is only
180c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick    // applicable to the InstrItins model. InstrSchedModel should model all
181c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick    // special cases without TII hooks.
182b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick    InstrLatency = std::max(InstrLatency,
18337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                            TII->defaultDefLatency(SchedModel, DefMI));
18472fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    return InstrLatency;
18534301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  }
186b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick  // hasInstrSchedModel()
18772fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick  const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
18872fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick  unsigned DefIdx = findDefIdx(DefMI, DefOperIdx);
18972fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick  if (DefIdx < SCDesc->NumWriteLatencyEntries) {
19072fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    // Lookup the definition's write latency in SubtargetInfo.
19172fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    const MCWriteLatencyEntry *WLEntry =
19272fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick      STI->getWriteLatencyEntry(SCDesc, DefIdx);
19372fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    unsigned WriteID = WLEntry->WriteResourceID;
194b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick    unsigned Latency = capLatency(WLEntry->Cycles);
19572fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    if (!UseMI)
19672fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick      return Latency;
19772fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick
19872fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    // Lookup the use's latency adjustment in SubtargetInfo.
19972fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    const MCSchedClassDesc *UseDesc = resolveSchedClass(UseMI);
20072fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    if (UseDesc->NumReadAdvanceEntries == 0)
20172fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick      return Latency;
20272fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    unsigned UseIdx = findUseIdx(UseMI, UseOperIdx);
20371b9d94d6ba2933df0f7936c44cdb344336d46efAndrew Trick    int Advance = STI->getReadAdvanceCycles(UseDesc, UseIdx, WriteID);
20471b9d94d6ba2933df0f7936c44cdb344336d46efAndrew Trick    if (Advance > 0 && (unsigned)Advance > Latency) // unsigned wrap
20571b9d94d6ba2933df0f7936c44cdb344336d46efAndrew Trick      return 0;
20671b9d94d6ba2933df0f7936c44cdb344336d46efAndrew Trick    return Latency - Advance;
20734301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick  }
20872fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick  // If DefIdx does not exist in the model (e.g. implicit defs), then return
20972fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick  // unit latency (defaultDefLatency may be too conservative).
21072fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick#ifndef NDEBUG
21172fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick  if (SCDesc->isValid() && !DefMI->getOperand(DefOperIdx).isImplicit()
212070156437752179833b1e5fddd50caa03fd7c12fAndrew Trick      && !DefMI->getDesc().OpInfo[DefOperIdx].isOptionalDef()
213070156437752179833b1e5fddd50caa03fd7c12fAndrew Trick      && SchedModel.isComplete()) {
21472fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    std::string Err;
21572fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    raw_string_ostream ss(Err);
21672fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    ss << "DefIdx " << DefIdx << " exceeds machine model writes for "
21772fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick       << *DefMI;
21872fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick    report_fatal_error(ss.str());
21972fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick  }
22072fd0a9448a9d9eced8f475741e4a1ee543253e0Andrew Trick#endif
22151f6747b23bf7c85e90f816bf9bfae3a1d4fd058Andrew Trick  // FIXME: Automatically giving all implicit defs defaultDefLatency is
22251f6747b23bf7c85e90f816bf9bfae3a1d4fd058Andrew Trick  // undesirable. We should only do it for defs that are known to the MC
22351f6747b23bf7c85e90f816bf9bfae3a1d4fd058Andrew Trick  // desc like flags. Truly implicit defs should get 1 cycle latency.
22437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return DefMI->isTransient() ? 0 : TII->defaultDefLatency(SchedModel, DefMI);
22537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines}
22637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
22737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hinesunsigned TargetSchedModel::computeInstrLatency(unsigned Opcode) const {
22837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  assert(hasInstrSchedModel() && "Only call this function with a SchedModel");
22937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
23037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  unsigned SCIdx = TII->get(Opcode).getSchedClass();
23137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SCIdx);
23237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  unsigned Latency = 0;
23337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
23437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  if (SCDesc->isValid() && !SCDesc->isVariant()) {
23537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
23637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines         DefIdx != DefEnd; ++DefIdx) {
23737ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      // Lookup the definition's write latency in SubtargetInfo.
23837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      const MCWriteLatencyEntry *WLEntry =
23937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines          STI->getWriteLatencyEntry(SCDesc, DefIdx);
24037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines      Latency = std::max(Latency, capLatency(WLEntry->Cycles));
24137ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    }
24237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    return Latency;
24337ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  }
24437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines
24537ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  assert(Latency && "No MI sched latency");
24637ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return 0;
24734301ceca8913f3126339f332d3dc6f2d7ac0d78Andrew Trick}
248c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick
249d42730dc712026cbfb1322a979e0ac72cd31a19eArnold Schwaighoferunsigned
250d42730dc712026cbfb1322a979e0ac72cd31a19eArnold SchwaighoferTargetSchedModel::computeInstrLatency(const MachineInstr *MI,
251d42730dc712026cbfb1322a979e0ac72cd31a19eArnold Schwaighofer                                      bool UseDefaultDefLatency) const {
25282d46aec62f127856f4bfeb30f80aa12dd74bae0Andrew Trick  // For the itinerary model, fall back to the old subtarget hook.
25382d46aec62f127856f4bfeb30f80aa12dd74bae0Andrew Trick  // Allow subtargets to compute Bundle latencies outside the machine model.
254d42730dc712026cbfb1322a979e0ac72cd31a19eArnold Schwaighofer  if (hasInstrItineraries() || MI->isBundle() ||
255d42730dc712026cbfb1322a979e0ac72cd31a19eArnold Schwaighofer      (!hasInstrSchedModel() && !UseDefaultDefLatency))
256c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick    return TII->getInstrLatency(&InstrItins, MI);
25782d46aec62f127856f4bfeb30f80aa12dd74bae0Andrew Trick
258c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick  if (hasInstrSchedModel()) {
259c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick    const MCSchedClassDesc *SCDesc = resolveSchedClass(MI);
2604903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick    if (SCDesc->isValid()) {
2614903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick      unsigned Latency = 0;
2624903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick      for (unsigned DefIdx = 0, DefEnd = SCDesc->NumWriteLatencyEntries;
2634903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick           DefIdx != DefEnd; ++DefIdx) {
2644903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick        // Lookup the definition's write latency in SubtargetInfo.
2654903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick        const MCWriteLatencyEntry *WLEntry =
2664903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick          STI->getWriteLatencyEntry(SCDesc, DefIdx);
267b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick        Latency = std::max(Latency, capLatency(WLEntry->Cycles));
2684903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick      }
2694903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick      return Latency;
270c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick    }
271c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick  }
27237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  return TII->defaultDefLatency(SchedModel, MI);
273c0dfffa448ad7ab647779bc3e7f2aee5c76cb31bAndrew Trick}
274412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick
275412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trickunsigned TargetSchedModel::
276412cd2f81374865dfa708bef6d5b896ca10dece0Andrew TrickcomputeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
277412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick                     const MachineInstr *DepMI) const {
278b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick  if (SchedModel.MicroOpBufferSize <= 1)
279412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick    return 1;
280412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick
281b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick  // MicroOpBufferSize > 1 indicates an out-of-order processor that can dispatch
282412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // WAW dependencies in the same cycle.
283412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick
284412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // Treat predication as a data dependency for out-of-order cpus. In-order
285412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // cpus do not need to treat predicated writes specially.
286412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  //
287412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // TODO: The following hack exists because predication passes do not
288412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // correctly append imp-use operands, and readsReg() strangely returns false
289412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // for predicated defs.
290412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  unsigned Reg = DefMI->getOperand(DefOperIdx).getReg();
291412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  const MachineFunction &MF = *DefMI->getParent()->getParent();
29237ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines  const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
293412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  if (!DepMI->readsRegister(Reg, TRI) && TII->isPredicated(DepMI))
294412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick    return computeInstrLatency(DefMI);
295412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick
296412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // If we have a per operand scheduling model, check if this def is writing
297412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  // an unbuffered resource. If so, it treated like an in-order cpu.
298412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  if (hasInstrSchedModel()) {
299412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick    const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI);
3004903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick    if (SCDesc->isValid()) {
3014903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick      for (const MCWriteProcResEntry *PRI = STI->getWriteProcResBegin(SCDesc),
3024903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick             *PRE = STI->getWriteProcResEnd(SCDesc); PRI != PRE; ++PRI) {
303b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick        if (!SchedModel.getProcResource(PRI->ProcResourceIdx)->BufferSize)
3044903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick          return 1;
3054903c15b7d92802a4f0f28928a89bb4c0d5e212fAndrew Trick      }
306412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick    }
307412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  }
308412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick  return 0;
309412cd2f81374865dfa708bef6d5b896ca10dece0Andrew Trick}
310