summaryrefslogtreecommitdiff
path: root/utils/TableGen/CodeGenSchedule.cpp
blob: f57fd182eafbe0949828d8cac040334c8021205a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines structures to encapsulate the machine model as decribed in
// the target description.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "subtarget-emitter"

#include "CodeGenSchedule.h"
#include "CodeGenTarget.h"
#include "llvm/Support/Debug.h"

using namespace llvm;

// CodeGenModels ctor interprets machine model records and populates maps.
CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
                                       const CodeGenTarget &TGT):
  Records(RK), Target(TGT), NumItineraryClasses(0), HasProcItineraries(false) {

  // Populate SchedClassIdxMap and set NumItineraryClasses.
  CollectSchedClasses();

  // Populate ProcModelMap.
  CollectProcModels();
}

// Visit all the instruction definitions for this target to gather and enumerate
// the itinerary classes. These are the explicitly specified SchedClasses. More
// SchedClasses may be inferred.
void CodeGenSchedModels::CollectSchedClasses() {

  // NoItinerary is always the first class at Index=0
  SchedClasses.resize(1);
  SchedClasses.back().Name = "NoItinerary";
  SchedClassIdxMap[SchedClasses.back().Name] = 0;

  // Gather and sort all itinerary classes used by instruction descriptions.
  std::vector<Record*> ItinClassList;
  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
         E = Target.inst_end(); I != E; ++I) {
    Record *SchedDef = (*I)->TheDef->getValueAsDef("Itinerary");
    // Map a new SchedClass with no index.
    if (!SchedClassIdxMap.count(SchedDef->getName())) {
      SchedClassIdxMap[SchedDef->getName()] = 0;
      ItinClassList.push_back(SchedDef);
    }
  }
  // Assign each itinerary class unique number, skipping NoItinerary==0
  NumItineraryClasses = ItinClassList.size();
  std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
  for (unsigned i = 0, N = NumItineraryClasses; i < N; i++) {
    Record *ItinDef = ItinClassList[i];
    SchedClassIdxMap[ItinDef->getName()] = SchedClasses.size();
    SchedClasses.push_back(CodeGenSchedClass(ItinDef));
  }

  // TODO: Infer classes from non-itinerary scheduler resources.
}

// Gather all processor models.
void CodeGenSchedModels::CollectProcModels() {
  std::vector<Record*> ProcRecords =
    Records.getAllDerivedDefinitions("Processor");
  std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName());

  // Reserve space because we can. Reallocation would be ok.
  ProcModels.reserve(ProcRecords.size());

  // For each processor, find a unique machine model.
  for (unsigned i = 0, N = ProcRecords.size(); i < N; ++i)
    addProcModel(ProcRecords[i]);
}

// Get a unique processor model based on the defined MachineModel and
// ProcessorItineraries.
void CodeGenSchedModels::addProcModel(Record *ProcDef) {
  unsigned Idx = getProcModelIdx(ProcDef);
  if (Idx < ProcModels.size())
    return;

  Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
  Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");

  std::string ModelName = ModelDef->getName();
  const std::string &ItinName = ItinsDef->getName();

  bool NoModel = ModelDef->getValueAsBit("NoModel");
  bool hasTopLevelItin = !ItinsDef->getValueAsListOfDefs("IID").empty();
  if (NoModel) {
    // If an itinerary is defined without a machine model, infer a new model.
    if (NoModel && hasTopLevelItin) {
      ModelName = ItinName + "Model";
      ModelDef = NULL;
    }
  }
  else {
    // If a machine model is defined, the itinerary must be defined within it
    // rather than in the Processor definition itself.
    assert(!hasTopLevelItin && "Itinerary must be defined in SchedModel");
    ItinsDef = ModelDef->getValueAsDef("Itineraries");
  }

  ProcModelMap[getProcModelKey(ProcDef)]= ProcModels.size();

  ProcModels.push_back(CodeGenProcModel(ModelName, ModelDef, ItinsDef));

  std::vector<Record*> ItinRecords = ItinsDef->getValueAsListOfDefs("IID");
  CollectProcItin(ProcModels.back(), ItinRecords);
}

// Gather the processor itineraries.
void CodeGenSchedModels::CollectProcItin(CodeGenProcModel &ProcModel,
                                         std::vector<Record*> ItinRecords) {
  // Skip empty itinerary.
  if (ItinRecords.empty())
    return;

  HasProcItineraries = true;

  ProcModel.ItinDefList.resize(NumItineraryClasses+1);

  // Insert each itinerary data record in the correct position within
  // the processor model's ItinDefList.
  for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) {
    Record *ItinData = ItinRecords[i];
    Record *ItinDef = ItinData->getValueAsDef("TheClass");
    if (!SchedClassIdxMap.count(ItinDef->getName())) {
      DEBUG(dbgs() << ProcModel.ItinsDef->getName()
            << " has unused itinerary class " << ItinDef->getName() << '\n');
      continue;
    }
    ProcModel.ItinDefList[getItinClassIdx(ItinDef)] = ItinData;
  }
#ifndef NDEBUG
  // Check for missing itinerary entries.
  assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec");
  for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) {
    if (!ProcModel.ItinDefList[i])
      DEBUG(dbgs() << ProcModel.ItinsDef->getName()
            << " missing itinerary for class " << SchedClasses[i].Name << '\n');
  }
#endif
}