LCOV - code coverage report
Current view: top level - lib/MC - MCSchedule.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 44 59 74.6 %
Date: 2018-10-20 13:21:21 Functions: 5 6 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- MCSchedule.cpp - Scheduling ------------------------------*- 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 defines the default scheduling model.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "llvm/MC/MCSchedule.h"
      15             : #include "llvm/MC/MCInst.h"
      16             : #include "llvm/MC/MCInstrDesc.h"
      17             : #include "llvm/MC/MCInstrInfo.h"
      18             : #include "llvm/MC/MCSubtargetInfo.h"
      19             : #include <type_traits>
      20             : 
      21             : using namespace llvm;
      22             : 
      23             : static_assert(std::is_pod<MCSchedModel>::value,
      24             :               "We shouldn't have a static constructor here");
      25             : const MCSchedModel MCSchedModel::Default = {DefaultIssueWidth,
      26             :                                             DefaultMicroOpBufferSize,
      27             :                                             DefaultLoopMicroOpBufferSize,
      28             :                                             DefaultLoadLatency,
      29             :                                             DefaultHighLatency,
      30             :                                             DefaultMispredictPenalty,
      31             :                                             false,
      32             :                                             true,
      33             :                                             0,
      34             :                                             nullptr,
      35             :                                             nullptr,
      36             :                                             0,
      37             :                                             0,
      38             :                                             nullptr,
      39             :                                             nullptr};
      40             : 
      41     1481470 : int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
      42             :                                       const MCSchedClassDesc &SCDesc) {
      43     1481470 :   int Latency = 0;
      44     1481470 :   for (unsigned DefIdx = 0, DefEnd = SCDesc.NumWriteLatencyEntries;
      45     2964949 :        DefIdx != DefEnd; ++DefIdx) {
      46             :     // Lookup the definition's write latency in SubtargetInfo.
      47             :     const MCWriteLatencyEntry *WLEntry =
      48     1483479 :         STI.getWriteLatencyEntry(&SCDesc, DefIdx);
      49             :     // Early exit if we found an invalid latency.
      50     1483479 :     if (WLEntry->Cycles < 0)
      51           0 :       return WLEntry->Cycles;
      52     2791161 :     Latency = std::max(Latency, static_cast<int>(WLEntry->Cycles));
      53             :   }
      54     1481470 :   return Latency;
      55             : }
      56             : 
      57       16164 : int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
      58             :                                       unsigned SchedClass) const {
      59       16164 :   const MCSchedClassDesc &SCDesc = *getSchedClassDesc(SchedClass);
      60       16164 :   if (!SCDesc.isValid())
      61             :     return 0;
      62       16164 :   if (!SCDesc.isVariant())
      63       16164 :     return MCSchedModel::computeInstrLatency(STI, SCDesc);
      64             : 
      65           0 :   llvm_unreachable("unsupported variant scheduling class");
      66             : }
      67             : 
      68       60861 : int MCSchedModel::computeInstrLatency(const MCSubtargetInfo &STI,
      69             :                                       const MCInstrInfo &MCII,
      70             :                                       const MCInst &Inst) const {
      71      121722 :   unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
      72       60861 :   const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
      73       60861 :   if (!SCDesc->isValid())
      74             :     return 0;
      75             : 
      76       60861 :   unsigned CPUID = getProcessorID();
      77       61206 :   while (SCDesc->isVariant()) {
      78         345 :     SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID);
      79         345 :     SCDesc = getSchedClassDesc(SchedClass);
      80             :   }
      81             : 
      82       60861 :   if (SchedClass)
      83       60861 :     return MCSchedModel::computeInstrLatency(STI, *SCDesc);
      84             : 
      85           0 :   llvm_unreachable("unsupported variant scheduling class");
      86             : }
      87             : 
      88             : double
      89       89433 : MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI,
      90             :                                       const MCSchedClassDesc &SCDesc) {
      91             :   Optional<double> Throughput;
      92       89433 :   const MCSchedModel &SM = STI.getSchedModel();
      93       89433 :   const MCWriteProcResEntry *I = STI.getWriteProcResBegin(&SCDesc);
      94             :   const MCWriteProcResEntry *E = STI.getWriteProcResEnd(&SCDesc);
      95      518659 :   for (; I != E; ++I) {
      96      429226 :     if (!I->Cycles)
      97           0 :       continue;
      98      429226 :     unsigned NumUnits = SM.getProcResource(I->ProcResourceIdx)->NumUnits;
      99      429226 :     double Temp = NumUnits * 1.0 / I->Cycles;
     100      770057 :     Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp;
     101             :   }
     102       89433 :   if (Throughput.hasValue())
     103       88395 :     return 1.0 / Throughput.getValue();
     104             : 
     105             :   // If no throughput value was calculated, assume that we can execute at the
     106             :   // maximum issue width scaled by number of micro-ops for the schedule class.
     107        1038 :   return ((double)SCDesc.NumMicroOps) / SM.IssueWidth;
     108             : }
     109             : 
     110             : double
     111       60861 : MCSchedModel::getReciprocalThroughput(const MCSubtargetInfo &STI,
     112             :                                       const MCInstrInfo &MCII,
     113             :                                       const MCInst &Inst) const {
     114      121722 :   unsigned SchedClass = MCII.get(Inst.getOpcode()).getSchedClass();
     115       60861 :   const MCSchedClassDesc *SCDesc = getSchedClassDesc(SchedClass);
     116             : 
     117             :   // If there's no valid class, assume that the instruction executes/completes
     118             :   // at the maximum issue width.
     119       60861 :   if (!SCDesc->isValid())
     120           0 :     return 1.0 / IssueWidth;
     121             : 
     122       60861 :   unsigned CPUID = getProcessorID();
     123       61206 :   while (SCDesc->isVariant()) {
     124         345 :     SchedClass = STI.resolveVariantSchedClass(SchedClass, &Inst, CPUID);
     125         345 :     SCDesc = getSchedClassDesc(SchedClass);
     126             :   }
     127             : 
     128       60861 :   if (SchedClass)
     129       60861 :     return MCSchedModel::getReciprocalThroughput(STI, *SCDesc);
     130             : 
     131           0 :   llvm_unreachable("unsupported variant scheduling class");
     132             : }
     133             : 
     134             : double
     135           0 : MCSchedModel::getReciprocalThroughput(unsigned SchedClass,
     136             :                                       const InstrItineraryData &IID) {
     137             :   Optional<double> Throughput;
     138           0 :   const InstrStage *I = IID.beginStage(SchedClass);
     139             :   const InstrStage *E = IID.endStage(SchedClass);
     140           0 :   for (; I != E; ++I) {
     141           0 :     if (!I->getCycles())
     142           0 :       continue;
     143           0 :     double Temp = countPopulation(I->getUnits()) * 1.0 / I->getCycles();
     144           0 :     Throughput = Throughput ? std::min(Throughput.getValue(), Temp) : Temp;
     145             :   }
     146           0 :   if (Throughput.hasValue())
     147           0 :     return 1.0 / Throughput.getValue();
     148             : 
     149             :   // If there are no execution resources specified for this class, then assume
     150             :   // that it can execute at the maximum default issue width.
     151             :   return 1.0 / DefaultIssueWidth;
     152             : }

Generated by: LCOV version 1.13