SubtargetEmitter.cpp revision 98eb98b0f2e6573f5aee67ce3e75624392d637b7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This tablegen backend emits subtarget enumerations.
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CodeGenTarget.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "CodeGenSchedule.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/ADT/StringExtras.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "llvm/MC/MCInstrItineraries.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/Support/Debug.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/TableGen/Record.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "llvm/TableGen/TableGenBackend.h"
2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include <algorithm>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <string>
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochusing namespace llvm;
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SubtargetEmitter {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordKeeper &Records;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CodeGenSchedModels &SchedModels;
32d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  std::string Target;
33d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned FeatureKeyValues(raw_ostream &OS);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned CPUKeyValues(raw_ostream &OS);
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FormItineraryStageString(const std::string &Names,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                Record *ItinData, std::string &ItinString,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                unsigned &NStages);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       unsigned &NOperandCycles);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FormItineraryBypassString(const std::string &Names,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 Record *ItinData,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 std::string &ItinString, unsigned NOperandCycles);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitStageAndOperandCycleData(raw_ostream &OS,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    std::vector<std::vector<InstrItinerary> >
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      &ProcItinLists);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitItineraries(raw_ostream &OS,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       std::vector<std::vector<InstrItinerary> >
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         &ProcItinLists);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         char Separator);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitProcessorModels(raw_ostream &OS);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitProcessorLookup(raw_ostream &OS);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void EmitSchedModel(raw_ostream &OS);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             unsigned NumProcs);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public:
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void run(raw_ostream &o);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // End anonymous namespace
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Enumeration - Emit the specified class as an enumeration.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SubtargetEmitter::Enumeration(raw_ostream &OS,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const char *ClassName,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   bool isBits) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get all records of class and sort
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(DefList.begin(), DefList.end(), LessRecord());
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned N = DefList.size();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (N == 0)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (N > 64) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    errs() << "Too many (> 64) subtarget features!\n";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    exit(1);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OS << "namespace " << Target << " {\n";
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For bit flag enumerations with more than 32 items, emit constants.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Emit an enum for everything else.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (isBits && N > 32) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For each record
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned i = 0; i < N; i++) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Next record
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Record *Def = DefList[i];
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Get and emit name and expression (1 << i)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OS << "  const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Open enumeration
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "enum {\n";
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For each record
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned i = 0; i < N;) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Next record
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Record *Def = DefList[i];
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Get and emit name
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OS << "  " << Def->getName();
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If bit flags then emit expression (1 << i)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (isBits)  OS << " = " << " 1ULL << " << i;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Depending on 'if more in the list' emit comma
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (++i < N) OS << ",";
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OS << "\n";
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close enumeration
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "};\n";
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OS << "}\n";
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// FeatureKeyValues - Emit data of all the subtarget features.  Used by the
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// command line.
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Gather and sort all the features
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<Record*> FeatureList =
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           Records.getAllDerivedDefinitions("SubtargetFeature");
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (FeatureList.empty())
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Begin feature table
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OS << "// Sorted (by key) array of values for CPU features.\n"
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     << "extern const llvm::SubtargetFeatureKV " << Target
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)     << "FeatureKV[] = {\n";
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For each feature
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned NumFeatures = 0;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Next feature
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Record *Feature = FeatureList[i];
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string &Name = Feature->getName();
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string &CommandLineName = Feature->getValueAsString("Name");
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string &Desc = Feature->getValueAsString("Desc");
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (CommandLineName.empty()) continue;
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OS << "  { "
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       << "\"" << CommandLineName << "\", "
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       << "\"" << Desc << "\", "
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       << Target << "::" << Name << ", ";
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<Record*> &ImpliesList =
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Feature->getValueAsListOfDefs("Implies");
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (ImpliesList.empty()) {
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      OS << "0ULL";
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        OS << Target << "::" << ImpliesList[j]->getName();
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (++j < M) OS << " | ";
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
1761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << " }";
1771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ++NumFeatures;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Depending on 'if more in the list' emit comma
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((i + 1) < N) OS << ",";
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "\n";
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // End feature table
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OS << "};\n";
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NumFeatures;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CPUKeyValues - Emit data of all the subtarget processors.  Used by command
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// line.
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gather and sort processor information
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<Record*> ProcessorList =
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          Records.getAllDerivedDefinitions("Processor");
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begin processor table
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OS << "// Sorted (by key) array of values for CPU subtype.\n"
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     << "extern const llvm::SubtargetFeatureKV " << Target
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     << "SubTypeKV[] = {\n";
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // For each processor
2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Next processor
2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    Record *Processor = ProcessorList[i];
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string &Name = Processor->getValueAsString("Name");
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<Record*> &FeatureList =
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Processor->getValueAsListOfDefs("Features");
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Emit as { "cpu", "description", f1 | f2 | ... fn },
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "  { "
2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       << "\"" << Name << "\", "
2181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       << "\"Select the " << Name << " processor\", ";
2191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FeatureList.empty()) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OS << "0ULL";
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (unsigned j = 0, M = FeatureList.size(); j < M;) {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        OS << Target << "::" << FeatureList[j]->getName();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (++j < M) OS << " | ";
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The "0" is for the "implies" section of this data structure.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << ", 0ULL }";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Depending on 'if more in the list' emit comma
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (++i < N) OS << ",";
2341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "\n";
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // End processor table
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OS << "};\n";
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProcessorList.size();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FormItineraryStageString - Compose a string containing the stage
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// data initialization for the specified itinerary.  N is the number
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of stages.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                Record *ItinData,
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                std::string &ItinString,
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                unsigned &NStages) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get states list
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::vector<Record*> &StageList =
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ItinData->getValueAsListOfDefs("Stages");
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For each stage
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  unsigned N = NStages = StageList.size();
2591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (unsigned i = 0; i < N;) {
2601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Next stage
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Record *Stage = StageList[i];
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int Cycles = Stage->getValueAsInt("Cycles");
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ItinString += "  { " + itostr(Cycles) + ", ";
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Get unit list
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // For each unit
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned j = 0, M = UnitList.size(); j < M;) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Add name and bitwise or
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ItinString += Name + "FU::" + UnitList[j]->getName();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (++j < M) ItinString += " | ";
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int TimeInc = Stage->getValueAsInt("TimeInc");
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ItinString += ", " + itostr(TimeInc);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int Kind = Stage->getValueAsInt("Kind");
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Close off stage
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ItinString += " }";
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (++i < N) ItinString += ", ";
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// FormItineraryOperandCycleString - Compose a string containing the
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// operand cycle initialization for the specified itinerary.  N is the
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// number of operands that has cycles specified.
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
2941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
2951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                         std::string &ItinString, unsigned &NOperandCycles) {
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Get operand cycle list
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::vector<int64_t> &OperandCycleList =
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ItinData->getValueAsListOfInts("OperandCycles");
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each operand cycle
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned N = NOperandCycles = OperandCycleList.size();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0; i < N;) {
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Next operand cycle
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const int OCycle = OperandCycleList[i];
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ItinString += "  " + itostr(OCycle);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (++i < N) ItinString += ", ";
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 Record *ItinData,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 std::string &ItinString,
31468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                 unsigned NOperandCycles) {
31568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  const std::vector<Record*> &BypassList =
31668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    ItinData->getValueAsListOfDefs("Bypasses");
31768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  unsigned N = BypassList.size();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned i = 0;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; i < N;) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ItinString += Name + "Bypass::" + BypassList[i]->getName();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (++i < NOperandCycles) ItinString += ", ";
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
32368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (; i < NOperandCycles;) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ItinString += " 0";
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (++i < NOperandCycles) ItinString += ", ";
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by CodeGenSchedClass::Index.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SubtargetEmitter::
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EmitStageAndOperandCycleData(raw_ostream &OS,
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             std::vector<std::vector<InstrItinerary> >
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &ProcItinLists) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Multiple processor models may share an itinerary record. Emit it once.
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SmallPtrSet<Record*, 8> ItinsDefSet;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Emit functional units for all the itineraries.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ItinsDefSet.insert(PI->ItinsDef))
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FUs.empty())
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string &Name = PI->ItinsDef->getName();
3541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "\n// Functional units for \"" << Name << "\"\n"
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       << "namespace " << Name << "FU {\n";
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OS << "  const unsigned " << FUs[j]->getName()
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << " = 1 << " << j << ";\n";
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OS << "}\n";
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (BPs.size()) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << "\"\n" << "namespace " << Name << "Bypass {\n";
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      OS << "  const unsigned NoBypass = 0;\n";
36968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
37068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        OS << "  const unsigned " << BPs[j]->getName()
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           << " = 1 << " << j << ";\n";
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      OS << "}\n";
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begin stages table
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string StageTable = "\nextern const llvm::InstrStage " + Target +
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           "Stages[] = {\n";
38068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begin operand cycle table
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string OperandCycleTable = "extern const unsigned " + Target +
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "OperandCycles[] = {\n";
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OperandCycleTable += "  0, // No itinerary\n";
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Begin pipeline bypass table
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string BypassTable = "extern const unsigned " + Target +
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "ForwardingPaths[] = {\n";
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BypassTable += " 0, // No itinerary\n";
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each Itinerary across all processors, add a unique entry to the stages,
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // operand cycles, and pipepine bypess tables. Then add the new Itinerary
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object with computed offsets to the ProcItinLists result.
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned StageCount = 1, OperandCycleCount = 1;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CodeGenProcModel &ProcModel = *PI;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add process itinerary to the list.
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcItinLists.resize(ProcItinLists.size()+1);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If this processor defines no itineraries, then leave the itinerary list
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // empty.
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ProcModel.ItinDefList.empty())
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Reserve index==0 for NoItinerary.
4111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    ItinList.resize(SchedModels.numItineraryClasses()+1);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string &Name = ProcModel.ItinsDef->getName();
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // For each itinerary data
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned SchedClassIdx = 0,
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           SchedClassEnd = ProcModel.ItinDefList.size();
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Next itinerary data
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Get string and stage count
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string ItinStageString;
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned NStages = 0;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (ItinData)
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Get string and operand cycle count
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string ItinOperandCycleString;
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned NOperandCycles = 0;
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string ItinBypassString;
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (ItinData) {
4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        NOperandCycles);
4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FormItineraryBypassString(Name, ItinData, ItinBypassString,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  NOperandCycles);
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Check to see if stage already exists and create if it doesn't
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned FindStage = 0;
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (NStages > 0) {
4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        FindStage = ItinStageMap[ItinStageString];
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (FindStage == 0) {
4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          StageTable += ItinStageString + ", // " + itostr(StageCount);
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (NStages > 1)
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            StageTable += "-" + itostr(StageCount + NStages - 1);
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          StageTable += "\n";
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Record Itin class number.
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ItinStageMap[ItinStageString] = FindStage = StageCount;
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          StageCount += NStages;
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Check to see if operand cycle already exists and create if it doesn't
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      unsigned FindOperandCycle = 0;
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (NOperandCycles > 0) {
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        FindOperandCycle = ItinOperandMap[ItinOperandString];
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (FindOperandCycle == 0) {
46368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          // Emit as  cycle, // index
46468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          OperandCycleTable += ItinOperandCycleString + ", // ";
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          std::string OperandIdxComment = itostr(OperandCycleCount);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (NOperandCycles > 1)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            OperandIdxComment += "-"
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              + itostr(OperandCycleCount + NOperandCycles - 1);
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          OperandCycleTable += OperandIdxComment + "\n";
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Record Itin class number.
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          ItinOperandMap[ItinOperandCycleString] =
47268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)            FindOperandCycle = OperandCycleCount;
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Emit as bypass, // index
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          OperandCycleCount += NOperandCycles;
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Set up itinerary as location and location + stage count
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    FindOperandCycle,
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    FindOperandCycle + NOperandCycles};
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Inject - empty slots will be 0, 0
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ItinList[SchedClassIdx] = Intinerary;
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Closing stage
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  StageTable += "};\n";
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Closing operand cycles
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OperandCycleTable += "  0 // End operand cycles\n";
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OperandCycleTable += "};\n";
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BypassTable += " 0 // End bypass tables\n";
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BypassTable += "};\n";
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Emit tables.
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  OS << StageTable;
5031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OS << OperandCycleTable;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OS << BypassTable;
5051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// EmitProcessorData - Generate data for processor itineraries that were
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Itineraries for each processor. The Itinerary lists are indexed on
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CodeGenSchedClass::Index.
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SubtargetEmitter::
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)EmitItineraries(raw_ostream &OS,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Multiple processor models may share an itinerary record. Emit it once.
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SmallPtrSet<Record*, 8> ItinsDefSet;
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For each processor's machine model
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::vector<InstrItinerary> >::iterator
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ProcItinListsIter = ProcItinLists.begin();
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Record *ItinsDef = PI->ItinsDef;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ItinsDefSet.insert(ItinsDef))
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Get processor itinerary name
5311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const std::string &Name = ItinsDef->getName();
5321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Get the itinerary list for the processor.
5341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
5351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    std::vector<InstrItinerary> &ItinList = *ProcItinListsIter++;
5361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "\n";
5381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "static const llvm::InstrItinerary ";
5391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (ItinList.empty()) {
5401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      OS << '*' << Name << " = 0;\n";
5411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      continue;
5421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Begin processor itinerary table
5451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << Name << "[] = {\n";
5461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // For each itinerary class in CodeGenSchedClass::Index order.
5481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
5491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      InstrItinerary &Intinerary = ItinList[j];
5501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Emit Itinerary in the form of
5521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // { firstStage, lastStage, firstCycle, lastCycle } // index
5531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      OS << "  { " <<
5541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        Intinerary.NumMicroOps << ", " <<
5551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        Intinerary.FirstStage << ", " <<
5561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        Intinerary.LastStage << ", " <<
5571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        Intinerary.FirstOperandCycle << ", " <<
5581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        Intinerary.LastOperandCycle << " }" <<
5591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
5601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
5611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // End processor itinerary table
5621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "  { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
5631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "};\n";
5641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
5651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Emit either the value defined in the TableGen Record, or the default
5681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// value defined in the C++ header. The Record is null if the processor does not
5691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// define a model.
5701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
5711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                         const char *Name, char Separator) {
5721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OS << "  ";
5731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int V = R ? R->getValueAsInt(Name) : -1;
5741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (V >= 0)
5751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << V << Separator << " // " << Name;
5761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  else
5771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "MCSchedModel::Default" << Name << Separator;
5781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OS << '\n';
5791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
5801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
5811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
5821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // For each processor model.
5831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
5841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
5851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Skip default
5861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Begin processor itinerary properties
5871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "\n";
5881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
5891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
5901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
5911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
5921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
5931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
5941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (SchedModels.hasItineraryClasses())
5951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      OS << "  " << PI->ItinsDef->getName();
5961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    else
5971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      OS << "  0";
5981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    OS << ");\n";
5991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
6001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
6011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// EmitProcessorLookup - generate cpu name to itinerary lookup table.
604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
605f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Gather and sort processor information
607f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<Record*> ProcessorList =
608f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                          Records.getAllDerivedDefinitions("Processor");
609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Begin processor table
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OS << "\n";
613f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     << "extern const llvm::SubtargetInfoKV "
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     << Target << "ProcSchedKV[] = {\n";
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // For each processor
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Next processor
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Record *Processor = ProcessorList[i];
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string &Name = Processor->getValueAsString("Name");
623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string &ProcModelName =
624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      SchedModels.getProcModel(Processor).ModelName;
625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
626f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Emit as { "cpu", procinit },
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OS << "  { "
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       << "\"" << Name << "\", "
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       << "(const void *)&" << ProcModelName;
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OS << " }";
632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Depending on ''if more in the list'' emit comma
634f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (++i < N) OS << ",";
635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OS << "\n";
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // End processor table
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  OS << "};\n";
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (SchedModels.hasItineraryClasses()) {
648f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    std::vector<std::vector<InstrItinerary> > ProcItinLists;
649f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Emit the stage data
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EmitStageAndOperandCycleData(OS, ProcItinLists);
651f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EmitItineraries(OS, ProcItinLists);
652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
653f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Emit the processor machine model
654f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EmitProcessorModels(OS);
655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Emit the processor lookup data
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  EmitProcessorLookup(OS);
657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
660f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// ParseFeaturesFunction - Produces a subtarget specific function for parsing
661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// the subtarget features string.
662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)//
663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                             unsigned NumFeatures,
665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                             unsigned NumProcs) {
666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<Record*> Features =
6671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                       Records.getAllDerivedDefinitions("SubtargetFeature");
6681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  std::sort(Features.begin(), Features.end(), LessRecord());
6691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
6701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
6711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)     << "// subtarget options.\n"
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     << "void llvm::";
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OS << Target;
674  OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
675     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
676     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
677
678  if (Features.empty()) {
679    OS << "}\n";
680    return;
681  }
682
683  OS << "  uint64_t Bits = ReInitMCSubtargetInfo(CPU, FS);\n";
684
685  for (unsigned i = 0; i < Features.size(); i++) {
686    // Next record
687    Record *R = Features[i];
688    const std::string &Instance = R->getName();
689    const std::string &Value = R->getValueAsString("Value");
690    const std::string &Attribute = R->getValueAsString("Attribute");
691
692    if (Value=="true" || Value=="false")
693      OS << "  if ((Bits & " << Target << "::"
694         << Instance << ") != 0) "
695         << Attribute << " = " << Value << ";\n";
696    else
697      OS << "  if ((Bits & " << Target << "::"
698         << Instance << ") != 0 && "
699         << Attribute << " < " << Value << ") "
700         << Attribute << " = " << Value << ";\n";
701  }
702
703  OS << "}\n";
704}
705
706//
707// SubtargetEmitter::run - Main subtarget enumeration emitter.
708//
709void SubtargetEmitter::run(raw_ostream &OS) {
710  emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
711
712  OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
713  OS << "#undef GET_SUBTARGETINFO_ENUM\n";
714
715  OS << "namespace llvm {\n";
716  Enumeration(OS, "SubtargetFeature", true);
717  OS << "} // End llvm namespace \n";
718  OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
719
720  OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
721  OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
722
723  OS << "namespace llvm {\n";
724#if 0
725  OS << "namespace {\n";
726#endif
727  unsigned NumFeatures = FeatureKeyValues(OS);
728  OS << "\n";
729  unsigned NumProcs = CPUKeyValues(OS);
730  OS << "\n";
731  EmitSchedModel(OS);
732  OS << "\n";
733#if 0
734  OS << "}\n";
735#endif
736
737  // MCInstrInfo initialization routine.
738  OS << "static inline void Init" << Target
739     << "MCSubtargetInfo(MCSubtargetInfo *II, "
740     << "StringRef TT, StringRef CPU, StringRef FS) {\n";
741  OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
742  if (NumFeatures)
743    OS << Target << "FeatureKV, ";
744  else
745    OS << "0, ";
746  if (NumProcs)
747    OS << Target << "SubTypeKV, ";
748  else
749    OS << "0, ";
750  if (SchedModels.hasItineraryClasses()) {
751    OS << Target << "ProcSchedKV, "
752       << Target << "Stages, "
753       << Target << "OperandCycles, "
754       << Target << "ForwardingPaths, ";
755  } else
756    OS << "0, 0, 0, 0, ";
757  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
758
759  OS << "} // End llvm namespace \n";
760
761  OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
762
763  OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
764  OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
765
766  OS << "#include \"llvm/Support/Debug.h\"\n";
767  OS << "#include \"llvm/Support/raw_ostream.h\"\n";
768  ParseFeaturesFunction(OS, NumFeatures, NumProcs);
769
770  OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
771
772  // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
773  OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
774  OS << "#undef GET_SUBTARGETINFO_HEADER\n";
775
776  std::string ClassName = Target + "GenSubtargetInfo";
777  OS << "namespace llvm {\n";
778  OS << "class DFAPacketizer;\n";
779  OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
780     << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
781     << "StringRef FS);\n"
782     << "public:\n"
783     << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
784     << " const;\n"
785     << "};\n";
786  OS << "} // End llvm namespace \n";
787
788  OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
789
790  OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
791  OS << "#undef GET_SUBTARGETINFO_CTOR\n";
792
793  OS << "namespace llvm {\n";
794  OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
795  OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
796  if (SchedModels.hasItineraryClasses()) {
797    OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
798    OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
799    OS << "extern const unsigned " << Target << "OperandCycles[];\n";
800    OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
801  }
802
803  OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
804     << "StringRef FS)\n"
805     << "  : TargetSubtargetInfo() {\n"
806     << "  InitMCSubtargetInfo(TT, CPU, FS, ";
807  if (NumFeatures)
808    OS << Target << "FeatureKV, ";
809  else
810    OS << "0, ";
811  if (NumProcs)
812    OS << Target << "SubTypeKV, ";
813  else
814    OS << "0, ";
815  if (SchedModels.hasItineraryClasses()) {
816    OS << Target << "ProcSchedKV, "
817       << Target << "Stages, "
818       << Target << "OperandCycles, "
819       << Target << "ForwardingPaths, ";
820  } else
821    OS << "0, 0, 0, 0, ";
822  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
823  OS << "} // End llvm namespace \n";
824
825  OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
826}
827
828namespace llvm {
829
830void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
831  CodeGenTarget CGTarget(RK);
832  SubtargetEmitter(RK, CGTarget).run(OS);
833}
834
835} // End llvm namespace
836