blob: b3bf4aa14ce37993d16c8bd15bbb9f9fafa77ed2 [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"
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000017#include "llvm/MC/MCInstrItineraries.h"
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000018#include "llvm/Support/Debug.h"
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000019#include "llvm/TableGen/Record.h"
20#include "llvm/TableGen/TableGenBackend.h"
Jeff Cohen9489c042005-10-28 01:43:09 +000021#include <algorithm>
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000022#include <map>
23#include <string>
24#include <vector>
Jim Laskey4bb9cbb2005-10-21 19:00:04 +000025using namespace llvm;
26
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000027namespace {
28class SubtargetEmitter {
29
30 RecordKeeper &Records;
Andrew Trick2661b412012-07-07 04:00:00 +000031 CodeGenSchedModels &SchedModels;
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000032 std::string Target;
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000033
34 void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
35 unsigned FeatureKeyValues(raw_ostream &OS);
36 unsigned CPUKeyValues(raw_ostream &OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000037 void FormItineraryStageString(const std::string &Names,
38 Record *ItinData, std::string &ItinString,
39 unsigned &NStages);
40 void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
41 unsigned &NOperandCycles);
42 void FormItineraryBypassString(const std::string &Names,
43 Record *ItinData,
44 std::string &ItinString, unsigned NOperandCycles);
Andrew Trick2661b412012-07-07 04:00:00 +000045 void EmitStageAndOperandCycleData(raw_ostream &OS,
46 std::vector<std::vector<InstrItinerary> >
47 &ProcItinLists);
48 void EmitItineraries(raw_ostream &OS,
49 std::vector<std::vector<InstrItinerary> >
50 &ProcItinLists);
51 void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000052 char Separator);
Andrew Trick2661b412012-07-07 04:00:00 +000053 void EmitProcessorModels(raw_ostream &OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000054 void EmitProcessorLookup(raw_ostream &OS);
Andrew Trick2661b412012-07-07 04:00:00 +000055 void EmitSchedModel(raw_ostream &OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000056 void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
57 unsigned NumProcs);
58
59public:
Andrew Trick2661b412012-07-07 04:00:00 +000060 SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
61 Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +000062
63 void run(raw_ostream &o);
64
65};
66} // End anonymous namespace
67
Jim Laskey7dc02042005-10-22 07:59:56 +000068//
Jim Laskey581a8f72005-10-26 17:30:34 +000069// Enumeration - Emit the specified class as an enumeration.
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000070//
Daniel Dunbar1a551802009-07-03 00:10:29 +000071void SubtargetEmitter::Enumeration(raw_ostream &OS,
Jim Laskey581a8f72005-10-26 17:30:34 +000072 const char *ClassName,
73 bool isBits) {
Jim Laskey908ae272005-10-28 15:20:43 +000074 // Get all records of class and sort
Jim Laskeyf7bcde02005-10-28 21:47:29 +000075 std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
Duraid Madina42d24c72005-12-30 14:56:37 +000076 std::sort(DefList.begin(), DefList.end(), LessRecord());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +000077
Evan Chengb6a63882011-04-15 19:35:46 +000078 unsigned N = DefList.size();
Evan Cheng94214702011-07-01 20:45:01 +000079 if (N == 0)
80 return;
Evan Chengb6a63882011-04-15 19:35:46 +000081 if (N > 64) {
82 errs() << "Too many (> 64) subtarget features!\n";
83 exit(1);
84 }
85
Evan Cheng94214702011-07-01 20:45:01 +000086 OS << "namespace " << Target << " {\n";
87
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +000088 // For bit flag enumerations with more than 32 items, emit constants.
89 // Emit an enum for everything else.
90 if (isBits && N > 32) {
91 // For each record
92 for (unsigned i = 0; i < N; i++) {
93 // Next record
94 Record *Def = DefList[i];
Evan Cheng94214702011-07-01 20:45:01 +000095
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +000096 // Get and emit name and expression (1 << i)
97 OS << " const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
98 }
99 } else {
100 // Open enumeration
101 OS << "enum {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000102
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000103 // For each record
104 for (unsigned i = 0; i < N;) {
105 // Next record
106 Record *Def = DefList[i];
Andrew Trickda96cf22011-04-01 01:56:55 +0000107
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000108 // Get and emit name
109 OS << " " << Def->getName();
Jim Laskey908ae272005-10-28 15:20:43 +0000110
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000111 // If bit flags then emit expression (1 << i)
112 if (isBits) OS << " = " << " 1ULL << " << i;
Andrew Trickda96cf22011-04-01 01:56:55 +0000113
Jakob Stoklund Olesenac1ed442012-01-03 23:04:28 +0000114 // Depending on 'if more in the list' emit comma
115 if (++i < N) OS << ",";
116
117 OS << "\n";
118 }
119
120 // Close enumeration
121 OS << "};\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000122 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000123
Evan Cheng94214702011-07-01 20:45:01 +0000124 OS << "}\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000125}
126
127//
Bill Wendling4222d802007-05-04 20:38:40 +0000128// FeatureKeyValues - Emit data of all the subtarget features. Used by the
129// command line.
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000130//
Evan Cheng94214702011-07-01 20:45:01 +0000131unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
Jim Laskey908ae272005-10-28 15:20:43 +0000132 // Gather and sort all the features
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000133 std::vector<Record*> FeatureList =
134 Records.getAllDerivedDefinitions("SubtargetFeature");
Evan Cheng94214702011-07-01 20:45:01 +0000135
136 if (FeatureList.empty())
137 return 0;
138
Jim Grosbach7c9a7722008-09-11 17:05:32 +0000139 std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000140
Jim Laskey908ae272005-10-28 15:20:43 +0000141 // Begin feature table
Jim Laskey581a8f72005-10-26 17:30:34 +0000142 OS << "// Sorted (by key) array of values for CPU features.\n"
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000143 << "extern const llvm::SubtargetFeatureKV " << Target
144 << "FeatureKV[] = {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000145
Jim Laskey908ae272005-10-28 15:20:43 +0000146 // For each feature
Evan Cheng94214702011-07-01 20:45:01 +0000147 unsigned NumFeatures = 0;
Jim Laskeydbe40062006-12-12 20:55:58 +0000148 for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000149 // Next feature
150 Record *Feature = FeatureList[i];
151
Bill Wendling4222d802007-05-04 20:38:40 +0000152 const std::string &Name = Feature->getName();
153 const std::string &CommandLineName = Feature->getValueAsString("Name");
154 const std::string &Desc = Feature->getValueAsString("Desc");
Andrew Trickda96cf22011-04-01 01:56:55 +0000155
Jim Laskeydbe40062006-12-12 20:55:58 +0000156 if (CommandLineName.empty()) continue;
Andrew Trickda96cf22011-04-01 01:56:55 +0000157
Jim Grosbachda4231f2009-03-26 16:17:51 +0000158 // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000159 OS << " { "
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000160 << "\"" << CommandLineName << "\", "
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000161 << "\"" << Desc << "\", "
Evan Cheng94214702011-07-01 20:45:01 +0000162 << Target << "::" << Name << ", ";
Bill Wendling4222d802007-05-04 20:38:40 +0000163
Andrew Trickda96cf22011-04-01 01:56:55 +0000164 const std::vector<Record*> &ImpliesList =
Bill Wendling4222d802007-05-04 20:38:40 +0000165 Feature->getValueAsListOfDefs("Implies");
Andrew Trickda96cf22011-04-01 01:56:55 +0000166
Bill Wendling4222d802007-05-04 20:38:40 +0000167 if (ImpliesList.empty()) {
Evan Chengb6a63882011-04-15 19:35:46 +0000168 OS << "0ULL";
Bill Wendling4222d802007-05-04 20:38:40 +0000169 } else {
170 for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
Evan Cheng94214702011-07-01 20:45:01 +0000171 OS << Target << "::" << ImpliesList[j]->getName();
Bill Wendling4222d802007-05-04 20:38:40 +0000172 if (++j < M) OS << " | ";
173 }
174 }
175
176 OS << " }";
Evan Cheng94214702011-07-01 20:45:01 +0000177 ++NumFeatures;
Andrew Trickda96cf22011-04-01 01:56:55 +0000178
Jim Laskey10b1dd92005-10-31 17:16:01 +0000179 // Depending on 'if more in the list' emit comma
Jim Laskeydbe40062006-12-12 20:55:58 +0000180 if ((i + 1) < N) OS << ",";
Andrew Trickda96cf22011-04-01 01:56:55 +0000181
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000182 OS << "\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000183 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000184
Jim Laskey908ae272005-10-28 15:20:43 +0000185 // End feature table
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000186 OS << "};\n";
187
Evan Cheng94214702011-07-01 20:45:01 +0000188 return NumFeatures;
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000189}
190
191//
192// CPUKeyValues - Emit data of all the subtarget processors. Used by command
193// line.
194//
Evan Cheng94214702011-07-01 20:45:01 +0000195unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
Jim Laskey908ae272005-10-28 15:20:43 +0000196 // Gather and sort processor information
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000197 std::vector<Record*> ProcessorList =
198 Records.getAllDerivedDefinitions("Processor");
Duraid Madina42d24c72005-12-30 14:56:37 +0000199 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000200
Jim Laskey908ae272005-10-28 15:20:43 +0000201 // Begin processor table
Jim Laskey581a8f72005-10-26 17:30:34 +0000202 OS << "// Sorted (by key) array of values for CPU subtype.\n"
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000203 << "extern const llvm::SubtargetFeatureKV " << Target
204 << "SubTypeKV[] = {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000205
Jim Laskey908ae272005-10-28 15:20:43 +0000206 // For each processor
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000207 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
208 // Next processor
209 Record *Processor = ProcessorList[i];
210
Bill Wendling4222d802007-05-04 20:38:40 +0000211 const std::string &Name = Processor->getValueAsString("Name");
Andrew Trickda96cf22011-04-01 01:56:55 +0000212 const std::vector<Record*> &FeatureList =
Chris Lattnerb0e103d2005-10-28 22:49:02 +0000213 Processor->getValueAsListOfDefs("Features");
Andrew Trickda96cf22011-04-01 01:56:55 +0000214
Jim Laskey908ae272005-10-28 15:20:43 +0000215 // Emit as { "cpu", "description", f1 | f2 | ... fn },
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000216 OS << " { "
217 << "\"" << Name << "\", "
218 << "\"Select the " << Name << " processor\", ";
Andrew Trickda96cf22011-04-01 01:56:55 +0000219
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000220 if (FeatureList.empty()) {
Evan Chengb6a63882011-04-15 19:35:46 +0000221 OS << "0ULL";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000222 } else {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000223 for (unsigned j = 0, M = FeatureList.size(); j < M;) {
Evan Cheng94214702011-07-01 20:45:01 +0000224 OS << Target << "::" << FeatureList[j]->getName();
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000225 if (++j < M) OS << " | ";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000226 }
227 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000228
Bill Wendling4222d802007-05-04 20:38:40 +0000229 // The "0" is for the "implies" section of this data structure.
Evan Chengb6a63882011-04-15 19:35:46 +0000230 OS << ", 0ULL }";
Andrew Trickda96cf22011-04-01 01:56:55 +0000231
Jim Laskey10b1dd92005-10-31 17:16:01 +0000232 // Depending on 'if more in the list' emit comma
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000233 if (++i < N) OS << ",";
Andrew Trickda96cf22011-04-01 01:56:55 +0000234
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000235 OS << "\n";
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000236 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000237
Jim Laskey908ae272005-10-28 15:20:43 +0000238 // End processor table
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000239 OS << "};\n";
240
Evan Cheng94214702011-07-01 20:45:01 +0000241 return ProcessorList.size();
Jim Laskeyb3b1d5f2005-10-25 15:16:36 +0000242}
Jim Laskey7dc02042005-10-22 07:59:56 +0000243
Jim Laskey581a8f72005-10-26 17:30:34 +0000244//
David Goodwinfac85412009-08-17 16:02:57 +0000245// FormItineraryStageString - Compose a string containing the stage
246// data initialization for the specified itinerary. N is the number
247// of stages.
Jim Laskey0d841e02005-10-27 19:47:21 +0000248//
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000249void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
250 Record *ItinData,
David Goodwinfac85412009-08-17 16:02:57 +0000251 std::string &ItinString,
252 unsigned &NStages) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000253 // Get states list
Bill Wendling4222d802007-05-04 20:38:40 +0000254 const std::vector<Record*> &StageList =
255 ItinData->getValueAsListOfDefs("Stages");
Jim Laskey908ae272005-10-28 15:20:43 +0000256
257 // For each stage
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000258 unsigned N = NStages = StageList.size();
Christopher Lamb8dadf6b2007-04-22 09:04:24 +0000259 for (unsigned i = 0; i < N;) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000260 // Next stage
Bill Wendling4222d802007-05-04 20:38:40 +0000261 const Record *Stage = StageList[i];
Andrew Trickda96cf22011-04-01 01:56:55 +0000262
Anton Korobeynikov96085a32010-04-07 18:19:32 +0000263 // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
Jim Laskey0d841e02005-10-27 19:47:21 +0000264 int Cycles = Stage->getValueAsInt("Cycles");
Jim Laskey7f39c142005-11-03 22:47:41 +0000265 ItinString += " { " + itostr(Cycles) + ", ";
Andrew Trickda96cf22011-04-01 01:56:55 +0000266
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000267 // Get unit list
Bill Wendling4222d802007-05-04 20:38:40 +0000268 const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
Andrew Trickda96cf22011-04-01 01:56:55 +0000269
Jim Laskey908ae272005-10-28 15:20:43 +0000270 // For each unit
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000271 for (unsigned j = 0, M = UnitList.size(); j < M;) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000272 // Add name and bitwise or
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000273 ItinString += Name + "FU::" + UnitList[j]->getName();
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000274 if (++j < M) ItinString += " | ";
Jim Laskey0d841e02005-10-27 19:47:21 +0000275 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000276
David Goodwin1a8f36e2009-08-12 18:31:53 +0000277 int TimeInc = Stage->getValueAsInt("TimeInc");
278 ItinString += ", " + itostr(TimeInc);
279
Anton Korobeynikov96085a32010-04-07 18:19:32 +0000280 int Kind = Stage->getValueAsInt("Kind");
281 ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
282
Jim Laskey908ae272005-10-28 15:20:43 +0000283 // Close off stage
284 ItinString += " }";
Christopher Lamb8dadf6b2007-04-22 09:04:24 +0000285 if (++i < N) ItinString += ", ";
Jim Laskey0d841e02005-10-27 19:47:21 +0000286 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000287}
288
289//
David Goodwinfac85412009-08-17 16:02:57 +0000290// FormItineraryOperandCycleString - Compose a string containing the
291// operand cycle initialization for the specified itinerary. N is the
292// number of operands that has cycles specified.
Jim Laskey0d841e02005-10-27 19:47:21 +0000293//
David Goodwinfac85412009-08-17 16:02:57 +0000294void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
295 std::string &ItinString, unsigned &NOperandCycles) {
296 // Get operand cycle list
297 const std::vector<int64_t> &OperandCycleList =
298 ItinData->getValueAsListOfInts("OperandCycles");
299
300 // For each operand cycle
301 unsigned N = NOperandCycles = OperandCycleList.size();
302 for (unsigned i = 0; i < N;) {
303 // Next operand cycle
304 const int OCycle = OperandCycleList[i];
Andrew Trickda96cf22011-04-01 01:56:55 +0000305
David Goodwinfac85412009-08-17 16:02:57 +0000306 ItinString += " " + itostr(OCycle);
307 if (++i < N) ItinString += ", ";
308 }
309}
310
Evan Cheng63d66ee2010-09-28 23:50:49 +0000311void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
312 Record *ItinData,
313 std::string &ItinString,
314 unsigned NOperandCycles) {
315 const std::vector<Record*> &BypassList =
316 ItinData->getValueAsListOfDefs("Bypasses");
317 unsigned N = BypassList.size();
Evan Cheng3881cb72010-09-29 22:42:35 +0000318 unsigned i = 0;
319 for (; i < N;) {
Evan Cheng63d66ee2010-09-28 23:50:49 +0000320 ItinString += Name + "Bypass::" + BypassList[i]->getName();
Evan Cheng3881cb72010-09-29 22:42:35 +0000321 if (++i < NOperandCycles) ItinString += ", ";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000322 }
Evan Cheng3881cb72010-09-29 22:42:35 +0000323 for (; i < NOperandCycles;) {
Evan Cheng63d66ee2010-09-28 23:50:49 +0000324 ItinString += " 0";
Evan Cheng3881cb72010-09-29 22:42:35 +0000325 if (++i < NOperandCycles) ItinString += ", ";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000326 }
327}
328
David Goodwinfac85412009-08-17 16:02:57 +0000329//
Andrew Trick2661b412012-07-07 04:00:00 +0000330// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
331// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
332// by CodeGenSchedClass::Index.
David Goodwinfac85412009-08-17 16:02:57 +0000333//
Andrew Trick2661b412012-07-07 04:00:00 +0000334void SubtargetEmitter::
335EmitStageAndOperandCycleData(raw_ostream &OS,
336 std::vector<std::vector<InstrItinerary> >
337 &ProcItinLists) {
Jim Laskey908ae272005-10-28 15:20:43 +0000338
Andrew Trickcb941922012-07-09 20:43:03 +0000339 // Multiple processor models may share an itinerary record. Emit it once.
340 SmallPtrSet<Record*, 8> ItinsDefSet;
341
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000342 // Emit functional units for all the itineraries.
Andrew Trick2661b412012-07-07 04:00:00 +0000343 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
344 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000345
Andrew Trickcb941922012-07-09 20:43:03 +0000346 if (!ItinsDefSet.insert(PI->ItinsDef))
347 continue;
348
Andrew Trick2661b412012-07-07 04:00:00 +0000349 std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000350 if (FUs.empty())
351 continue;
352
Andrew Trick2661b412012-07-07 04:00:00 +0000353 const std::string &Name = PI->ItinsDef->getName();
354 OS << "\n// Functional units for \"" << Name << "\"\n"
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000355 << "namespace " << Name << "FU {\n";
356
357 for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
Hal Finkelb460a332012-06-22 20:27:13 +0000358 OS << " const unsigned " << FUs[j]->getName()
359 << " = 1 << " << j << ";\n";
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000360
361 OS << "}\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000362
Andrew Trick2661b412012-07-07 04:00:00 +0000363 std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
Evan Cheng3881cb72010-09-29 22:42:35 +0000364 if (BPs.size()) {
365 OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
366 << "\"\n" << "namespace " << Name << "Bypass {\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000367
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000368 OS << " const unsigned NoBypass = 0;\n";
Evan Cheng3881cb72010-09-29 22:42:35 +0000369 for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000370 OS << " const unsigned " << BPs[j]->getName()
Evan Cheng3881cb72010-09-29 22:42:35 +0000371 << " = 1 << " << j << ";\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000372
Evan Cheng3881cb72010-09-29 22:42:35 +0000373 OS << "}\n";
374 }
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000375 }
376
Jim Laskey908ae272005-10-28 15:20:43 +0000377 // Begin stages table
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000378 std::string StageTable = "\nextern const llvm::InstrStage " + Target +
379 "Stages[] = {\n";
Anton Korobeynikov96085a32010-04-07 18:19:32 +0000380 StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000381
David Goodwinfac85412009-08-17 16:02:57 +0000382 // Begin operand cycle table
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000383 std::string OperandCycleTable = "extern const unsigned " + Target +
Evan Cheng94214702011-07-01 20:45:01 +0000384 "OperandCycles[] = {\n";
David Goodwinfac85412009-08-17 16:02:57 +0000385 OperandCycleTable += " 0, // No itinerary\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000386
387 // Begin pipeline bypass table
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000388 std::string BypassTable = "extern const unsigned " + Target +
Andrew Tricka11a6282012-07-07 03:59:48 +0000389 "ForwardingPaths[] = {\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000390 BypassTable += " 0, // No itinerary\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000391
Andrew Trick2661b412012-07-07 04:00:00 +0000392 // For each Itinerary across all processors, add a unique entry to the stages,
393 // operand cycles, and pipepine bypess tables. Then add the new Itinerary
394 // object with computed offsets to the ProcItinLists result.
David Goodwinfac85412009-08-17 16:02:57 +0000395 unsigned StageCount = 1, OperandCycleCount = 1;
Evan Cheng3881cb72010-09-29 22:42:35 +0000396 std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
Andrew Trick2661b412012-07-07 04:00:00 +0000397 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
398 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
399 const CodeGenProcModel &ProcModel = *PI;
Andrew Trickda96cf22011-04-01 01:56:55 +0000400
Andrew Trick2661b412012-07-07 04:00:00 +0000401 // Add process itinerary to the list.
402 ProcItinLists.resize(ProcItinLists.size()+1);
Andrew Trickda96cf22011-04-01 01:56:55 +0000403
Andrew Trick2661b412012-07-07 04:00:00 +0000404 // If this processor defines no itineraries, then leave the itinerary list
405 // empty.
406 std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
407 if (ProcModel.ItinDefList.empty())
Andrew Trickd85934b2012-06-22 03:58:51 +0000408 continue;
Andrew Trickd85934b2012-06-22 03:58:51 +0000409
Andrew Trick2661b412012-07-07 04:00:00 +0000410 // Reserve index==0 for NoItinerary.
411 ItinList.resize(SchedModels.numItineraryClasses()+1);
412
413 const std::string &Name = ProcModel.ItinsDef->getName();
Andrew Trickda96cf22011-04-01 01:56:55 +0000414
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000415 // For each itinerary data
Andrew Trick2661b412012-07-07 04:00:00 +0000416 for (unsigned SchedClassIdx = 0,
417 SchedClassEnd = ProcModel.ItinDefList.size();
418 SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
419
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000420 // Next itinerary data
Andrew Trick2661b412012-07-07 04:00:00 +0000421 Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
Andrew Trickda96cf22011-04-01 01:56:55 +0000422
Jim Laskey908ae272005-10-28 15:20:43 +0000423 // Get string and stage count
David Goodwinfac85412009-08-17 16:02:57 +0000424 std::string ItinStageString;
Andrew Trick2661b412012-07-07 04:00:00 +0000425 unsigned NStages = 0;
426 if (ItinData)
427 FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
Jim Laskey0d841e02005-10-27 19:47:21 +0000428
David Goodwinfac85412009-08-17 16:02:57 +0000429 // Get string and operand cycle count
430 std::string ItinOperandCycleString;
Andrew Trick2661b412012-07-07 04:00:00 +0000431 unsigned NOperandCycles = 0;
Evan Cheng63d66ee2010-09-28 23:50:49 +0000432 std::string ItinBypassString;
Andrew Trick2661b412012-07-07 04:00:00 +0000433 if (ItinData) {
434 FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
435 NOperandCycles);
436
437 FormItineraryBypassString(Name, ItinData, ItinBypassString,
438 NOperandCycles);
439 }
Evan Cheng63d66ee2010-09-28 23:50:49 +0000440
David Goodwinfac85412009-08-17 16:02:57 +0000441 // Check to see if stage already exists and create if it doesn't
442 unsigned FindStage = 0;
443 if (NStages > 0) {
444 FindStage = ItinStageMap[ItinStageString];
445 if (FindStage == 0) {
Andrew Trick23482322011-04-01 02:22:47 +0000446 // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
447 StageTable += ItinStageString + ", // " + itostr(StageCount);
448 if (NStages > 1)
449 StageTable += "-" + itostr(StageCount + NStages - 1);
450 StageTable += "\n";
David Goodwinfac85412009-08-17 16:02:57 +0000451 // Record Itin class number.
452 ItinStageMap[ItinStageString] = FindStage = StageCount;
453 StageCount += NStages;
David Goodwinfac85412009-08-17 16:02:57 +0000454 }
455 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000456
David Goodwinfac85412009-08-17 16:02:57 +0000457 // Check to see if operand cycle already exists and create if it doesn't
458 unsigned FindOperandCycle = 0;
459 if (NOperandCycles > 0) {
Evan Cheng3881cb72010-09-29 22:42:35 +0000460 std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
461 FindOperandCycle = ItinOperandMap[ItinOperandString];
David Goodwinfac85412009-08-17 16:02:57 +0000462 if (FindOperandCycle == 0) {
463 // Emit as cycle, // index
Andrew Trick23482322011-04-01 02:22:47 +0000464 OperandCycleTable += ItinOperandCycleString + ", // ";
465 std::string OperandIdxComment = itostr(OperandCycleCount);
466 if (NOperandCycles > 1)
467 OperandIdxComment += "-"
468 + itostr(OperandCycleCount + NOperandCycles - 1);
469 OperandCycleTable += OperandIdxComment + "\n";
David Goodwinfac85412009-08-17 16:02:57 +0000470 // Record Itin class number.
Andrew Trickda96cf22011-04-01 01:56:55 +0000471 ItinOperandMap[ItinOperandCycleString] =
David Goodwinfac85412009-08-17 16:02:57 +0000472 FindOperandCycle = OperandCycleCount;
Evan Cheng63d66ee2010-09-28 23:50:49 +0000473 // Emit as bypass, // index
Andrew Trick23482322011-04-01 02:22:47 +0000474 BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
David Goodwinfac85412009-08-17 16:02:57 +0000475 OperandCycleCount += NOperandCycles;
David Goodwinfac85412009-08-17 16:02:57 +0000476 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000477 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000478
Evan Cheng5f54ce32010-09-09 18:18:55 +0000479 // Set up itinerary as location and location + stage count
Andrew Trick2661b412012-07-07 04:00:00 +0000480 int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
Evan Cheng5f54ce32010-09-09 18:18:55 +0000481 InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
482 FindOperandCycle,
483 FindOperandCycle + NOperandCycles};
484
Jim Laskey908ae272005-10-28 15:20:43 +0000485 // Inject - empty slots will be 0, 0
Andrew Trick2661b412012-07-07 04:00:00 +0000486 ItinList[SchedClassIdx] = Intinerary;
Jim Laskey0d841e02005-10-27 19:47:21 +0000487 }
Jim Laskey0d841e02005-10-27 19:47:21 +0000488 }
Evan Cheng63d66ee2010-09-28 23:50:49 +0000489
Jim Laskey7f39c142005-11-03 22:47:41 +0000490 // Closing stage
Andrew Trick2661b412012-07-07 04:00:00 +0000491 StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
David Goodwinfac85412009-08-17 16:02:57 +0000492 StageTable += "};\n";
493
494 // Closing operand cycles
Andrew Trick2661b412012-07-07 04:00:00 +0000495 OperandCycleTable += " 0 // End operand cycles\n";
David Goodwinfac85412009-08-17 16:02:57 +0000496 OperandCycleTable += "};\n";
497
Andrew Trick2661b412012-07-07 04:00:00 +0000498 BypassTable += " 0 // End bypass tables\n";
Evan Cheng63d66ee2010-09-28 23:50:49 +0000499 BypassTable += "};\n";
500
David Goodwinfac85412009-08-17 16:02:57 +0000501 // Emit tables.
502 OS << StageTable;
503 OS << OperandCycleTable;
Evan Cheng63d66ee2010-09-28 23:50:49 +0000504 OS << BypassTable;
Jim Laskey0d841e02005-10-27 19:47:21 +0000505}
506
Andrew Trick2661b412012-07-07 04:00:00 +0000507//
508// EmitProcessorData - Generate data for processor itineraries that were
509// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
510// Itineraries for each processor. The Itinerary lists are indexed on
511// CodeGenSchedClass::Index.
512//
513void SubtargetEmitter::
514EmitItineraries(raw_ostream &OS,
515 std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
516
Andrew Trickcb941922012-07-09 20:43:03 +0000517 // Multiple processor models may share an itinerary record. Emit it once.
518 SmallPtrSet<Record*, 8> ItinsDefSet;
519
Andrew Trick2661b412012-07-07 04:00:00 +0000520 // For each processor's machine model
521 std::vector<std::vector<InstrItinerary> >::iterator
522 ProcItinListsIter = ProcItinLists.begin();
523 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
524 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
Andrew Trickcb941922012-07-09 20:43:03 +0000525
Andrew Trick2661b412012-07-07 04:00:00 +0000526 Record *ItinsDef = PI->ItinsDef;
Andrew Trickcb941922012-07-09 20:43:03 +0000527 if (!ItinsDefSet.insert(ItinsDef))
528 continue;
Andrew Trick2661b412012-07-07 04:00:00 +0000529
530 // Get processor itinerary name
531 const std::string &Name = ItinsDef->getName();
532
533 // Get the itinerary list for the processor.
534 assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
535 std::vector<InstrItinerary> &ItinList = *ProcItinListsIter++;
536
537 OS << "\n";
538 OS << "static const llvm::InstrItinerary ";
539 if (ItinList.empty()) {
540 OS << '*' << Name << " = 0;\n";
541 continue;
542 }
543
544 // Begin processor itinerary table
545 OS << Name << "[] = {\n";
546
547 // For each itinerary class in CodeGenSchedClass::Index order.
548 for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
549 InstrItinerary &Intinerary = ItinList[j];
550
551 // Emit Itinerary in the form of
552 // { firstStage, lastStage, firstCycle, lastCycle } // index
553 OS << " { " <<
554 Intinerary.NumMicroOps << ", " <<
555 Intinerary.FirstStage << ", " <<
556 Intinerary.LastStage << ", " <<
557 Intinerary.FirstOperandCycle << ", " <<
558 Intinerary.LastOperandCycle << " }" <<
559 ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
560 }
561 // End processor itinerary table
562 OS << " { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
563 OS << "};\n";
564 }
565}
566
Sylvestre Ledruc8e41c52012-07-23 08:51:15 +0000567// Emit either the value defined in the TableGen Record, or the default
Andrew Trick2661b412012-07-07 04:00:00 +0000568// value defined in the C++ header. The Record is null if the processor does not
569// define a model.
570void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
Andrew Trickfc992992012-06-05 03:44:40 +0000571 const char *Name, char Separator) {
572 OS << " ";
Andrew Trick2661b412012-07-07 04:00:00 +0000573 int V = R ? R->getValueAsInt(Name) : -1;
Andrew Trickfc992992012-06-05 03:44:40 +0000574 if (V >= 0)
575 OS << V << Separator << " // " << Name;
576 else
Andrew Trick2661b412012-07-07 04:00:00 +0000577 OS << "MCSchedModel::Default" << Name << Separator;
Andrew Trickfc992992012-06-05 03:44:40 +0000578 OS << '\n';
579}
580
Andrew Trick2661b412012-07-07 04:00:00 +0000581void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
582 // For each processor model.
583 for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
584 PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
Jim Laskey908ae272005-10-28 15:20:43 +0000585 // Skip default
Andrew Trickfc992992012-06-05 03:44:40 +0000586 // Begin processor itinerary properties
587 OS << "\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000588 OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
589 EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
590 EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
591 EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
592 EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
593 if (SchedModels.hasItineraryClasses())
594 OS << " " << PI->ItinsDef->getName();
Andrew Trickd85934b2012-06-22 03:58:51 +0000595 else
Andrew Trick2661b412012-07-07 04:00:00 +0000596 OS << " 0";
597 OS << ");\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000598 }
Jim Laskey10b1dd92005-10-31 17:16:01 +0000599}
600
601//
602// EmitProcessorLookup - generate cpu name to itinerary lookup table.
603//
Daniel Dunbar1a551802009-07-03 00:10:29 +0000604void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
Jim Laskey10b1dd92005-10-31 17:16:01 +0000605 // Gather and sort processor information
606 std::vector<Record*> ProcessorList =
607 Records.getAllDerivedDefinitions("Processor");
Duraid Madina42d24c72005-12-30 14:56:37 +0000608 std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
Jim Laskey10b1dd92005-10-31 17:16:01 +0000609
610 // Begin processor table
611 OS << "\n";
612 OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000613 << "extern const llvm::SubtargetInfoKV "
Andrew Trick2661b412012-07-07 04:00:00 +0000614 << Target << "ProcSchedKV[] = {\n";
Andrew Trickda96cf22011-04-01 01:56:55 +0000615
Jim Laskey10b1dd92005-10-31 17:16:01 +0000616 // For each processor
617 for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
618 // Next processor
619 Record *Processor = ProcessorList[i];
620
Bill Wendling4222d802007-05-04 20:38:40 +0000621 const std::string &Name = Processor->getValueAsString("Name");
Andrew Trick2661b412012-07-07 04:00:00 +0000622 const std::string &ProcModelName =
623 SchedModels.getProcModel(Processor).ModelName;
Andrew Trickda96cf22011-04-01 01:56:55 +0000624
Jim Laskey10b1dd92005-10-31 17:16:01 +0000625 // Emit as { "cpu", procinit },
626 OS << " { "
627 << "\"" << Name << "\", "
Andrew Trick2661b412012-07-07 04:00:00 +0000628 << "(void *)&" << ProcModelName;
Andrew Trickda96cf22011-04-01 01:56:55 +0000629
Jim Laskey10b1dd92005-10-31 17:16:01 +0000630 OS << " }";
Andrew Trickda96cf22011-04-01 01:56:55 +0000631
Jim Laskey10b1dd92005-10-31 17:16:01 +0000632 // Depending on ''if more in the list'' emit comma
633 if (++i < N) OS << ",";
Andrew Trickda96cf22011-04-01 01:56:55 +0000634
Jim Laskey10b1dd92005-10-31 17:16:01 +0000635 OS << "\n";
636 }
Andrew Trickda96cf22011-04-01 01:56:55 +0000637
Jim Laskey10b1dd92005-10-31 17:16:01 +0000638 // End processor table
639 OS << "};\n";
Jim Laskey0d841e02005-10-27 19:47:21 +0000640}
641
642//
Andrew Trick2661b412012-07-07 04:00:00 +0000643// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
Jim Laskey0d841e02005-10-27 19:47:21 +0000644//
Andrew Trick2661b412012-07-07 04:00:00 +0000645void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
646 if (SchedModels.hasItineraryClasses()) {
647 std::vector<std::vector<InstrItinerary> > ProcItinLists;
Jim Laskey6cee6302005-11-01 20:06:59 +0000648 // Emit the stage data
Andrew Trick2661b412012-07-07 04:00:00 +0000649 EmitStageAndOperandCycleData(OS, ProcItinLists);
650 EmitItineraries(OS, ProcItinLists);
Jim Laskey6cee6302005-11-01 20:06:59 +0000651 }
Andrew Trick2661b412012-07-07 04:00:00 +0000652 // Emit the processor machine model
653 EmitProcessorModels(OS);
654 // Emit the processor lookup data
655 EmitProcessorLookup(OS);
Jim Laskey0d841e02005-10-27 19:47:21 +0000656}
657
658//
Jim Laskey581a8f72005-10-26 17:30:34 +0000659// ParseFeaturesFunction - Produces a subtarget specific function for parsing
660// the subtarget features string.
661//
Evan Cheng94214702011-07-01 20:45:01 +0000662void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
663 unsigned NumFeatures,
664 unsigned NumProcs) {
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000665 std::vector<Record*> Features =
666 Records.getAllDerivedDefinitions("SubtargetFeature");
Duraid Madina42d24c72005-12-30 14:56:37 +0000667 std::sort(Features.begin(), Features.end(), LessRecord());
Jim Laskey581a8f72005-10-26 17:30:34 +0000668
Andrew Trickda96cf22011-04-01 01:56:55 +0000669 OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
670 << "// subtarget options.\n"
Evan Cheng276365d2011-06-30 01:53:36 +0000671 << "void llvm::";
Jim Laskey581a8f72005-10-26 17:30:34 +0000672 OS << Target;
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000673 OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
David Greenef0fd3af2010-01-05 17:47:41 +0000674 << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
Hal Finkel3f696e52012-06-12 04:21:36 +0000675 << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
Evan Cheng94214702011-07-01 20:45:01 +0000676
677 if (Features.empty()) {
678 OS << "}\n";
679 return;
680 }
681
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000682 OS << " uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
Bill Wendling4222d802007-05-04 20:38:40 +0000683
Jim Laskeyf7bcde02005-10-28 21:47:29 +0000684 for (unsigned i = 0; i < Features.size(); i++) {
685 // Next record
686 Record *R = Features[i];
Bill Wendling4222d802007-05-04 20:38:40 +0000687 const std::string &Instance = R->getName();
688 const std::string &Value = R->getValueAsString("Value");
689 const std::string &Attribute = R->getValueAsString("Attribute");
Evan Cheng19c95502006-01-27 08:09:42 +0000690
Dale Johannesendb01c8b2008-02-14 23:35:16 +0000691 if (Value=="true" || Value=="false")
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000692 OS << " if ((Bits & " << Target << "::"
693 << Instance << ") != 0) "
Dale Johannesendb01c8b2008-02-14 23:35:16 +0000694 << Attribute << " = " << Value << ";\n";
695 else
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000696 OS << " if ((Bits & " << Target << "::"
697 << Instance << ") != 0 && "
Evan Cheng94214702011-07-01 20:45:01 +0000698 << Attribute << " < " << Value << ") "
699 << Attribute << " = " << Value << ";\n";
Jim Laskey6cee6302005-11-01 20:06:59 +0000700 }
Anton Korobeynikov41a02432009-05-23 19:50:50 +0000701
Evan Cheng276365d2011-06-30 01:53:36 +0000702 OS << "}\n";
Jim Laskey581a8f72005-10-26 17:30:34 +0000703}
704
Anton Korobeynikov41a02432009-05-23 19:50:50 +0000705//
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000706// SubtargetEmitter::run - Main subtarget enumeration emitter.
707//
Daniel Dunbar1a551802009-07-03 00:10:29 +0000708void SubtargetEmitter::run(raw_ostream &OS) {
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +0000709 emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000710
Evan Chengebdeeab2011-07-08 01:53:10 +0000711 OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
712 OS << "#undef GET_SUBTARGETINFO_ENUM\n";
713
714 OS << "namespace llvm {\n";
715 Enumeration(OS, "SubtargetFeature", true);
716 OS << "} // End llvm namespace \n";
717 OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
718
Evan Cheng94214702011-07-01 20:45:01 +0000719 OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
720 OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
Anton Korobeynikov928eb492010-04-18 20:31:01 +0000721
Evan Cheng94214702011-07-01 20:45:01 +0000722 OS << "namespace llvm {\n";
Evan Chengc60f9b72011-07-14 20:59:42 +0000723#if 0
724 OS << "namespace {\n";
725#endif
Evan Cheng94214702011-07-01 20:45:01 +0000726 unsigned NumFeatures = FeatureKeyValues(OS);
Evan Chengc60f9b72011-07-14 20:59:42 +0000727 OS << "\n";
Evan Cheng94214702011-07-01 20:45:01 +0000728 unsigned NumProcs = CPUKeyValues(OS);
Evan Chengc60f9b72011-07-14 20:59:42 +0000729 OS << "\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000730 EmitSchedModel(OS);
Evan Chengc60f9b72011-07-14 20:59:42 +0000731 OS << "\n";
732#if 0
733 OS << "}\n";
734#endif
Evan Cheng94214702011-07-01 20:45:01 +0000735
736 // MCInstrInfo initialization routine.
737 OS << "static inline void Init" << Target
Evan Cheng59ee62d2011-07-11 03:57:24 +0000738 << "MCSubtargetInfo(MCSubtargetInfo *II, "
739 << "StringRef TT, StringRef CPU, StringRef FS) {\n";
740 OS << " II->InitMCSubtargetInfo(TT, CPU, FS, ";
Evan Cheng94214702011-07-01 20:45:01 +0000741 if (NumFeatures)
742 OS << Target << "FeatureKV, ";
743 else
744 OS << "0, ";
745 if (NumProcs)
746 OS << Target << "SubTypeKV, ";
747 else
748 OS << "0, ";
Andrew Trick2661b412012-07-07 04:00:00 +0000749 if (SchedModels.hasItineraryClasses()) {
750 OS << Target << "ProcSchedKV, "
Evan Cheng94214702011-07-01 20:45:01 +0000751 << Target << "Stages, "
752 << Target << "OperandCycles, "
Andrew Tricka11a6282012-07-07 03:59:48 +0000753 << Target << "ForwardingPaths, ";
Evan Cheng94214702011-07-01 20:45:01 +0000754 } else
755 OS << "0, 0, 0, 0, ";
756 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
757
758 OS << "} // End llvm namespace \n";
759
760 OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
761
762 OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
763 OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
764
765 OS << "#include \"llvm/Support/Debug.h\"\n";
766 OS << "#include \"llvm/Support/raw_ostream.h\"\n";
767 ParseFeaturesFunction(OS, NumFeatures, NumProcs);
768
769 OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
770
Evan Cheng5b1b44892011-07-01 21:01:15 +0000771 // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
Evan Cheng94214702011-07-01 20:45:01 +0000772 OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
773 OS << "#undef GET_SUBTARGETINFO_HEADER\n";
774
775 std::string ClassName = Target + "GenSubtargetInfo";
776 OS << "namespace llvm {\n";
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +0000777 OS << "class DFAPacketizer;\n";
Evan Cheng5b1b44892011-07-01 21:01:15 +0000778 OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000779 << " explicit " << ClassName << "(StringRef TT, StringRef CPU, "
780 << "StringRef FS);\n"
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +0000781 << "public:\n"
Sebastian Pop464f3a32011-12-06 17:34:16 +0000782 << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
Anshuman Dasguptadc81e5d2011-12-01 21:10:21 +0000783 << " const;\n"
Evan Cheng94214702011-07-01 20:45:01 +0000784 << "};\n";
785 OS << "} // End llvm namespace \n";
786
787 OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
788
789 OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
790 OS << "#undef GET_SUBTARGETINFO_CTOR\n";
791
792 OS << "namespace llvm {\n";
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000793 OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
794 OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
Andrew Trick2661b412012-07-07 04:00:00 +0000795 if (SchedModels.hasItineraryClasses()) {
796 OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
Benjamin Kramer1a2f9882011-10-22 16:50:00 +0000797 OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
798 OS << "extern const unsigned " << Target << "OperandCycles[];\n";
Andrew Tricka11a6282012-07-07 03:59:48 +0000799 OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
Evan Chengc60f9b72011-07-14 20:59:42 +0000800 }
801
Evan Cheng0ddff1b2011-07-07 07:07:08 +0000802 OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
803 << "StringRef FS)\n"
Evan Cheng5b1b44892011-07-01 21:01:15 +0000804 << " : TargetSubtargetInfo() {\n"
Evan Cheng59ee62d2011-07-11 03:57:24 +0000805 << " InitMCSubtargetInfo(TT, CPU, FS, ";
Evan Cheng94214702011-07-01 20:45:01 +0000806 if (NumFeatures)
807 OS << Target << "FeatureKV, ";
808 else
809 OS << "0, ";
810 if (NumProcs)
811 OS << Target << "SubTypeKV, ";
812 else
813 OS << "0, ";
Andrew Trick2661b412012-07-07 04:00:00 +0000814 if (SchedModels.hasItineraryClasses()) {
815 OS << Target << "ProcSchedKV, "
Evan Cheng94214702011-07-01 20:45:01 +0000816 << Target << "Stages, "
817 << Target << "OperandCycles, "
Andrew Tricka11a6282012-07-07 03:59:48 +0000818 << Target << "ForwardingPaths, ";
Evan Cheng94214702011-07-01 20:45:01 +0000819 } else
820 OS << "0, 0, 0, 0, ";
821 OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
822 OS << "} // End llvm namespace \n";
823
824 OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
Jim Laskey4bb9cbb2005-10-21 19:00:04 +0000825}
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +0000826
827namespace llvm {
828
829void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
Andrew Trick2661b412012-07-07 04:00:00 +0000830 CodeGenTarget CGTarget(RK);
831 SubtargetEmitter(RK, CGTarget).run(OS);
Jakob Stoklund Olesen6f36fa92012-06-11 15:37:55 +0000832}
833
834} // End llvm namespace