//===- MCSchedule.cpp - Scheduling ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file defines the default scheduling model. // //===----------------------------------------------------------------------===// #include "llvm/MC/MCSchedule.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include using namespace llvm; static_assert(std::is_pod::value, "We shouldn't have a static constructor here"); const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth, DefaultMicroOpBufferSize, DefaultLoopMicroOpBufferSize, DefaultLoadLatency, DefaultHighLatency, DefaultMispredictPenalty, false, true, 0, nullptr, nullptr, 0, 0, nullptr, nullptr}; int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc) { int Latency = 0; for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries; DefIdx != DefEnd; ++DefIdx) { // Lookup the definition's write latency in SubtargetInfo. const MCWriteLatencyEntry *WLEntry = STI.getWriteLatencyEntry(&SCDesc, DefIdx); // Early exit if we found an invalid latency. if (WLEntry->Cycles < 0) return WLEntry->Cycles; Latency = std::max(Latency, static_cast(WLEntry->Cycles)); } return Latency; } int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI, unsigned SchedClass) const { const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass); if (!SCDesc.isValid()) return 0; if (!SCDesc.isVariant()) return MCSchedModel::computeInstrLatency(STI, SCDesc); llvm_unreachable("unsupported variant scheduling class"); } Optional MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc) { Optional Throughput; const MCSchedModel &SM = STI.getSchedModel(); const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc); const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc); for (; I != E; ++I) { if (!I->Cycles) continue; unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits; double Temp = NumUnits * 1.0 / I->Cycles; Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp; } return Throughput ? 1 / Throughput.getValue() : Throughput; } Optional MCSchedModel::getReciprocalThroughput(unsigned SchedClass, const InstrItineraryData &IID) { Optional Throughput; const InstrStage *I = IID.beginStage(SchedClass); const InstrStage *E = IID.endStage(SchedClass); for (; I != E; ++I) { if (!I->getCycles()) continue; double Temp = countPopulation(I->getUnits()) * 1.0 / I->getCycles(); Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp; } return Throughput ? 1 / Throughput.getValue() : Throughput; }