TargetSchedule.cpp revision 42bb106118db51393c2524c8b0c7f7ba6674cfd7
1//===-- llvm/Target/TargetSchedule.cpp - Sched Machine Model ----*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file implements a wrapper around MCSchedModel that allows the interface 11// to benefit from information currently only available in TargetInstrInfo. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/CodeGen/TargetSchedule.h" 16#include "llvm/Target/TargetInstrInfo.h" 17#include "llvm/Target/TargetRegisterInfo.h" 18#include "llvm/Target/TargetSubtargetInfo.h" 19#include "llvm/Support/CommandLine.h" 20#include "llvm/Support/raw_ostream.h" 21 22using namespace llvm; 23 24static cl::opt<bool> EnableSchedModel("schedmodel", cl::Hidden, cl::init(true), 25 cl::desc("Use TargetSchedModel for latency lookup")); 26 27static cl::opt<bool> EnableSchedItins("scheditins", cl::Hidden, cl::init(true), 28 cl::desc("Use InstrItineraryData for latency lookup")); 29 30bool TargetSchedModel::hasInstrSchedModel() const { 31 return EnableSchedModel && SchedModel.hasInstrSchedModel(); 32} 33 34bool TargetSchedModel::hasInstrItineraries() const { 35 return EnableSchedItins && !InstrItins.isEmpty(); 36} 37 38void TargetSchedModel::init(const MCSchedModel &sm, 39 const TargetSubtargetInfo *sti, 40 const TargetInstrInfo *tii) { 41 SchedModel = sm; 42 STI = sti; 43 TII = tii; 44 STI->initInstrItins(InstrItins); 45} 46 47/// If we can determine the operand latency from the def only, without machine 48/// model or itinerary lookup, do so. Otherwise return -1. 49int TargetSchedModel::getDefLatency(const MachineInstr *DefMI, 50 bool FindMin) const { 51 52 // Return a latency based on the itinerary properties and defining instruction 53 // if possible. Some common subtargets don't require per-operand latency, 54 // especially for minimum latencies. 55 if (FindMin) { 56 // If MinLatency is invalid, then use the itinerary for MinLatency. If no 57 // itinerary exists either, then use single cycle latency. 58 if (SchedModel.MinLatency < 0 && !hasInstrItineraries()) { 59 return 1; 60 } 61 return SchedModel.MinLatency; 62 } 63 else if (!hasInstrSchedModel() && !hasInstrItineraries()) { 64 return TII->defaultDefLatency(&SchedModel, DefMI); 65 } 66 // ...operand lookup required 67 return -1; 68} 69 70/// Return the MCSchedClassDesc for this instruction. Some SchedClasses require 71/// evaluation of predicates that depend on instruction operands or flags. 72const MCSchedClassDesc *TargetSchedModel:: 73resolveSchedClass(const MachineInstr *MI) const { 74 75 // Get the definition's scheduling class descriptor from this machine model. 76 unsigned SchedClass = MI->getDesc().getSchedClass(); 77 const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SchedClass); 78 79#ifndef NDEBUG 80 unsigned NIter = 0; 81#endif 82 while (SCDesc->isVariant()) { 83 assert(++NIter < 6 && "Variants are nested deeper than the magic number"); 84 85 SchedClass = STI->resolveSchedClass(SchedClass, MI, this); 86 SCDesc = SchedModel.getSchedClassDesc(SchedClass); 87 } 88 return SCDesc; 89} 90 91/// Find the def index of this operand. This index maps to the machine model and 92/// is independent of use operands. Def operands may be reordered with uses or 93/// merged with uses without affecting the def index (e.g. before/after 94/// regalloc). However, an instruction's def operands must never be reordered 95/// with respect to each other. 96static unsigned findDefIdx(const MachineInstr *MI, unsigned DefOperIdx) { 97 unsigned DefIdx = 0; 98 for (unsigned i = 0; i != DefOperIdx; ++i) { 99 const MachineOperand &MO = MI->getOperand(i); 100 if (MO.isReg() && MO.isDef()) 101 ++DefIdx; 102 } 103 return DefIdx; 104} 105 106/// Find the use index of this operand. This is independent of the instruction's 107/// def operands. 108/// 109/// Note that uses are not determined by the operand's isUse property, which 110/// is simply the inverse of isDef. Here we consider any readsReg operand to be 111/// a "use". The machine model allows an operand to be both a Def and Use. 112static unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) { 113 unsigned UseIdx = 0; 114 for (unsigned i = 0; i != UseOperIdx; ++i) { 115 const MachineOperand &MO = MI->getOperand(i); 116 if (MO.isReg() && MO.readsReg()) 117 ++UseIdx; 118 } 119 return UseIdx; 120} 121 122// Top-level API for clients that know the operand indices. 123unsigned TargetSchedModel::computeOperandLatency( 124 const MachineInstr *DefMI, unsigned DefOperIdx, 125 const MachineInstr *UseMI, unsigned UseOperIdx, 126 bool FindMin) const { 127 128 int DefLatency = getDefLatency(DefMI, FindMin); 129 if (DefLatency >= 0) 130 return DefLatency; 131 132 if (hasInstrItineraries()) { 133 int OperLatency = 0; 134 if (UseMI) { 135 OperLatency = 136 TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx, UseMI, UseOperIdx); 137 } 138 else { 139 unsigned DefClass = DefMI->getDesc().getSchedClass(); 140 OperLatency = InstrItins.getOperandCycle(DefClass, DefOperIdx); 141 } 142 if (OperLatency >= 0) 143 return OperLatency; 144 145 // No operand latency was found. 146 unsigned InstrLatency = TII->getInstrLatency(&InstrItins, DefMI); 147 148 // Expected latency is the max of the stage latency and itinerary props. 149 if (!FindMin) 150 InstrLatency = std::max(InstrLatency, 151 TII->defaultDefLatency(&SchedModel, DefMI)); 152 return InstrLatency; 153 } 154 assert(!FindMin && hasInstrSchedModel() && 155 "Expected a SchedModel for this cpu"); 156 const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI); 157 unsigned DefIdx = findDefIdx(DefMI, DefOperIdx); 158 if (DefIdx < SCDesc->NumWriteLatencyEntries) { 159 // Lookup the definition's write latency in SubtargetInfo. 160 const MCWriteLatencyEntry *WLEntry = 161 STI->getWriteLatencyEntry(SCDesc, DefIdx); 162 unsigned WriteID = WLEntry->WriteResourceID; 163 unsigned Latency = WLEntry->Cycles; 164 if (!UseMI) 165 return Latency; 166 167 // Lookup the use's latency adjustment in SubtargetInfo. 168 const MCSchedClassDesc *UseDesc = resolveSchedClass(UseMI); 169 if (UseDesc->NumReadAdvanceEntries == 0) 170 return Latency; 171 unsigned UseIdx = findUseIdx(UseMI, UseOperIdx); 172 return Latency - STI->getReadAdvanceCycles(UseDesc, UseIdx, WriteID); 173 } 174 // If DefIdx does not exist in the model (e.g. implicit defs), then return 175 // unit latency (defaultDefLatency may be too conservative). 176#ifndef NDEBUG 177 if (SCDesc->isValid() && !DefMI->getOperand(DefOperIdx).isImplicit() 178 && !DefMI->getDesc().OpInfo[DefOperIdx].isOptionalDef()) { 179 std::string Err; 180 raw_string_ostream ss(Err); 181 ss << "DefIdx " << DefIdx << " exceeds machine model writes for " 182 << *DefMI; 183 report_fatal_error(ss.str()); 184 } 185#endif 186 return 1; 187} 188