SubtargetEmitter.cpp revision 928eb49cae286c95dceecf4442997dd561c6e3b7
1//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This tablegen backend emits subtarget enumerations.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SubtargetEmitter.h"
15#include "CodeGenTarget.h"
16#include "Record.h"
17#include "llvm/ADT/StringExtras.h"
18#include "llvm/Support/Debug.h"
19#include <algorithm>
20using namespace llvm;
21
22//
23// Enumeration - Emit the specified class as an enumeration.
24//
25void SubtargetEmitter::Enumeration(raw_ostream &OS,
26                                   const char *ClassName,
27                                   bool isBits) {
28  // Get all records of class and sort
29  std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
30  std::sort(DefList.begin(), DefList.end(), LessRecord());
31
32  // Open enumeration
33  OS << "enum {\n";
34
35  // For each record
36  for (unsigned i = 0, N = DefList.size(); i < N;) {
37    // Next record
38    Record *Def = DefList[i];
39
40    // Get and emit name
41    OS << "  " << Def->getName();
42
43    // If bit flags then emit expression (1 << i)
44    if (isBits)  OS << " = " << " 1 << " << i;
45
46    // Depending on 'if more in the list' emit comma
47    if (++i < N) OS << ",";
48
49    OS << "\n";
50  }
51
52  // Close enumeration
53  OS << "};\n";
54}
55
56//
57// FeatureKeyValues - Emit data of all the subtarget features.  Used by the
58// command line.
59//
60void SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
61  // Gather and sort all the features
62  std::vector<Record*> FeatureList =
63                           Records.getAllDerivedDefinitions("SubtargetFeature");
64  std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
65
66  // Begin feature table
67  OS << "// Sorted (by key) array of values for CPU features.\n"
68     << "static const llvm::SubtargetFeatureKV FeatureKV[] = {\n";
69
70  // For each feature
71  for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
72    // Next feature
73    Record *Feature = FeatureList[i];
74
75    const std::string &Name = Feature->getName();
76    const std::string &CommandLineName = Feature->getValueAsString("Name");
77    const std::string &Desc = Feature->getValueAsString("Desc");
78
79    if (CommandLineName.empty()) continue;
80
81    // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
82    OS << "  { "
83       << "\"" << CommandLineName << "\", "
84       << "\"" << Desc << "\", "
85       << Name << ", ";
86
87    const std::vector<Record*> &ImpliesList =
88      Feature->getValueAsListOfDefs("Implies");
89
90    if (ImpliesList.empty()) {
91      OS << "0";
92    } else {
93      for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
94        OS << ImpliesList[j]->getName();
95        if (++j < M) OS << " | ";
96      }
97    }
98
99    OS << " }";
100
101    // Depending on 'if more in the list' emit comma
102    if ((i + 1) < N) OS << ",";
103
104    OS << "\n";
105  }
106
107  // End feature table
108  OS << "};\n";
109
110  // Emit size of table
111  OS<<"\nenum {\n";
112  OS<<"  FeatureKVSize = sizeof(FeatureKV)/sizeof(llvm::SubtargetFeatureKV)\n";
113  OS<<"};\n";
114}
115
116//
117// CPUKeyValues - Emit data of all the subtarget processors.  Used by command
118// line.
119//
120void SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
121  // Gather and sort processor information
122  std::vector<Record*> ProcessorList =
123                          Records.getAllDerivedDefinitions("Processor");
124  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
125
126  // Begin processor table
127  OS << "// Sorted (by key) array of values for CPU subtype.\n"
128     << "static const llvm::SubtargetFeatureKV SubTypeKV[] = {\n";
129
130  // For each processor
131  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
132    // Next processor
133    Record *Processor = ProcessorList[i];
134
135    const std::string &Name = Processor->getValueAsString("Name");
136    const std::vector<Record*> &FeatureList =
137      Processor->getValueAsListOfDefs("Features");
138
139    // Emit as { "cpu", "description", f1 | f2 | ... fn },
140    OS << "  { "
141       << "\"" << Name << "\", "
142       << "\"Select the " << Name << " processor\", ";
143
144    if (FeatureList.empty()) {
145      OS << "0";
146    } else {
147      for (unsigned j = 0, M = FeatureList.size(); j < M;) {
148        OS << FeatureList[j]->getName();
149        if (++j < M) OS << " | ";
150      }
151    }
152
153    // The "0" is for the "implies" section of this data structure.
154    OS << ", 0 }";
155
156    // Depending on 'if more in the list' emit comma
157    if (++i < N) OS << ",";
158
159    OS << "\n";
160  }
161
162  // End processor table
163  OS << "};\n";
164
165  // Emit size of table
166  OS<<"\nenum {\n";
167  OS<<"  SubTypeKVSize = sizeof(SubTypeKV)/sizeof(llvm::SubtargetFeatureKV)\n";
168  OS<<"};\n";
169}
170
171//
172// CollectAllItinClasses - Gathers and enumerates all the itinerary classes.
173// Returns itinerary class count.
174//
175unsigned SubtargetEmitter::CollectAllItinClasses(raw_ostream &OS,
176                              std::map<std::string, unsigned> &ItinClassesMap) {
177  // Gather and sort all itinerary classes
178  std::vector<Record*> ItinClassList =
179                            Records.getAllDerivedDefinitions("InstrItinClass");
180  std::sort(ItinClassList.begin(), ItinClassList.end(), LessRecord());
181
182  // For each itinerary class
183  unsigned N = ItinClassList.size();
184  for (unsigned i = 0; i < N; i++) {
185    // Next itinerary class
186    const Record *ItinClass = ItinClassList[i];
187    // Get name of itinerary class
188    // Assign itinerary class a unique number
189    ItinClassesMap[ItinClass->getName()] = i;
190  }
191
192  // Emit size of table
193  OS<<"\nenum {\n";
194  OS<<"  ItinClassesSize = " << N << "\n";
195  OS<<"};\n";
196
197  // Return itinerary class count
198  return N;
199}
200
201//
202// FormItineraryStageString - Compose a string containing the stage
203// data initialization for the specified itinerary.  N is the number
204// of stages.
205//
206void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
207                                                Record *ItinData,
208                                                std::string &ItinString,
209                                                unsigned &NStages) {
210  // Get states list
211  const std::vector<Record*> &StageList =
212    ItinData->getValueAsListOfDefs("Stages");
213
214  // For each stage
215  unsigned N = NStages = StageList.size();
216  for (unsigned i = 0; i < N;) {
217    // Next stage
218    const Record *Stage = StageList[i];
219
220    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
221    int Cycles = Stage->getValueAsInt("Cycles");
222    ItinString += "  { " + itostr(Cycles) + ", ";
223
224    // Get unit list
225    const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
226
227    // For each unit
228    for (unsigned j = 0, M = UnitList.size(); j < M;) {
229      // Add name and bitwise or
230      ItinString += Name + "FU::" + UnitList[j]->getName();
231      if (++j < M) ItinString += " | ";
232    }
233
234    int TimeInc = Stage->getValueAsInt("TimeInc");
235    ItinString += ", " + itostr(TimeInc);
236
237    int Kind = Stage->getValueAsInt("Kind");
238    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
239
240    // Close off stage
241    ItinString += " }";
242    if (++i < N) ItinString += ", ";
243  }
244}
245
246//
247// FormItineraryOperandCycleString - Compose a string containing the
248// operand cycle initialization for the specified itinerary.  N is the
249// number of operands that has cycles specified.
250//
251void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
252                         std::string &ItinString, unsigned &NOperandCycles) {
253  // Get operand cycle list
254  const std::vector<int64_t> &OperandCycleList =
255    ItinData->getValueAsListOfInts("OperandCycles");
256
257  // For each operand cycle
258  unsigned N = NOperandCycles = OperandCycleList.size();
259  for (unsigned i = 0; i < N;) {
260    // Next operand cycle
261    const int OCycle = OperandCycleList[i];
262
263    ItinString += "  " + itostr(OCycle);
264    if (++i < N) ItinString += ", ";
265  }
266}
267
268//
269// EmitStageAndOperandCycleData - Generate unique itinerary stages and
270// operand cycle tables.  Record itineraries for processors.
271//
272void SubtargetEmitter::EmitStageAndOperandCycleData(raw_ostream &OS,
273       unsigned NItinClasses,
274       std::map<std::string, unsigned> &ItinClassesMap,
275       std::vector<std::vector<InstrItinerary> > &ProcList) {
276  // Gather processor iteraries
277  std::vector<Record*> ProcItinList =
278                       Records.getAllDerivedDefinitions("ProcessorItineraries");
279
280  // If just no itinerary then don't bother
281  if (ProcItinList.size() < 2) return;
282
283  // Emit functional units for all the itineraries.
284  for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
285    // Next record
286    Record *Proc = ProcItinList[i];
287
288    std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
289    if (FUs.empty())
290      continue;
291
292    const std::string &Name = Proc->getName();
293    OS << "\n// Functional units for itineraries \"" << Name << "\"\n"
294       << "namespace " << Name << "FU {\n";
295
296    for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
297      OS << "  const unsigned " << FUs[j]->getName()
298         << " = 1 << " << j << ";\n";
299
300    OS << "}\n";
301  }
302
303  // Begin stages table
304  std::string StageTable = "\nstatic const llvm::InstrStage Stages[] = {\n";
305  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
306
307  // Begin operand cycle table
308  std::string OperandCycleTable = "static const unsigned OperandCycles[] = {\n";
309  OperandCycleTable += "  0, // No itinerary\n";
310
311  unsigned StageCount = 1, OperandCycleCount = 1;
312  unsigned ItinStageEnum = 1, ItinOperandCycleEnum = 1;
313  std::map<std::string, unsigned> ItinStageMap, ItinOperandCycleMap;
314  for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
315    // Next record
316    Record *Proc = ProcItinList[i];
317
318    // Get processor itinerary name
319    const std::string &Name = Proc->getName();
320
321    // Skip default
322    if (Name == "NoItineraries") continue;
323
324    // Create and expand processor itinerary to cover all itinerary classes
325    std::vector<InstrItinerary> ItinList;
326    ItinList.resize(NItinClasses);
327
328    // Get itinerary data list
329    std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
330
331    // For each itinerary data
332    for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {
333      // Next itinerary data
334      Record *ItinData = ItinDataList[j];
335
336      // Get string and stage count
337      std::string ItinStageString;
338      unsigned NStages;
339      FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
340
341      // Get string and operand cycle count
342      std::string ItinOperandCycleString;
343      unsigned NOperandCycles;
344      FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
345                                      NOperandCycles);
346
347      // Check to see if stage already exists and create if it doesn't
348      unsigned FindStage = 0;
349      if (NStages > 0) {
350        FindStage = ItinStageMap[ItinStageString];
351        if (FindStage == 0) {
352          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // index
353          StageTable += ItinStageString + ", // " + itostr(ItinStageEnum) + "\n";
354          // Record Itin class number.
355          ItinStageMap[ItinStageString] = FindStage = StageCount;
356          StageCount += NStages;
357          ItinStageEnum++;
358        }
359      }
360
361      // Check to see if operand cycle already exists and create if it doesn't
362      unsigned FindOperandCycle = 0;
363      if (NOperandCycles > 0) {
364        FindOperandCycle = ItinOperandCycleMap[ItinOperandCycleString];
365        if (FindOperandCycle == 0) {
366          // Emit as  cycle, // index
367          OperandCycleTable += ItinOperandCycleString + ", // " +
368            itostr(ItinOperandCycleEnum) + "\n";
369          // Record Itin class number.
370          ItinOperandCycleMap[ItinOperandCycleString] =
371            FindOperandCycle = OperandCycleCount;
372          OperandCycleCount += NOperandCycles;
373          ItinOperandCycleEnum++;
374        }
375      }
376
377      // Set up itinerary as location and location + stage count
378      InstrItinerary Intinerary = { FindStage, FindStage + NStages,
379                                    FindOperandCycle, FindOperandCycle + NOperandCycles};
380
381      // Locate where to inject into processor itinerary table
382      const std::string &Name = ItinData->getValueAsDef("TheClass")->getName();
383      unsigned Find = ItinClassesMap[Name];
384
385      // Inject - empty slots will be 0, 0
386      ItinList[Find] = Intinerary;
387    }
388
389    // Add process itinerary to list
390    ProcList.push_back(ItinList);
391  }
392
393  // Closing stage
394  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End itinerary\n";
395  StageTable += "};\n";
396
397  // Closing operand cycles
398  OperandCycleTable += "  0 // End itinerary\n";
399  OperandCycleTable += "};\n";
400
401  // Emit tables.
402  OS << StageTable;
403  OS << OperandCycleTable;
404
405  // Emit size of tables
406  OS<<"\nenum {\n";
407  OS<<"  StagesSize = sizeof(Stages)/sizeof(llvm::InstrStage),\n";
408  OS<<"  OperandCyclesSize = sizeof(OperandCycles)/sizeof(unsigned)\n";
409  OS<<"};\n";
410}
411
412//
413// EmitProcessorData - Generate data for processor itineraries.
414//
415void SubtargetEmitter::EmitProcessorData(raw_ostream &OS,
416      std::vector<std::vector<InstrItinerary> > &ProcList) {
417  // Get an iterator for processor itinerary stages
418  std::vector<std::vector<InstrItinerary> >::iterator
419      ProcListIter = ProcList.begin();
420
421  // For each processor itinerary
422  std::vector<Record*> Itins =
423                       Records.getAllDerivedDefinitions("ProcessorItineraries");
424  for (unsigned i = 0, N = Itins.size(); i < N; i++) {
425    // Next record
426    Record *Itin = Itins[i];
427
428    // Get processor itinerary name
429    const std::string &Name = Itin->getName();
430
431    // Skip default
432    if (Name == "NoItineraries") continue;
433
434    // Begin processor itinerary table
435    OS << "\n";
436    OS << "static const llvm::InstrItinerary " << Name << "[] = {\n";
437
438    // For each itinerary class
439    std::vector<InstrItinerary> &ItinList = *ProcListIter++;
440    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
441      InstrItinerary &Intinerary = ItinList[j];
442
443      // Emit in the form of
444      // { firstStage, lastStage, firstCycle, lastCycle } // index
445      if (Intinerary.FirstStage == 0) {
446        OS << "  { 0, 0, 0, 0 }";
447      } else {
448        OS << "  { " << Intinerary.FirstStage << ", " <<
449          Intinerary.LastStage << ", " <<
450          Intinerary.FirstOperandCycle << ", " <<
451          Intinerary.LastOperandCycle << " }";
452      }
453
454      OS << ", // " << j << "\n";
455    }
456
457    // End processor itinerary table
458    OS << "  { ~0U, ~0U, ~0U, ~0U } // end marker\n";
459    OS << "};\n";
460  }
461}
462
463//
464// EmitProcessorLookup - generate cpu name to itinerary lookup table.
465//
466void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
467  // Gather and sort processor information
468  std::vector<Record*> ProcessorList =
469                          Records.getAllDerivedDefinitions("Processor");
470  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
471
472  // Begin processor table
473  OS << "\n";
474  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
475     << "static const llvm::SubtargetInfoKV ProcItinKV[] = {\n";
476
477  // For each processor
478  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
479    // Next processor
480    Record *Processor = ProcessorList[i];
481
482    const std::string &Name = Processor->getValueAsString("Name");
483    const std::string &ProcItin =
484      Processor->getValueAsDef("ProcItin")->getName();
485
486    // Emit as { "cpu", procinit },
487    OS << "  { "
488       << "\"" << Name << "\", "
489       << "(void *)&" << ProcItin;
490
491    OS << " }";
492
493    // Depending on ''if more in the list'' emit comma
494    if (++i < N) OS << ",";
495
496    OS << "\n";
497  }
498
499  // End processor table
500  OS << "};\n";
501
502  // Emit size of table
503  OS<<"\nenum {\n";
504  OS<<"  ProcItinKVSize = sizeof(ProcItinKV)/"
505                            "sizeof(llvm::SubtargetInfoKV)\n";
506  OS<<"};\n";
507}
508
509//
510// EmitData - Emits all stages and itineries, folding common patterns.
511//
512void SubtargetEmitter::EmitData(raw_ostream &OS) {
513  std::map<std::string, unsigned> ItinClassesMap;
514  std::vector<std::vector<InstrItinerary> > ProcList;
515
516  // Enumerate all the itinerary classes
517  unsigned NItinClasses = CollectAllItinClasses(OS, ItinClassesMap);
518  // Make sure the rest is worth the effort
519  HasItineraries = NItinClasses != 1;   // Ignore NoItinerary.
520
521  if (HasItineraries) {
522    // Emit the stage data
523    EmitStageAndOperandCycleData(OS, NItinClasses, ItinClassesMap, ProcList);
524    // Emit the processor itinerary data
525    EmitProcessorData(OS, ProcList);
526    // Emit the processor lookup data
527    EmitProcessorLookup(OS);
528  }
529}
530
531//
532// ParseFeaturesFunction - Produces a subtarget specific function for parsing
533// the subtarget features string.
534//
535void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS) {
536  std::vector<Record*> Features =
537                       Records.getAllDerivedDefinitions("SubtargetFeature");
538  std::sort(Features.begin(), Features.end(), LessRecord());
539
540  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
541     << "// subtarget options.\n"
542     << "std::string llvm::";
543  OS << Target;
544  OS << "Subtarget::ParseSubtargetFeatures(const std::string &FS,\n"
545     << "                                  const std::string &CPU) {\n"
546     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
547     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU);\n"
548     << "  SubtargetFeatures Features(FS);\n"
549     << "  Features.setCPUIfNone(CPU);\n"
550     << "  uint32_t Bits =  Features.getBits(SubTypeKV, SubTypeKVSize,\n"
551     << "                                    FeatureKV, FeatureKVSize);\n";
552
553  for (unsigned i = 0; i < Features.size(); i++) {
554    // Next record
555    Record *R = Features[i];
556    const std::string &Instance = R->getName();
557    const std::string &Value = R->getValueAsString("Value");
558    const std::string &Attribute = R->getValueAsString("Attribute");
559
560    if (Value=="true" || Value=="false")
561      OS << "  if ((Bits & " << Instance << ") != 0) "
562         << Attribute << " = " << Value << ";\n";
563    else
564      OS << "  if ((Bits & " << Instance << ") != 0 && " << Attribute <<
565            " < " << Value << ") " << Attribute << " = " << Value << ";\n";
566  }
567
568  if (HasItineraries) {
569    OS << "\n"
570       << "  InstrItinerary *Itinerary = (InstrItinerary *)"
571       <<              "Features.getInfo(ProcItinKV, ProcItinKVSize);\n"
572       << "  InstrItins = InstrItineraryData(Stages, OperandCycles, Itinerary);\n";
573  }
574
575  OS << "  return Features.getCPU();\n"
576     << "}\n";
577}
578
579//
580// SubtargetEmitter::run - Main subtarget enumeration emitter.
581//
582void SubtargetEmitter::run(raw_ostream &OS) {
583  Target = CodeGenTarget().getName();
584
585  EmitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
586
587  OS << "#include \"llvm/Support/Debug.h\"\n";
588  OS << "#include \"llvm/Support/raw_ostream.h\"\n";
589  OS << "#include \"llvm/Target/SubtargetFeature.h\"\n";
590  OS << "#include \"llvm/Target/TargetInstrItineraries.h\"\n\n";
591
592//  Enumeration(OS, "FuncUnit", true);
593//  OS<<"\n";
594//  Enumeration(OS, "InstrItinClass", false);
595//  OS<<"\n";
596  Enumeration(OS, "SubtargetFeature", true);
597  OS<<"\n";
598  FeatureKeyValues(OS);
599  OS<<"\n";
600  CPUKeyValues(OS);
601  OS<<"\n";
602  EmitData(OS);
603  OS<<"\n";
604  ParseFeaturesFunction(OS);
605}
606