blob: 99d3b8e21d8b9d92feeca376f21ed486bc393d08 [file] [log] [blame]
Jim Laskey4bb9cbb2005-10-21 19:00:04 +00001//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner30609102007-12-29 20:37:13 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Jim Laskey4bb9cbb2005-10-21 19:00:04 +00007//
8//===----------------------------------------------------------------------===//
9//
Chris Lattner3d878112006-03-03 02:04:07 +000010// This tablegen backend emits subtarget enumerations.
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000011//
12//===----------------------------------------------------------------------===//
13
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000014#include "CodeGenTarget.h"
Andrew Trick2661b412012-07-07 04:00:00 +000015#include "CodeGenSchedule.h"
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000016#include "llvm/ADT/StringExtras.h"
Andrew Trick40096d22012-09-17 22:18:45 +000017#include "llvm/ADT/STLExtras.h"
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000018#include "llvm/MC/MCInstrItineraries.h"
Andrew Trick40096d22012-09-17 22:18:45 +000019#include "llvm/TableGen/Error.h"
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000020#include "llvm/TableGen/Record.h"
21#include "llvm/TableGen/TableGenBackend.h"
Andrew Trick40096d22012-09-17 22:18:45 +000022#include "llvm/Support/Debug.h"
Jeff Cohen9489c042005-10-28 01:43:09 +000023#include <algorithm>
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000024#include <map>
25#include <string>
26#include <vector>
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000027using namespace llvm;
28
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000029namespace {
30class SubtargetEmitter {
31
32 RecordKeeper &Records;
Andrew Trick2661b412012-07-07 04:00:00 +000033 CodeGenSchedModels &SchedModels;
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000034 std::string Target;
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000035
36 void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
37 unsigned FeatureKeyValues(raw_ostream &OS);
38 unsigned CPUKeyValues(raw_ostream &OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000039 void FormItineraryStageString(const std::string &Names,
40 Record *ItinData, std::string &ItinString,
41 unsigned &NStages);
42 void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
43 unsigned &NOperandCycles);
44 void FormItineraryBypassString(const std::string &Names,
45 Record *ItinData,
46 std::string &ItinString, unsigned NOperandCycles);
Andrew Trick2661b412012-07-07 04:00:00 +000047 void EmitStageAndOperandCycleData(raw_ostream &OS,
48 std::vector<std::vector<InstrItinerary> >
49 &ProcItinLists);
50 void EmitItineraries(raw_ostream &OS,
51 std::vector<std::vector<InstrItinerary> >
52 &ProcItinLists);
53 void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000054 char Separator);
Andrew Trick40096d22012-09-17 22:18:45 +000055 void EmitProcessorResources(const CodeGenProcModel &ProcModel,
56 raw_ostream &OS);
Andrew Trick2661b412012-07-07 04:00:00 +000057 void EmitProcessorModels(raw_ostream &OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000058 void EmitProcessorLookup(raw_ostream &OS);
Andrew Trick2661b412012-07-07 04:00:00 +000059 void EmitSchedModel(raw_ostream &OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000060 void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
61 unsigned NumProcs);
62
63public:
Andrew Trick2661b412012-07-07 04:00:00 +000064 SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
65 Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000066
67 void run(raw_ostream &o);
68
69};
70} // End anonymous namespace
71
Jim Laskey7dc02042005-10-22 07:59:56 +000072//
Jim Laskey581a8f72005-10-26 17:30:34 +000073// Enumeration - Emit the specified class as an enumeration.
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000074//
Daniel Dunbar1a551802009-07-03 00:10:29 +000075void SubtargetEmitter::Enumeration(raw_ostream &OS,
Jim Laskey581a8f72005-10-26 17:30:34 +000076 const char *ClassName,
77 bool isBits) {
Jim Laskey908ae272005-10-28 15:20:43 +000078 // Get all records of class and sort
Jim Laskeyf7bcde02005-10-28 21:47:29 +000079 std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
Duraid Madina42d24c72005-12-30 14:56:37 +000080 std::sort(DefList.begin(), DefList.end(), LessRecord());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000081
Evan Chengb6a63882011-04-15 19:35:46 +000082 unsigned N = DefList.size();
Evan Cheng94214702011-07-01 20:45:01 +000083 if (N == 0)
84 return;
Evan Chengb6a63882011-04-15 19:35:46 +000085 if (N > 64) {
86 errs() << "Too many (> 64) subtarget features!\n";
87 exit(1);
88 }
89
Evan Cheng94214702011-07-01 20:45:01 +000090 OS << "namespace " << Target << " {\n";
91
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +000092 // For bit flag enumerations with more than 32 items, emit constants.
93 // Emit an enum for everything else.
94 if (isBits && N > 32) {
95 // For each record
96 for (unsigned i = 0; i < N; i++) {
97 // Next record
98 Record *Def = DefList[i];
Evan Cheng94214702011-07-01 20:45:01 +000099
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000100 // Get and emit name and expression (1 << i)
101 OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
102 }
103 } else {
104 // Open enumeration
105 OS << "enum {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000106
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000107 // For each record
108 for (unsigned i = 0; i < N;) {
109 // Next record
110 Record *Def = DefList[i];
Andrew Trickda96cf22011-04-01 01:56:55 +0000111
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000112 // Get and emit name
113 OS << " " << Def->getName();
Jim Laskey908ae272005-10-28 15:20:43 +0000114
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000115 // If bit flags then emit expression (1 << i)
116 if (isBits) OS << " = " << " 1ULL << " << i;
Andrew Trickda96cf22011-04-01 01:56:55 +0000117
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000118 // Depending on 'if more in the list' emit comma
119 if (++i < N) OS << ",";
120
121 OS << "\n";
122 }
123
124 // Close enumeration
125 OS << "};\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000126 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000127
Evan Cheng94214702011-07-01 20:45:01 +0000128 OS << "}\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000129}
130
131//
Bill Wendling4222d802007-05-04 20:38:40 +0000132// FeatureKeyValues - Emit data of all the subtarget features. Used by the
133// command line.
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000134//
Evan Cheng94214702011-07-01 20:45:01 +0000135unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
Jim Laskey908ae272005-10-28 15:20:43 +0000136 // Gather and sort all the features
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000137 std::vector<Record*> FeatureList =
138 Records.getAllDerivedDefinitions("SubtargetFeature");
Evan Cheng94214702011-07-01 20:45:01 +0000139
140 if (FeatureList.empty())
141 return 0;
142
Jim Grosbach7c9a7722008-09-11 17:05:32 +0000143 std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000144
Jim Laskey908ae272005-10-28 15:20:43 +0000145 // Begin feature table
Jim Laskey581a8f72005-10-26 17:30:34 +0000146 OS << "// Sorted (by key) array of values for CPU features.\n"
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000147 << "extern const llvm::SubtargetFeatureKV " << Target
148 << "FeatureKV[] = {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000149
Jim Laskey908ae272005-10-28 15:20:43 +0000150 // For each feature
Evan Cheng94214702011-07-01 20:45:01 +0000151 unsigned NumFeatures = 0;
Jim Laskeydbe40062006-12-12 20:55:58 +0000152 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000153 // Next feature
154 Record *Feature = FeatureList[i];
155
Bill Wendling4222d802007-05-04 20:38:40 +0000156 const std::string &Name = Feature->getName();
157 const std::string &CommandLineName = Feature->getValueAsString("Name");
158 const std::string &Desc = Feature->getValueAsString("Desc");
Andrew Trickda96cf22011-04-01 01:56:55 +0000159
Jim Laskeydbe40062006-12-12 20:55:58 +0000160 if (CommandLineName.empty()) continue;
Andrew Trickda96cf22011-04-01 01:56:55 +0000161
Jim Grosbachda4231f2009-03-26 16:17:51 +0000162 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000163 OS << " { "
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000164 << "\"" << CommandLineName << "\", "
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000165 << "\"" << Desc << "\", "
Evan Cheng94214702011-07-01 20:45:01 +0000166 << Target << "::" << Name << ", ";
Bill Wendling4222d802007-05-04 20:38:40 +0000167
Andrew Trickda96cf22011-04-01 01:56:55 +0000168 const std::vector<Record*> &ImpliesList =
Bill Wendling4222d802007-05-04 20:38:40 +0000169 Feature->getValueAsListOfDefs("Implies");
Andrew Trickda96cf22011-04-01 01:56:55 +0000170
Bill Wendling4222d802007-05-04 20:38:40 +0000171 if (ImpliesList.empty()) {
Evan Chengb6a63882011-04-15 19:35:46 +0000172 OS << "0ULL";
Bill Wendling4222d802007-05-04 20:38:40 +0000173 } else {
174 for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
Evan Cheng94214702011-07-01 20:45:01 +0000175 OS << Target << "::" << ImpliesList[j]->getName();
Bill Wendling4222d802007-05-04 20:38:40 +0000176 if (++j < M) OS << " | ";
177 }
178 }
179
180 OS << " }";
Evan Cheng94214702011-07-01 20:45:01 +0000181 ++NumFeatures;
Andrew Trickda96cf22011-04-01 01:56:55 +0000182
Jim Laskey10b1dd92005-10-31 17:16:01 +0000183 // Depending on 'if more in the list' emit comma
Jim Laskeydbe40062006-12-12 20:55:58 +0000184 if ((i + 1) < N) OS << ",";
Andrew Trickda96cf22011-04-01 01:56:55 +0000185
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000186 OS << "\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000187 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000188
Jim Laskey908ae272005-10-28 15:20:43 +0000189 // End feature table
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000190 OS << "};\n";
191
Evan Cheng94214702011-07-01 20:45:01 +0000192 return NumFeatures;
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000193}
194
195//
196// CPUKeyValues - Emit data of all the subtarget processors. Used by command
197// line.
198//
Evan Cheng94214702011-07-01 20:45:01 +0000199unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
Jim Laskey908ae272005-10-28 15:20:43 +0000200 // Gather and sort processor information
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000201 std::vector<Record*> ProcessorList =
202 Records.getAllDerivedDefinitions("Processor");
Duraid Madina42d24c72005-12-30 14:56:37 +0000203 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000204
Jim Laskey908ae272005-10-28 15:20:43 +0000205 // Begin processor table
Jim Laskey581a8f72005-10-26 17:30:34 +0000206 OS << "// Sorted (by key) array of values for CPU subtype.\n"
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000207 << "extern const llvm::SubtargetFeatureKV " << Target
208 << "SubTypeKV[] = {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000209
Jim Laskey908ae272005-10-28 15:20:43 +0000210 // For each processor
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000211 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
212 // Next processor
213 Record *Processor = ProcessorList[i];
214
Bill Wendling4222d802007-05-04 20:38:40 +0000215 const std::string &Name = Processor->getValueAsString("Name");
Andrew Trickda96cf22011-04-01 01:56:55 +0000216 const std::vector<Record*> &FeatureList =
Chris Lattnerb0e103d2005-10-28 22:49:02 +0000217 Processor->getValueAsListOfDefs("Features");
Andrew Trickda96cf22011-04-01 01:56:55 +0000218
Jim Laskey908ae272005-10-28 15:20:43 +0000219 // Emit as { "cpu", "description", f1 | f2 | ... fn },
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000220 OS << " { "
221 << "\"" << Name << "\", "
222 << "\"Select the " << Name << " processor\", ";
Andrew Trickda96cf22011-04-01 01:56:55 +0000223
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000224 if (FeatureList.empty()) {
Evan Chengb6a63882011-04-15 19:35:46 +0000225 OS << "0ULL";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000226 } else {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000227 for (unsigned j = 0, M = FeatureList.size(); j < M;) {
Evan Cheng94214702011-07-01 20:45:01 +0000228 OS << Target << "::" << FeatureList[j]->getName();
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000229 if (++j < M) OS << " | ";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000230 }
231 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000232
Bill Wendling4222d802007-05-04 20:38:40 +0000233 // The "0" is for the "implies" section of this data structure.
Evan Chengb6a63882011-04-15 19:35:46 +0000234 OS << ", 0ULL }";
Andrew Trickda96cf22011-04-01 01:56:55 +0000235
Jim Laskey10b1dd92005-10-31 17:16:01 +0000236 // Depending on 'if more in the list' emit comma
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000237 if (++i < N) OS << ",";
Andrew Trickda96cf22011-04-01 01:56:55 +0000238
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000239 OS << "\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000240 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000241
Jim Laskey908ae272005-10-28 15:20:43 +0000242 // End processor table
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000243 OS << "};\n";
244
Evan Cheng94214702011-07-01 20:45:01 +0000245 return ProcessorList.size();
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000246}
Jim Laskey7dc02042005-10-22 07:59:56 +0000247
Jim Laskey581a8f72005-10-26 17:30:34 +0000248//
David Goodwinfac85412009-08-17 16:02:57 +0000249// FormItineraryStageString - Compose a string containing the stage
250// data initialization for the specified itinerary. N is the number
251// of stages.
Jim Laskey0d841e02005-10-27 19:47:21 +0000252//
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000253void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
254 Record *ItinData,
David Goodwinfac85412009-08-17 16:02:57 +0000255 std::string &ItinString,
256 unsigned &NStages) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000257 // Get states list
Bill Wendling4222d802007-05-04 20:38:40 +0000258 const std::vector<Record*> &StageList =
259 ItinData->getValueAsListOfDefs("Stages");
Jim Laskey908ae272005-10-28 15:20:43 +0000260
261 // For each stage
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000262 unsigned N = NStages = StageList.size();
Christopher Lamb8dadf6b2007-04-22 09:04:24 +0000263 for (unsigned i = 0; i < N;) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000264 // Next stage
Bill Wendling4222d802007-05-04 20:38:40 +0000265 const Record *Stage = StageList[i];
Andrew Trickda96cf22011-04-01 01:56:55 +0000266
Anton Korobeynikov96085a32010-04-07 18:19:32 +0000267 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
Jim Laskey0d841e02005-10-27 19:47:21 +0000268 int Cycles = Stage->getValueAsInt("Cycles");
Jim Laskey7f39c142005-11-03 22:47:41 +0000269 ItinString += " { " + itostr(Cycles) + ", ";
Andrew Trickda96cf22011-04-01 01:56:55 +0000270
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000271 // Get unit list
Bill Wendling4222d802007-05-04 20:38:40 +0000272 const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
Andrew Trickda96cf22011-04-01 01:56:55 +0000273
Jim Laskey908ae272005-10-28 15:20:43 +0000274 // For each unit
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000275 for (unsigned j = 0, M = UnitList.size(); j < M;) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000276 // Add name and bitwise or
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000277 ItinString += Name + "FU::" + UnitList[j]->getName();
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000278 if (++j < M) ItinString += " | ";
Jim Laskey0d841e02005-10-27 19:47:21 +0000279 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000280
David Goodwin1a8f36e2009-08-12 18:31:53 +0000281 int TimeInc = Stage->getValueAsInt("TimeInc");
282 ItinString += ", " + itostr(TimeInc);
283
Anton Korobeynikov96085a32010-04-07 18:19:32 +0000284 int Kind = Stage->getValueAsInt("Kind");
285 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
286
Jim Laskey908ae272005-10-28 15:20:43 +0000287 // Close off stage
288 ItinString += " }";
Christopher Lamb8dadf6b2007-04-22 09:04:24 +0000289 if (++i < N) ItinString += ", ";
Jim Laskey0d841e02005-10-27 19:47:21 +0000290 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000291}
292
293//
David Goodwinfac85412009-08-17 16:02:57 +0000294// FormItineraryOperandCycleString - Compose a string containing the
295// operand cycle initialization for the specified itinerary. N is the
296// number of operands that has cycles specified.
Jim Laskey0d841e02005-10-27 19:47:21 +0000297//
David Goodwinfac85412009-08-17 16:02:57 +0000298void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
299 std::string &ItinString, unsigned &NOperandCycles) {
300 // Get operand cycle list
301 const std::vector<int64_t> &OperandCycleList =
302 ItinData->getValueAsListOfInts("OperandCycles");
303
304 // For each operand cycle
305 unsigned N = NOperandCycles = OperandCycleList.size();
306 for (unsigned i = 0; i < N;) {
307 // Next operand cycle
308 const int OCycle = OperandCycleList[i];
Andrew Trickda96cf22011-04-01 01:56:55 +0000309
David Goodwinfac85412009-08-17 16:02:57 +0000310 ItinString += " " + itostr(OCycle);
311 if (++i < N) ItinString += ", ";
312 }
313}
314
Evan Cheng63d66ee2010-09-28 23:50:49 +0000315void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
316 Record *ItinData,
317 std::string &ItinString,
318 unsigned NOperandCycles) {
319 const std::vector<Record*> &BypassList =
320 ItinData->getValueAsListOfDefs("Bypasses");
321 unsigned N = BypassList.size();
Evan Cheng3881cb72010-09-29 22:42:35 +0000322 unsigned i = 0;
323 for (; i < N;) {
Evan Cheng63d66ee2010-09-28 23:50:49 +0000324 ItinString += Name + "Bypass::" + BypassList[i]->getName();
Evan Cheng3881cb72010-09-29 22:42:35 +0000325 if (++i < NOperandCycles) ItinString += ", ";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000326 }
Evan Cheng3881cb72010-09-29 22:42:35 +0000327 for (; i < NOperandCycles;) {
Evan Cheng63d66ee2010-09-28 23:50:49 +0000328 ItinString += " 0";
Evan Cheng3881cb72010-09-29 22:42:35 +0000329 if (++i < NOperandCycles) ItinString += ", ";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000330 }
331}
332
David Goodwinfac85412009-08-17 16:02:57 +0000333//
Andrew Trick2661b412012-07-07 04:00:00 +0000334// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
335// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
336// by CodeGenSchedClass::Index.
David Goodwinfac85412009-08-17 16:02:57 +0000337//
Andrew Trick2661b412012-07-07 04:00:00 +0000338void SubtargetEmitter::
339EmitStageAndOperandCycleData(raw_ostream &OS,
340 std::vector<std::vector<InstrItinerary> >
341 &ProcItinLists) {
Jim Laskey908ae272005-10-28 15:20:43 +0000342
Andrew Trickcb941922012-07-09 20:43:03 +0000343 // Multiple processor models may share an itinerary record. Emit it once.
344 SmallPtrSet<Record*, 8> ItinsDefSet;
345
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000346 // Emit functional units for all the itineraries.
Andrew Trick2661b412012-07-07 04:00:00 +0000347 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
348 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000349
Andrew Trickcb941922012-07-09 20:43:03 +0000350 if (!ItinsDefSet.insert(PI->ItinsDef))
351 continue;
352
Andrew Trick2661b412012-07-07 04:00:00 +0000353 std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000354 if (FUs.empty())
355 continue;
356
Andrew Trick2661b412012-07-07 04:00:00 +0000357 const std::string &Name = PI->ItinsDef->getName();
358 OS << "\n// Functional units for \"" << Name << "\"\n"
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000359 << "namespace " << Name << "FU {\n";
360
361 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
Hal Finkelb460a332012-06-22 20:27:13 +0000362 OS << " const unsigned " << FUs[j]->getName()
363 << " = 1 << " << j << ";\n";
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000364
365 OS << "}\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000366
Andrew Trick2661b412012-07-07 04:00:00 +0000367 std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
Evan Cheng3881cb72010-09-29 22:42:35 +0000368 if (BPs.size()) {
369 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
370 << "\"\n" << "namespace " << Name << "Bypass {\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000371
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000372 OS << " const unsigned NoBypass = 0;\n";
Evan Cheng3881cb72010-09-29 22:42:35 +0000373 for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000374 OS << " const unsigned " << BPs[j]->getName()
Evan Cheng3881cb72010-09-29 22:42:35 +0000375 << " = 1 << " << j << ";\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000376
Evan Cheng3881cb72010-09-29 22:42:35 +0000377 OS << "}\n";
378 }
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000379 }
380
Jim Laskey908ae272005-10-28 15:20:43 +0000381 // Begin stages table
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000382 std::string StageTable = "\nextern const llvm::InstrStage " + Target +
383 "Stages[] = {\n";
Anton Korobeynikov96085a32010-04-07 18:19:32 +0000384 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000385
David Goodwinfac85412009-08-17 16:02:57 +0000386 // Begin operand cycle table
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000387 std::string OperandCycleTable = "extern const unsigned " + Target +
Evan Cheng94214702011-07-01 20:45:01 +0000388 "OperandCycles[] = {\n";
David Goodwinfac85412009-08-17 16:02:57 +0000389 OperandCycleTable += " 0, // No itinerary\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000390
391 // Begin pipeline bypass table
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000392 std::string BypassTable = "extern const unsigned " + Target +
Andrew Tricka11a6282012-07-07 03:59:48 +0000393 "ForwardingPaths[] = {\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000394 BypassTable += " 0, // No itinerary\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000395
Andrew Trick2661b412012-07-07 04:00:00 +0000396 // For each Itinerary across all processors, add a unique entry to the stages,
397 // operand cycles, and pipepine bypess tables. Then add the new Itinerary
398 // object with computed offsets to the ProcItinLists result.
David Goodwinfac85412009-08-17 16:02:57 +0000399 unsigned StageCount = 1, OperandCycleCount = 1;
Evan Cheng3881cb72010-09-29 22:42:35 +0000400 std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
Andrew Trick2661b412012-07-07 04:00:00 +0000401 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
402 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
403 const CodeGenProcModel &ProcModel = *PI;
Andrew Trickda96cf22011-04-01 01:56:55 +0000404
Andrew Trick2661b412012-07-07 04:00:00 +0000405 // Add process itinerary to the list.
406 ProcItinLists.resize(ProcItinLists.size()+1);
Andrew Trickda96cf22011-04-01 01:56:55 +0000407
Andrew Trick2661b412012-07-07 04:00:00 +0000408 // If this processor defines no itineraries, then leave the itinerary list
409 // empty.
410 std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
411 if (ProcModel.ItinDefList.empty())
Andrew Trickd85934b2012-06-22 03:58:51 +0000412 continue;
Andrew Trickd85934b2012-06-22 03:58:51 +0000413
Andrew Trick2661b412012-07-07 04:00:00 +0000414 // Reserve index==0 for NoItinerary.
415 ItinList.resize(SchedModels.numItineraryClasses()+1);
416
417 const std::string &Name = ProcModel.ItinsDef->getName();
Andrew Trickda96cf22011-04-01 01:56:55 +0000418
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000419 // For each itinerary data
Andrew Trick2661b412012-07-07 04:00:00 +0000420 for (unsigned SchedClassIdx = 0,
421 SchedClassEnd = ProcModel.ItinDefList.size();
422 SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
423
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000424 // Next itinerary data
Andrew Trick2661b412012-07-07 04:00:00 +0000425 Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
Andrew Trickda96cf22011-04-01 01:56:55 +0000426
Jim Laskey908ae272005-10-28 15:20:43 +0000427 // Get string and stage count
David Goodwinfac85412009-08-17 16:02:57 +0000428 std::string ItinStageString;
Andrew Trick2661b412012-07-07 04:00:00 +0000429 unsigned NStages = 0;
430 if (ItinData)
431 FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
Jim Laskey0d841e02005-10-27 19:47:21 +0000432
David Goodwinfac85412009-08-17 16:02:57 +0000433 // Get string and operand cycle count
434 std::string ItinOperandCycleString;
Andrew Trick2661b412012-07-07 04:00:00 +0000435 unsigned NOperandCycles = 0;
Evan Cheng63d66ee2010-09-28 23:50:49 +0000436 std::string ItinBypassString;
Andrew Trick2661b412012-07-07 04:00:00 +0000437 if (ItinData) {
438 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
439 NOperandCycles);
440
441 FormItineraryBypassString(Name, ItinData, ItinBypassString,
442 NOperandCycles);
443 }
Evan Cheng63d66ee2010-09-28 23:50:49 +0000444
David Goodwinfac85412009-08-17 16:02:57 +0000445 // Check to see if stage already exists and create if it doesn't
446 unsigned FindStage = 0;
447 if (NStages > 0) {
448 FindStage = ItinStageMap[ItinStageString];
449 if (FindStage == 0) {
Andrew Trick23482322011-04-01 02:22:47 +0000450 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
451 StageTable += ItinStageString + ", // " + itostr(StageCount);
452 if (NStages > 1)
453 StageTable += "-" + itostr(StageCount + NStages - 1);
454 StageTable += "\n";
David Goodwinfac85412009-08-17 16:02:57 +0000455 // Record Itin class number.
456 ItinStageMap[ItinStageString] = FindStage = StageCount;
457 StageCount += NStages;
David Goodwinfac85412009-08-17 16:02:57 +0000458 }
459 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000460
David Goodwinfac85412009-08-17 16:02:57 +0000461 // Check to see if operand cycle already exists and create if it doesn't
462 unsigned FindOperandCycle = 0;
463 if (NOperandCycles > 0) {
Evan Cheng3881cb72010-09-29 22:42:35 +0000464 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
465 FindOperandCycle = ItinOperandMap[ItinOperandString];
David Goodwinfac85412009-08-17 16:02:57 +0000466 if (FindOperandCycle == 0) {
467 // Emit as cycle, // index
Andrew Trick23482322011-04-01 02:22:47 +0000468 OperandCycleTable += ItinOperandCycleString + ", // ";
469 std::string OperandIdxComment = itostr(OperandCycleCount);
470 if (NOperandCycles > 1)
471 OperandIdxComment += "-"
472 + itostr(OperandCycleCount + NOperandCycles - 1);
473 OperandCycleTable += OperandIdxComment + "\n";
David Goodwinfac85412009-08-17 16:02:57 +0000474 // Record Itin class number.
Andrew Trickda96cf22011-04-01 01:56:55 +0000475 ItinOperandMap[ItinOperandCycleString] =
David Goodwinfac85412009-08-17 16:02:57 +0000476 FindOperandCycle = OperandCycleCount;
Evan Cheng63d66ee2010-09-28 23:50:49 +0000477 // Emit as bypass, // index
Andrew Trick23482322011-04-01 02:22:47 +0000478 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
David Goodwinfac85412009-08-17 16:02:57 +0000479 OperandCycleCount += NOperandCycles;
David Goodwinfac85412009-08-17 16:02:57 +0000480 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000481 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000482
Evan Cheng5f54ce32010-09-09 18:18:55 +0000483 // Set up itinerary as location and location + stage count
Andrew Trick2661b412012-07-07 04:00:00 +0000484 int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
Evan Cheng5f54ce32010-09-09 18:18:55 +0000485 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
486 FindOperandCycle,
487 FindOperandCycle + NOperandCycles};
488
Jim Laskey908ae272005-10-28 15:20:43 +0000489 // Inject - empty slots will be 0, 0
Andrew Trick2661b412012-07-07 04:00:00 +0000490 ItinList[SchedClassIdx] = Intinerary;
Jim Laskey0d841e02005-10-27 19:47:21 +0000491 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000492 }
Evan Cheng63d66ee2010-09-28 23:50:49 +0000493
Jim Laskey7f39c142005-11-03 22:47:41 +0000494 // Closing stage
Andrew Trick2661b412012-07-07 04:00:00 +0000495 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
David Goodwinfac85412009-08-17 16:02:57 +0000496 StageTable += "};\n";
497
498 // Closing operand cycles
Andrew Trick2661b412012-07-07 04:00:00 +0000499 OperandCycleTable += " 0 // End operand cycles\n";
David Goodwinfac85412009-08-17 16:02:57 +0000500 OperandCycleTable += "};\n";
501
Andrew Trick2661b412012-07-07 04:00:00 +0000502 BypassTable += " 0 // End bypass tables\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000503 BypassTable += "};\n";
504
David Goodwinfac85412009-08-17 16:02:57 +0000505 // Emit tables.
506 OS << StageTable;
507 OS << OperandCycleTable;
Evan Cheng63d66ee2010-09-28 23:50:49 +0000508 OS << BypassTable;
Jim Laskey0d841e02005-10-27 19:47:21 +0000509}
510
Andrew Trick2661b412012-07-07 04:00:00 +0000511//
512// EmitProcessorData - Generate data for processor itineraries that were
513// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
514// Itineraries for each processor. The Itinerary lists are indexed on
515// CodeGenSchedClass::Index.
516//
517void SubtargetEmitter::
518EmitItineraries(raw_ostream &OS,
519 std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
520
Andrew Trickcb941922012-07-09 20:43:03 +0000521 // Multiple processor models may share an itinerary record. Emit it once.
522 SmallPtrSet<Record*, 8> ItinsDefSet;
523
Andrew Trick2661b412012-07-07 04:00:00 +0000524 // For each processor's machine model
525 std::vector<std::vector<InstrItinerary> >::iterator
526 ProcItinListsIter = ProcItinLists.begin();
527 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
Andrew Trick48605c32012-09-15 00:19:57 +0000528 PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
Andrew Trickcb941922012-07-09 20:43:03 +0000529
Andrew Trick2661b412012-07-07 04:00:00 +0000530 Record *ItinsDef = PI->ItinsDef;
Andrew Trickcb941922012-07-09 20:43:03 +0000531 if (!ItinsDefSet.insert(ItinsDef))
532 continue;
Andrew Trick2661b412012-07-07 04:00:00 +0000533
534 // Get processor itinerary name
535 const std::string &Name = ItinsDef->getName();
536
537 // Get the itinerary list for the processor.
538 assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
Andrew Trick48605c32012-09-15 00:19:57 +0000539 std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
Andrew Trick2661b412012-07-07 04:00:00 +0000540
541 OS << "\n";
542 OS << "static const llvm::InstrItinerary ";
543 if (ItinList.empty()) {
544 OS << '*' << Name << " = 0;\n";
545 continue;
546 }
547
548 // Begin processor itinerary table
549 OS << Name << "[] = {\n";
550
551 // For each itinerary class in CodeGenSchedClass::Index order.
552 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
553 InstrItinerary &Intinerary = ItinList[j];
554
555 // Emit Itinerary in the form of
556 // { firstStage, lastStage, firstCycle, lastCycle } // index
557 OS << " { " <<
558 Intinerary.NumMicroOps << ", " <<
559 Intinerary.FirstStage << ", " <<
560 Intinerary.LastStage << ", " <<
561 Intinerary.FirstOperandCycle << ", " <<
562 Intinerary.LastOperandCycle << " }" <<
563 ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
564 }
565 // End processor itinerary table
566 OS << " { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
567 OS << "};\n";
568 }
569}
570
Sylvestre Ledruc8e41c52012-07-23 08:51:15 +0000571// Emit either the value defined in the TableGen Record, or the default
Andrew Trick2661b412012-07-07 04:00:00 +0000572// value defined in the C++ header. The Record is null if the processor does not
573// define a model.
574void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
Andrew Trickfc992992012-06-05 03:44:40 +0000575 const char *Name, char Separator) {
576 OS << " ";
Andrew Trick2661b412012-07-07 04:00:00 +0000577 int V = R ? R->getValueAsInt(Name) : -1;
Andrew Trickfc992992012-06-05 03:44:40 +0000578 if (V >= 0)
579 OS << V << Separator << " // " << Name;
580 else
Andrew Trick2661b412012-07-07 04:00:00 +0000581 OS << "MCSchedModel::Default" << Name << Separator;
Andrew Trickfc992992012-06-05 03:44:40 +0000582 OS << '\n';
583}
584
Andrew Trick40096d22012-09-17 22:18:45 +0000585void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
586 raw_ostream &OS) {
587 char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
588
589 OS << "\n// {Name, NumUnits, SuperIdx}\n";
590 OS << "static const llvm::MCProcResourceDesc "
591 << ProcModel.ModelName << "ProcResources" << "[] = {\n"
592 << " {DBGFIELD(\"InvalidUnit\") 0, 0}" << Sep << "\n";
593
594 for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
595 Record *PRDef = ProcModel.ProcResourceDefs[i];
596
597 // Find the SuperIdx
598 unsigned SuperIdx = 0;
599 Record *SuperDef = 0;
600 if (PRDef->getValueInit("Super")->isComplete()) {
601 SuperDef =
602 SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
603 SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
604 }
605 // Emit the ProcResourceDesc
606 if (i+1 == e)
607 Sep = ' ';
608 OS << " {DBGFIELD(\"" << PRDef->getName() << "\") ";
609 if (PRDef->getName().size() < 15)
610 OS.indent(15 - PRDef->getName().size());
611 OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx
612 << "}" << Sep << " // #" << i+1;
613 if (SuperDef)
614 OS << ", Super=" << SuperDef->getName();
615 OS << "\n";
616 }
617 OS << "};\n";
618}
619
Andrew Trick2661b412012-07-07 04:00:00 +0000620void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
621 // For each processor model.
622 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
623 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
Andrew Trick40096d22012-09-17 22:18:45 +0000624 // Emit processor resource table.
625 if (PI->hasInstrSchedModel())
626 EmitProcessorResources(*PI, OS);
627 else if(!PI->ProcResourceDefs.empty())
628 throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
629 "ProcResources without defining either WriteResourcesList "
630 "or ItinResources");
631
Andrew Trickfc992992012-06-05 03:44:40 +0000632 // Begin processor itinerary properties
633 OS << "\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000634 OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
635 EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
636 EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
637 EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
638 EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
Andrew Trickd43b5c92012-08-08 02:44:16 +0000639 EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
Andrew Trick2661b412012-07-07 04:00:00 +0000640 if (SchedModels.hasItineraryClasses())
Andrew Trick40096d22012-09-17 22:18:45 +0000641 OS << " " << PI->ItinsDef->getName() << ");\n";
Andrew Trickd85934b2012-06-22 03:58:51 +0000642 else
Andrew Trick40096d22012-09-17 22:18:45 +0000643 OS << " 0); // No Itinerary\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000644 }
Jim Laskey10b1dd92005-10-31 17:16:01 +0000645}
646
647//
648// EmitProcessorLookup - generate cpu name to itinerary lookup table.
649//
Daniel Dunbar1a551802009-07-03 00:10:29 +0000650void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
Jim Laskey10b1dd92005-10-31 17:16:01 +0000651 // Gather and sort processor information
652 std::vector<Record*> ProcessorList =
653 Records.getAllDerivedDefinitions("Processor");
Duraid Madina42d24c72005-12-30 14:56:37 +0000654 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
Jim Laskey10b1dd92005-10-31 17:16:01 +0000655
656 // Begin processor table
657 OS << "\n";
658 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000659 << "extern const llvm::SubtargetInfoKV "
Andrew Trick2661b412012-07-07 04:00:00 +0000660 << Target << "ProcSchedKV[] = {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000661
Jim Laskey10b1dd92005-10-31 17:16:01 +0000662 // For each processor
663 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
664 // Next processor
665 Record *Processor = ProcessorList[i];
666
Bill Wendling4222d802007-05-04 20:38:40 +0000667 const std::string &Name = Processor->getValueAsString("Name");
Andrew Trick2661b412012-07-07 04:00:00 +0000668 const std::string &ProcModelName =
Andrew Trick48605c32012-09-15 00:19:57 +0000669 SchedModels.getModelForProc(Processor).ModelName;
Andrew Trickda96cf22011-04-01 01:56:55 +0000670
Jim Laskey10b1dd92005-10-31 17:16:01 +0000671 // Emit as { "cpu", procinit },
Andrew Trick40096d22012-09-17 22:18:45 +0000672 OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
Andrew Trickda96cf22011-04-01 01:56:55 +0000673
Jim Laskey10b1dd92005-10-31 17:16:01 +0000674 // Depending on ''if more in the list'' emit comma
675 if (++i < N) OS << ",";
Andrew Trickda96cf22011-04-01 01:56:55 +0000676
Jim Laskey10b1dd92005-10-31 17:16:01 +0000677 OS << "\n";
678 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000679
Jim Laskey10b1dd92005-10-31 17:16:01 +0000680 // End processor table
681 OS << "};\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000682}
683
684//
Andrew Trick2661b412012-07-07 04:00:00 +0000685// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
Jim Laskey0d841e02005-10-27 19:47:21 +0000686//
Andrew Trick2661b412012-07-07 04:00:00 +0000687void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
Andrew Trick40096d22012-09-17 22:18:45 +0000688 OS << "#ifdef DBGFIELD\n"
689 << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
690 << "#endif\n"
691 << "#ifndef NDEBUG\n"
692 << "#define DBGFIELD(x) x,\n"
693 << "#else\n"
694 << "#define DBGFIELD(x)\n"
695 << "#endif\n";
696
Andrew Trick2661b412012-07-07 04:00:00 +0000697 if (SchedModels.hasItineraryClasses()) {
698 std::vector<std::vector<InstrItinerary> > ProcItinLists;
Jim Laskey6cee6302005-11-01 20:06:59 +0000699 // Emit the stage data
Andrew Trick2661b412012-07-07 04:00:00 +0000700 EmitStageAndOperandCycleData(OS, ProcItinLists);
701 EmitItineraries(OS, ProcItinLists);
Jim Laskey6cee6302005-11-01 20:06:59 +0000702 }
Andrew Trick40096d22012-09-17 22:18:45 +0000703
Andrew Trick2661b412012-07-07 04:00:00 +0000704 // Emit the processor machine model
705 EmitProcessorModels(OS);
706 // Emit the processor lookup data
707 EmitProcessorLookup(OS);
Andrew Trick40096d22012-09-17 22:18:45 +0000708
709 OS << "#undef DBGFIELD";
Jim Laskey0d841e02005-10-27 19:47:21 +0000710}
711
712//
Jim Laskey581a8f72005-10-26 17:30:34 +0000713// ParseFeaturesFunction - Produces a subtarget specific function for parsing
714// the subtarget features string.
715//
Evan Cheng94214702011-07-01 20:45:01 +0000716void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
717 unsigned NumFeatures,
718 unsigned NumProcs) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000719 std::vector<Record*> Features =
720 Records.getAllDerivedDefinitions("SubtargetFeature");
Duraid Madina42d24c72005-12-30 14:56:37 +0000721 std::sort(Features.begin(), Features.end(), LessRecord());
Jim Laskey581a8f72005-10-26 17:30:34 +0000722
Andrew Trickda96cf22011-04-01 01:56:55 +0000723 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
724 << "// subtarget options.\n"
Evan Cheng276365d2011-06-30 01:53:36 +0000725 << "void llvm::";
Jim Laskey581a8f72005-10-26 17:30:34 +0000726 OS << Target;
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000727 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
David Greenef0fd3af2010-01-05 17:47:41 +0000728 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
Hal Finkel3f696e52012-06-12 04:21:36 +0000729 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
Evan Cheng94214702011-07-01 20:45:01 +0000730
731 if (Features.empty()) {
732 OS << "}\n";
733 return;
734 }
735
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000736 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
Bill Wendling4222d802007-05-04 20:38:40 +0000737
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000738 for (unsigned i = 0; i < Features.size(); i++) {
739 // Next record
740 Record *R = Features[i];
Bill Wendling4222d802007-05-04 20:38:40 +0000741 const std::string &Instance = R->getName();
742 const std::string &Value = R->getValueAsString("Value");
743 const std::string &Attribute = R->getValueAsString("Attribute");
Evan Cheng19c95502006-01-27 08:09:42 +0000744
Dale Johannesendb01c8b2008-02-14 23:35:16 +0000745 if (Value=="true" || Value=="false")
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000746 OS << " if ((Bits & " << Target << "::"
747 << Instance << ") != 0) "
Dale Johannesendb01c8b2008-02-14 23:35:16 +0000748 << Attribute << " = " << Value << ";\n";
749 else
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000750 OS << " if ((Bits & " << Target << "::"
751 << Instance << ") != 0 && "
Evan Cheng94214702011-07-01 20:45:01 +0000752 << Attribute << " < " << Value << ") "
753 << Attribute << " = " << Value << ";\n";
Jim Laskey6cee6302005-11-01 20:06:59 +0000754 }
Anton Korobeynikov41a02432009-05-23 19:50:50 +0000755
Evan Cheng276365d2011-06-30 01:53:36 +0000756 OS << "}\n";
Jim Laskey581a8f72005-10-26 17:30:34 +0000757}
758
Anton Korobeynikov41a02432009-05-23 19:50:50 +0000759//
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000760// SubtargetEmitter::run - Main subtarget enumeration emitter.
761//
Daniel Dunbar1a551802009-07-03 00:10:29 +0000762void SubtargetEmitter::run(raw_ostream &OS) {
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +0000763 emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000764
Evan Chengebdeeab2011-07-08 01:53:10 +0000765 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
766 OS << "#undef GET_SUBTARGETINFO_ENUM\n";
767
768 OS << "namespace llvm {\n";
769 Enumeration(OS, "SubtargetFeature", true);
770 OS << "} // End llvm namespace \n";
771 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
772
Evan Cheng94214702011-07-01 20:45:01 +0000773 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
774 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000775
Evan Cheng94214702011-07-01 20:45:01 +0000776 OS << "namespace llvm {\n";
Evan Chengc60f9b72011-07-14 20:59:42 +0000777#if 0
778 OS << "namespace {\n";
779#endif
Evan Cheng94214702011-07-01 20:45:01 +0000780 unsigned NumFeatures = FeatureKeyValues(OS);
Evan Chengc60f9b72011-07-14 20:59:42 +0000781 OS << "\n";
Evan Cheng94214702011-07-01 20:45:01 +0000782 unsigned NumProcs = CPUKeyValues(OS);
Evan Chengc60f9b72011-07-14 20:59:42 +0000783 OS << "\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000784 EmitSchedModel(OS);
Evan Chengc60f9b72011-07-14 20:59:42 +0000785 OS << "\n";
786#if 0
787 OS << "}\n";
788#endif
Evan Cheng94214702011-07-01 20:45:01 +0000789
790 // MCInstrInfo initialization routine.
791 OS << "static inline void Init" << Target
Evan Cheng59ee62d2011-07-11 03:57:24 +0000792 << "MCSubtargetInfo(MCSubtargetInfo *II, "
793 << "StringRef TT, StringRef CPU, StringRef FS) {\n";
794 OS << " II->InitMCSubtargetInfo(TT, CPU, FS, ";
Evan Cheng94214702011-07-01 20:45:01 +0000795 if (NumFeatures)
796 OS << Target << "FeatureKV, ";
797 else
798 OS << "0, ";
799 if (NumProcs)
800 OS << Target << "SubTypeKV, ";
801 else
802 OS << "0, ";
Andrew Trick2661b412012-07-07 04:00:00 +0000803 if (SchedModels.hasItineraryClasses()) {
804 OS << Target << "ProcSchedKV, "
Evan Cheng94214702011-07-01 20:45:01 +0000805 << Target << "Stages, "
806 << Target << "OperandCycles, "
Andrew Tricka11a6282012-07-07 03:59:48 +0000807 << Target << "ForwardingPaths, ";
Evan Cheng94214702011-07-01 20:45:01 +0000808 } else
809 OS << "0, 0, 0, 0, ";
810 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
811
812 OS << "} // End llvm namespace \n";
813
814 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
815
816 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
817 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
818
819 OS << "#include \"llvm/Support/Debug.h\"\n";
820 OS << "#include \"llvm/Support/raw_ostream.h\"\n";
821 ParseFeaturesFunction(OS, NumFeatures, NumProcs);
822
823 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
824
Evan Cheng5b1b44892011-07-01 21:01:15 +0000825 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
Evan Cheng94214702011-07-01 20:45:01 +0000826 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
827 OS << "#undef GET_SUBTARGETINFO_HEADER\n";
828
829 std::string ClassName = Target + "GenSubtargetInfo";
830 OS << "namespace llvm {\n";
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +0000831 OS << "class DFAPacketizer;\n";
Evan Cheng5b1b44892011-07-01 21:01:15 +0000832 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000833 << " explicit " << ClassName << "(StringRef TT, StringRef CPU, "
834 << "StringRef FS);\n"
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +0000835 << "public:\n"
Sebastian Pop464f3a32011-12-06 17:34:16 +0000836 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +0000837 << " const;\n"
Evan Cheng94214702011-07-01 20:45:01 +0000838 << "};\n";
839 OS << "} // End llvm namespace \n";
840
841 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
842
843 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
844 OS << "#undef GET_SUBTARGETINFO_CTOR\n";
845
846 OS << "namespace llvm {\n";
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000847 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
848 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000849 if (SchedModels.hasItineraryClasses()) {
850 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000851 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
852 OS << "extern const unsigned " << Target << "OperandCycles[];\n";
Andrew Tricka11a6282012-07-07 03:59:48 +0000853 OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
Evan Chengc60f9b72011-07-14 20:59:42 +0000854 }
855
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000856 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
857 << "StringRef FS)\n"
Evan Cheng5b1b44892011-07-01 21:01:15 +0000858 << " : TargetSubtargetInfo() {\n"
Evan Cheng59ee62d2011-07-11 03:57:24 +0000859 << " InitMCSubtargetInfo(TT, CPU, FS, ";
Evan Cheng94214702011-07-01 20:45:01 +0000860 if (NumFeatures)
861 OS << Target << "FeatureKV, ";
862 else
863 OS << "0, ";
864 if (NumProcs)
865 OS << Target << "SubTypeKV, ";
866 else
867 OS << "0, ";
Andrew Trick2661b412012-07-07 04:00:00 +0000868 if (SchedModels.hasItineraryClasses()) {
869 OS << Target << "ProcSchedKV, "
Evan Cheng94214702011-07-01 20:45:01 +0000870 << Target << "Stages, "
871 << Target << "OperandCycles, "
Andrew Tricka11a6282012-07-07 03:59:48 +0000872 << Target << "ForwardingPaths, ";
Evan Cheng94214702011-07-01 20:45:01 +0000873 } else
874 OS << "0, 0, 0, 0, ";
875 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
876 OS << "} // End llvm namespace \n";
877
878 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000879}
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +0000880
881namespace llvm {
882
883void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
Andrew Trick2661b412012-07-07 04:00:00 +0000884 CodeGenTarget CGTarget(RK);
885 SubtargetEmitter(RK, CGTarget).run(OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +0000886}
887
888} // End llvm namespace