summaryrefslogtreecommitdiff
path: root/utils/TableGen/CodeGenSchedule.h
blob: 9da0145732b3868d020bb67ad53d547d4b9229f5 (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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
//===- CodeGenSchedule.h - Scheduling Machine Models ------------*- 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 structures to encapsulate the machine model as decribed in
// the target description.
//
//===----------------------------------------------------------------------===//

#ifndef CODEGEN_SCHEDULE_H
#define CODEGEN_SCHEDULE_H

#include "llvm/TableGen/Record.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"

namespace llvm {

class CodeGenTarget;

// Scheduling class.
//
// Each instruction description will be mapped to a scheduling class. It may be
// an explicitly defined itinerary class, or an inferred class in which case
// ItinClassDef == NULL.
struct CodeGenSchedClass {
  std::string Name;
  unsigned Index;
  Record *ItinClassDef;

  CodeGenSchedClass(): Index(0), ItinClassDef(0) {}
  CodeGenSchedClass(Record *rec): Index(0), ItinClassDef(rec) {
    Name = rec->getName();
  }
};

// Processor model.
//
// ModelName is a unique name used to name an instantiation of MCSchedModel.
//
// ModelDef is NULL for inferred Models. This happens when a processor defines
// an itinerary but no machine model. If the processer defines neither a machine
// model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
// the special "NoModel" field set to true.
//
// ItinsDef always points to a valid record definition, but may point to the
// default NoItineraries. NoItineraries has an empty list of InstrItinData
// records.
//
// ItinDefList orders this processor's InstrItinData records by SchedClass idx.
struct CodeGenProcModel {
  std::string ModelName;
  Record *ModelDef;
  Record *ItinsDef;

  // Array of InstrItinData records indexed by CodeGenSchedClass::Index.
  // The list is empty if the subtarget has no itineraries.
  std::vector<Record *> ItinDefList;

  CodeGenProcModel(const std::string &Name, Record *MDef, Record *IDef):
    ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}
};

// Top level container for machine model data.
class CodeGenSchedModels {
  RecordKeeper &Records;
  const CodeGenTarget &Target;

  // List of unique SchedClasses.
  std::vector<CodeGenSchedClass> SchedClasses;

  // Map SchedClass name to itinerary index.
  // These are either explicit itinerary classes or inferred classes.
  StringMap<unsigned> SchedClassIdxMap;

  // SchedClass indices 1 up to and including NumItineraryClasses identify
  // itinerary classes that are explicitly used for this target's instruction
  // definitions. NoItinerary always has index 0 regardless of whether it is
  // explicitly referenced.
  //
  // Any inferred SchedClass have a index greater than NumItineraryClasses.
  unsigned NumItineraryClasses;

  // List of unique processor models.
  std::vector<CodeGenProcModel> ProcModels;

  // Map Processor's MachineModel + ProcItin fields to a CodeGenProcModel index.
  typedef DenseMap<std::pair<Record*, Record*>, unsigned> ProcModelMapTy;
  ProcModelMapTy ProcModelMap;

  // True if any processors have nonempty itineraries.
  bool HasProcItineraries;

public:
  CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);

  // Check if any instructions are assigned to an explicit itinerary class other
  // than NoItinerary.
  bool hasItineraryClasses() const { return NumItineraryClasses > 0; }

  // Return the number of itinerary classes in use by this target's instruction
  // descriptions, not including "NoItinerary".
  unsigned numItineraryClasses() const {
    return NumItineraryClasses;
  }

  // Get a SchedClass from its index.
  const CodeGenSchedClass &getSchedClass(unsigned Idx) {
    assert(Idx < SchedClasses.size() && "bad SchedClass index");
    return SchedClasses[Idx];
  }

  // Get an itinerary class's index. Value indices are '0' for NoItinerary up to
  // and including numItineraryClasses().
  unsigned getItinClassIdx(Record *ItinDef) const {
    assert(SchedClassIdxMap.count(ItinDef->getName()) && "missing ItinClass");
    unsigned Idx = SchedClassIdxMap.lookup(ItinDef->getName());
    assert(Idx <= NumItineraryClasses && "bad ItinClass index");
    return Idx;
  }

  bool hasProcessorItineraries() const {
    return HasProcItineraries;
  }

  // Get an existing machine model for a processor definition.
  const CodeGenProcModel &getProcModel(Record *ProcDef) const {
    unsigned idx = getProcModelIdx(ProcDef);
    assert(idx < ProcModels.size() && "missing machine model");
    return ProcModels[idx];
  }

  // Iterate over the unique processor models.
  typedef std::vector<CodeGenProcModel>::const_iterator ProcIter;
  ProcIter procModelBegin() const { return ProcModels.begin(); }
  ProcIter procModelEnd() const { return ProcModels.end(); }

private:
  // Get a key that can uniquely identify a machine model.
  ProcModelMapTy::key_type getProcModelKey(Record *ProcDef) const {
    Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
    Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
    return std::make_pair(ModelDef, ItinsDef);
  }

  // Get the unique index of a machine model.
  unsigned getProcModelIdx(Record *ProcDef) const {
    ProcModelMapTy::const_iterator I =
      ProcModelMap.find(getProcModelKey(ProcDef));
    if (I == ProcModelMap.end())
      return ProcModels.size();
    return I->second;
  }

  // Initialize a new processor model if it is unique.
  void addProcModel(Record *ProcDef);

  void CollectSchedClasses();
  void CollectProcModels();
  void CollectProcItin(CodeGenProcModel &ProcModel,
                       std::vector<Record*> ItinRecords);
};

} // namespace llvm

#endif