TargetSchedule.cpp revision 34301ceca8913f3126339f332d3dc6f2d7ac0d78
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 21using namespace llvm; 22 23static cl::opt<bool> EnableSchedModel("schedmodel", cl::Hidden, cl::init(false), 24 cl::desc("Use TargetSchedModel for latency lookup")); 25 26static cl::opt<bool> EnableSchedItins("scheditins", cl::Hidden, cl::init(true), 27 cl::desc("Use InstrItineraryData for latency lookup")); 28 29void TargetSchedModel::init(const MCSchedModel &sm, 30 const TargetSubtargetInfo *sti, 31 const TargetInstrInfo *tii) { 32 SchedModel = sm; 33 STI = sti; 34 TII = tii; 35 STI->initInstrItins(InstrItins); 36} 37 38/// If we can determine the operand latency from the def only, without machine 39/// model or itinerary lookup, do so. Otherwise return -1. 40int TargetSchedModel::getDefLatency(const MachineInstr *DefMI, 41 bool FindMin) const { 42 43 // Return a latency based on the itinerary properties and defining instruction 44 // if possible. Some common subtargets don't require per-operand latency, 45 // especially for minimum latencies. 46 if (FindMin) { 47 // If MinLatency is invalid, then use the itinerary for MinLatency. If no 48 // itinerary exists either, then use single cycle latency. 49 if (SchedModel.MinLatency < 0 50 && !(EnableSchedItins && hasInstrItineraries())) { 51 return 1; 52 } 53 return SchedModel.MinLatency; 54 } 55 else if (!(EnableSchedModel && hasInstrSchedModel()) 56 && !(EnableSchedItins && hasInstrItineraries())) { 57 return TII->defaultDefLatency(&SchedModel, DefMI); 58 } 59 // ...operand lookup required 60 return -1; 61} 62 63/// Return the MCSchedClassDesc for this instruction. Some SchedClasses require 64/// evaluation of predicates that depend on instruction operands or flags. 65const MCSchedClassDesc *TargetSchedModel:: 66resolveSchedClass(const MachineInstr *MI) const { 67 68 // Get the definition's scheduling class descriptor from this machine model. 69 unsigned SchedClass = MI->getDesc().getSchedClass(); 70 const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SchedClass); 71 72#ifndef NDEBUG 73 unsigned NIter = 0; 74#endif 75 while (SCDesc->isVariant()) { 76 assert(++NIter < 6 && "Variants are nested deeper than the magic number"); 77 78 SchedClass = STI->resolveSchedClass(SchedClass, MI, this); 79 SCDesc = SchedModel.getSchedClassDesc(SchedClass); 80 } 81 return SCDesc; 82} 83 84/// Find the def index of this operand. This index maps to the machine model and 85/// is independent of use operands. Def operands may be reordered with uses or 86/// merged with uses without affecting the def index (e.g. before/after 87/// regalloc). However, an instruction's def operands must never be reordered 88/// with respect to each other. 89static unsigned findDefIdx(const MachineInstr *MI, unsigned DefOperIdx) { 90 unsigned DefIdx = 0; 91 for (unsigned i = 0; i != DefOperIdx; ++i) { 92 const MachineOperand &MO = MI->getOperand(i); 93 if (MO.isReg() && MO.isDef()) 94 ++DefIdx; 95 } 96 return DefIdx; 97} 98 99/// Find the use index of this operand. This is independent of the instruction's 100/// def operands. 101static unsigned findUseIdx(const MachineInstr *MI, unsigned UseOperIdx) { 102 unsigned UseIdx = 0; 103 for (unsigned i = 0; i != UseOperIdx; ++i) { 104 const MachineOperand &MO = MI->getOperand(i); 105 if (MO.isReg() && MO.isUse()) 106 ++UseIdx; 107 } 108 return UseIdx; 109} 110 111// Top-level API for clients that know the operand indices. 112unsigned TargetSchedModel::computeOperandLatency( 113 const MachineInstr *DefMI, unsigned DefOperIdx, 114 const MachineInstr *UseMI, unsigned UseOperIdx, 115 bool FindMin) const { 116 117 int DefLatency = getDefLatency(DefMI, FindMin); 118 if (DefLatency >= 0) 119 return DefLatency; 120 121 if (!FindMin && EnableSchedModel && hasInstrSchedModel()) { 122 const MCSchedClassDesc *SCDesc = resolveSchedClass(DefMI); 123 unsigned DefIdx = findDefIdx(DefMI, DefOperIdx); 124 if (DefIdx < SCDesc->NumWriteLatencyEntries) { 125 126 // Lookup the definition's write latency in SubtargetInfo. 127 const MCWriteLatencyEntry *WLEntry = 128 STI->getWriteLatencyEntry(SCDesc, DefIdx); 129 unsigned WriteID = WLEntry->WriteResourceID; 130 unsigned Latency = WLEntry->Cycles; 131 if (!UseMI) 132 return Latency; 133 134 // Lookup the use's latency adjustment in SubtargetInfo. 135 const MCSchedClassDesc *UseDesc = resolveSchedClass(UseMI); 136 if (UseDesc->NumReadAdvanceEntries == 0) 137 return Latency; 138 unsigned UseIdx = findUseIdx(UseMI, UseOperIdx); 139 return Latency - STI->getReadAdvanceCycles(UseDesc, UseIdx, WriteID); 140 } 141 // If DefIdx does not exist in the model (e.g. implicit defs), then return 142 // unit latency (defaultDefLatency may be too conservative). 143 // TODO: For unknown defs, we may want to use the subtarget's model 144 // for WAW latency here instead of 1 cycle. 145 assert((!SCDesc->isValid() || DefMI->getOperand(DefOperIdx).isImplicit()) && 146 "DefIdx exceeds machine model def operand list"); 147 return 1; 148 } 149 assert(EnableSchedItins && hasInstrItineraries() && 150 "operand latency requires itinerary"); 151 152 int OperLatency = 0; 153 if (UseMI) { 154 OperLatency = 155 TII->getOperandLatency(&InstrItins, DefMI, DefOperIdx, UseMI, UseOperIdx); 156 } 157 else { 158 unsigned DefClass = DefMI->getDesc().getSchedClass(); 159 OperLatency = InstrItins.getOperandCycle(DefClass, DefOperIdx); 160 } 161 if (OperLatency >= 0) 162 return OperLatency; 163 164 // No operand latency was found. 165 unsigned InstrLatency = TII->getInstrLatency(&InstrItins, DefMI); 166 167 // Expected latency is the max of the stage latency and itinerary props. 168 if (!FindMin) 169 InstrLatency = std::max(InstrLatency, 170 TII->defaultDefLatency(&SchedModel, DefMI)); 171 return InstrLatency; 172} 173