SubtargetEmitter.cpp revision 3b8fb648c6e1c519b7e0f487f4fb511744869d35
14bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
24bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//
34bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//                     The LLVM Compiler Infrastructure
44bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//
53060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// This file is distributed under the University of Illinois Open Source
63060910e290949a9ac5eda8726d030790c4d60ffChris Lattner// License. See LICENSE.TXT for details.
74bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//
84bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//===----------------------------------------------------------------------===//
94bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//
103d87811ce0381c3364ce10aed77de8231a03bc48Chris Lattner// This tablegen backend emits subtarget enumerations.
114bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//
124bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey//===----------------------------------------------------------------------===//
134bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey
144bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey#include "CodeGenTarget.h"
152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick#include "CodeGenSchedule.h"
164bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey#include "llvm/ADT/StringExtras.h"
1740096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/ADT/STLExtras.h"
186f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/MC/MCInstrItineraries.h"
1940096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/TableGen/Error.h"
206f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/Record.h"
216f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.h"
2240096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/Support/Debug.h"
23544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick#include "llvm/Support/Format.h"
249489c04efc47a68af65e226e50f03d488094ffceJeff Cohen#include <algorithm>
256f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include <map>
266f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include <string>
276f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include <vector>
284bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskeyusing namespace llvm;
294bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey
306f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace {
316f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenclass SubtargetEmitter {
3252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Each processor has a SchedClassDesc table with an entry for each SchedClass.
3352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // The SchedClassDesc table indexes into a global write resource table, write
3452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // latency table, and read advance table.
3552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  struct SchedClassTables {
3652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;
3752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry> WriteProcResources;
3852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry> WriteLatencies;
393b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    std::vector<std::string> WriterNames;
4052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
4152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
4252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Reserve an invalid entry at index 0
4352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SchedClassTables() {
4452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      ProcSchedClasses.resize(1);
4552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteProcResources.resize(1);
4652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.resize(1);
473b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WriterNames.push_back("InvalidWrite");
4852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      ReadAdvanceEntries.resize(1);
4952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
5052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  };
5152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
5252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  struct LessWriteProcResources {
5352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    bool operator()(const MCWriteProcResEntry &LHS,
5452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                    const MCWriteProcResEntry &RHS) {
5552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
5652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
5752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  };
586f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
596f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  RecordKeeper &Records;
602661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  CodeGenSchedModels &SchedModels;
616f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  std::string Target;
626f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
646f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  unsigned FeatureKeyValues(raw_ostream &OS);
656f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  unsigned CPUKeyValues(raw_ostream &OS);
666f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void FormItineraryStageString(const std::string &Names,
676f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                Record *ItinData, std::string &ItinString,
686f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                unsigned &NStages);
696f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
706f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                       unsigned &NOperandCycles);
716f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void FormItineraryBypassString(const std::string &Names,
726f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                 Record *ItinData,
736f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                 std::string &ItinString, unsigned NOperandCycles);
742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitStageAndOperandCycleData(raw_ostream &OS,
752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                    std::vector<std::vector<InstrItinerary> >
762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                      &ProcItinLists);
772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitItineraries(raw_ostream &OS,
782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                       std::vector<std::vector<InstrItinerary> >
792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                         &ProcItinLists);
802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
816f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                         char Separator);
8240096d26937cd47c865464bef7b28550bc20c631Andrew Trick  void EmitProcessorResources(const CodeGenProcModel &ProcModel,
8340096d26937cd47c865464bef7b28550bc20c631Andrew Trick                              raw_ostream &OS);
8452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  Record *FindWriteResources(Record *WriteDef,
8552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                             const CodeGenProcModel &ProcModel);
8652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  Record *FindReadAdvance(Record *ReadDef, const CodeGenProcModel &ProcModel);
8752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  void GenSchedClassTables(const CodeGenProcModel &ProcModel,
8852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                           SchedClassTables &SchedTables);
89544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
902661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitProcessorModels(raw_ostream &OS);
916f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void EmitProcessorLookup(raw_ostream &OS);
924d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  void EmitSchedModelHelpers(std::string ClassName, raw_ostream &OS);
932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitSchedModel(raw_ostream &OS);
946f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
956f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                             unsigned NumProcs);
966f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
976f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenpublic:
982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
1006f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1016f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void run(raw_ostream &o);
1026f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1036f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen};
1046f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End anonymous namespace
1056f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1067dc02047fbb4b014e914458f54ea539c8ae58316Jim Laskey//
107581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// Enumeration - Emit the specified class as an enumeration.
108b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
1091a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::Enumeration(raw_ostream &OS,
110581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey                                   const char *ClassName,
111581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey                                   bool isBits) {
112908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Get all records of class and sort
113f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
11442d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(DefList.begin(), DefList.end(), LessRecord());
1154bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey
116b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  unsigned N = DefList.size();
11794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (N == 0)
11894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return;
119b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  if (N > 64) {
120b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    errs() << "Too many (> 64) subtarget features!\n";
121b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    exit(1);
122b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  }
123b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng
12494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace " << Target << " {\n";
12594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
126ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  // For bit flag enumerations with more than 32 items, emit constants.
127ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  // Emit an enum for everything else.
128ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  if (isBits && N > 32) {
129ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // For each record
130ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    for (unsigned i = 0; i < N; i++) {
131ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Next record
132ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      Record *Def = DefList[i];
13394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
134ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Get and emit name and expression (1 << i)
135ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "  const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
136ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    }
137ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  } else {
138ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // Open enumeration
139ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    OS << "enum {\n";
140da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
141ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // For each record
142ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    for (unsigned i = 0; i < N;) {
143ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Next record
144ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      Record *Def = DefList[i];
145da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
146ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Get and emit name
147ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "  " << Def->getName();
148908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
149ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // If bit flags then emit expression (1 << i)
150ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      if (isBits)  OS << " = " << " 1ULL << " << i;
151da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
152ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Depending on 'if more in the list' emit comma
153ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      if (++i < N) OS << ",";
154ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen
155ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "\n";
156ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    }
157da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
158ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // Close enumeration
159ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    OS << "};\n";
160ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  }
16194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
16294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "}\n";
163b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
164b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
165b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
1664222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// FeatureKeyValues - Emit data of all the subtarget features.  Used by the
1674222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// command line.
168b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
16994214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
170908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Gather and sort all the features
171f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> FeatureList =
172f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                           Records.getAllDerivedDefinitions("SubtargetFeature");
17394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
17494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (FeatureList.empty())
17594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return 0;
17694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
1777c9a7728d9dd248ebee8f2dd969d303711d487a9Jim Grosbach  std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
178b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
179908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin feature table
180581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << "// Sorted (by key) array of values for CPU features.\n"
1811a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetFeatureKV " << Target
1821a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "FeatureKV[] = {\n";
183da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
184908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each feature
18594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumFeatures = 0;
186dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey  for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
187f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next feature
188f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *Feature = FeatureList[i];
189f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
1904222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Feature->getName();
1914222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &CommandLineName = Feature->getValueAsString("Name");
1924222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Desc = Feature->getValueAsString("Desc");
193da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
194dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey    if (CommandLineName.empty()) continue;
195da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
196da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach    // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
197b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    OS << "  { "
198f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey       << "\"" << CommandLineName << "\", "
199b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"" << Desc << "\", "
20094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "::" << Name << ", ";
2014222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
202da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick    const std::vector<Record*> &ImpliesList =
2034222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      Feature->getValueAsListOfDefs("Implies");
204da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
2054222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    if (ImpliesList.empty()) {
206b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng      OS << "0ULL";
2074222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    } else {
2084222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
20994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng        OS << Target << "::" << ImpliesList[j]->getName();
2104222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        if (++j < M) OS << " | ";
2114222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      }
2124222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    }
2134222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
2144222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    OS << " }";
21594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    ++NumFeatures;
216da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
21710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on 'if more in the list' emit comma
218dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey    if ((i + 1) < N) OS << ",";
219da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
220f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    OS << "\n";
221b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  }
222da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
223908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // End feature table
224b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  OS << "};\n";
225b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
22694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  return NumFeatures;
227b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
228b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
229b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
230b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// CPUKeyValues - Emit data of all the subtarget processors.  Used by command
231b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// line.
232b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
23394214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
234908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Gather and sort processor information
235f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> ProcessorList =
236f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                          Records.getAllDerivedDefinitions("Processor");
23742d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
238b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
239908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin processor table
240581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << "// Sorted (by key) array of values for CPU subtype.\n"
2411a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetFeatureKV " << Target
2421a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "SubTypeKV[] = {\n";
243da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
244908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each processor
245f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
246f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next processor
247f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *Processor = ProcessorList[i];
248f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
2494222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Processor->getValueAsString("Name");
250da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick    const std::vector<Record*> &FeatureList =
251b0e103d46bf8799ac5523157a6ed4a78d1751a89Chris Lattner      Processor->getValueAsListOfDefs("Features");
252da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
253908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Emit as { "cpu", "description", f1 | f2 | ... fn },
254b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    OS << "  { "
255b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"" << Name << "\", "
256b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"Select the " << Name << " processor\", ";
257da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
258f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    if (FeatureList.empty()) {
259b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng      OS << "0ULL";
260b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    } else {
261f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      for (unsigned j = 0, M = FeatureList.size(); j < M;) {
26294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng        OS << Target << "::" << FeatureList[j]->getName();
263f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey        if (++j < M) OS << " | ";
2644bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey      }
2654bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey    }
266da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
2674222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    // The "0" is for the "implies" section of this data structure.
268b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    OS << ", 0ULL }";
269da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
27010b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on 'if more in the list' emit comma
271f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    if (++i < N) OS << ",";
272da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
273f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    OS << "\n";
2744bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey  }
275da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
276908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // End processor table
277b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  OS << "};\n";
278b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
27994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  return ProcessorList.size();
2804bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey}
281b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
282581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey//
283fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryStageString - Compose a string containing the stage
284fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// data initialization for the specified itinerary.  N is the number
285fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// of stages.
2860d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
287928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikovvoid SubtargetEmitter::FormItineraryStageString(const std::string &Name,
288928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov                                                Record *ItinData,
289fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                                                std::string &ItinString,
290fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                                                unsigned &NStages) {
291f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  // Get states list
2924222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling  const std::vector<Record*> &StageList =
2934222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    ItinData->getValueAsListOfDefs("Stages");
294908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
295908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each stage
296f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  unsigned N = NStages = StageList.size();
2978dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb  for (unsigned i = 0; i < N;) {
298f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next stage
2994222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const Record *Stage = StageList[i];
300da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
30196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
3020d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    int Cycles = Stage->getValueAsInt("Cycles");
3037f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey    ItinString += "  { " + itostr(Cycles) + ", ";
304da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
305f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Get unit list
3064222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
307da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
308908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // For each unit
309f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    for (unsigned j = 0, M = UnitList.size(); j < M;) {
310f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      // Add name and bitwise or
311928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov      ItinString += Name + "FU::" + UnitList[j]->getName();
312f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      if (++j < M) ItinString += " | ";
3130d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
314da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
3151a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin    int TimeInc = Stage->getValueAsInt("TimeInc");
3161a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin    ItinString += ", " + itostr(TimeInc);
3171a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin
31896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    int Kind = Stage->getValueAsInt("Kind");
31996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
32096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov
321908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Close off stage
322908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    ItinString += " }";
3238dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb    if (++i < N) ItinString += ", ";
3240d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
3250d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
3260d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
3270d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
328fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryOperandCycleString - Compose a string containing the
329fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// operand cycle initialization for the specified itinerary.  N is the
330fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// number of operands that has cycles specified.
3310d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
332fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwinvoid SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
333fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                         std::string &ItinString, unsigned &NOperandCycles) {
334fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Get operand cycle list
335fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  const std::vector<int64_t> &OperandCycleList =
336fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    ItinData->getValueAsListOfInts("OperandCycles");
337fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
338fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // For each operand cycle
339fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  unsigned N = NOperandCycles = OperandCycleList.size();
340fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  for (unsigned i = 0; i < N;) {
341fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    // Next operand cycle
342fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    const int OCycle = OperandCycleList[i];
343da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
344fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    ItinString += "  " + itostr(OCycle);
345fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    if (++i < N) ItinString += ", ";
346fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  }
347fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin}
348fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
34963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Chengvoid SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
35063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 Record *ItinData,
35163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 std::string &ItinString,
35263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 unsigned NOperandCycles) {
35363d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  const std::vector<Record*> &BypassList =
35463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinData->getValueAsListOfDefs("Bypasses");
35563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  unsigned N = BypassList.size();
3563881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  unsigned i = 0;
3573881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  for (; i < N;) {
35863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinString += Name + "Bypass::" + BypassList[i]->getName();
3593881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (++i < NOperandCycles) ItinString += ", ";
36063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  }
3613881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  for (; i < NOperandCycles;) {
36263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinString += " 0";
3633881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (++i < NOperandCycles) ItinString += ", ";
36463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  }
36563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng}
36663d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
367fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin//
3682661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
3692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
3702661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// by CodeGenSchedClass::Index.
371fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin//
3722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::
3732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitStageAndOperandCycleData(raw_ostream &OS,
3742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                             std::vector<std::vector<InstrItinerary> >
3752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                               &ProcItinLists) {
376908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
377cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  // Multiple processor models may share an itinerary record. Emit it once.
378cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  SmallPtrSet<Record*, 8> ItinsDefSet;
379cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
380928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov  // Emit functional units for all the itineraries.
3812661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
3822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
383928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
384cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick    if (!ItinsDefSet.insert(PI->ItinsDef))
385cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick      continue;
386cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
3872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
388928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    if (FUs.empty())
389928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov      continue;
390928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
3912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = PI->ItinsDef->getName();
3922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n// Functional units for \"" << Name << "\"\n"
393928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov       << "namespace " << Name << "FU {\n";
394928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
395928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
396b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      OS << "  const unsigned " << FUs[j]->getName()
397b460a3382961c5be9952a75d46228f624edbd39fHal Finkel         << " = 1 << " << j << ";\n";
398928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
399928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    OS << "}\n";
40063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4012661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
4023881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (BPs.size()) {
4033881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
4043881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng         << "\"\n" << "namespace " << Name << "Bypass {\n";
40563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4061a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer      OS << "  const unsigned NoBypass = 0;\n";
4073881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
4081a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer        OS << "  const unsigned " << BPs[j]->getName()
4093881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng           << " = 1 << " << j << ";\n";
41063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4113881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      OS << "}\n";
4123881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    }
413928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov  }
414928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
415908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin stages table
4161a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string StageTable = "\nextern const llvm::InstrStage " + Target +
4171a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer                           "Stages[] = {\n";
41896085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
419da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
420fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Begin operand cycle table
4211a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string OperandCycleTable = "extern const unsigned " + Target +
42294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    "OperandCycles[] = {\n";
423fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OperandCycleTable += "  0, // No itinerary\n";
42463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
42563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  // Begin pipeline bypass table
4261a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string BypassTable = "extern const unsigned " + Target +
427a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick    "ForwardingPaths[] = {\n";
4282661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  BypassTable += " 0, // No itinerary\n";
429da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
4302661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each Itinerary across all processors, add a unique entry to the stages,
4312661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // operand cycles, and pipepine bypess tables. Then add the new Itinerary
4322661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // object with computed offsets to the ProcItinLists result.
433fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  unsigned StageCount = 1, OperandCycleCount = 1;
4343881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
4352661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
4362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
4372661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const CodeGenProcModel &ProcModel = *PI;
438da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
4392661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Add process itinerary to the list.
4402661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    ProcItinLists.resize(ProcItinLists.size()+1);
441d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick
4422661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // If this processor defines no itineraries, then leave the itinerary list
4432661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // empty.
4442661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
4452661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    if (ProcModel.ItinDefList.empty())
446d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick      continue;
447d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick
4482661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Reserve index==0 for NoItinerary.
4492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    ItinList.resize(SchedModels.numItineraryClasses()+1);
4502661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
4512661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = ProcModel.ItinsDef->getName();
452da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
453f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // For each itinerary data
4542661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    for (unsigned SchedClassIdx = 0,
4552661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick           SchedClassEnd = ProcModel.ItinDefList.size();
4562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
4572661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
458f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      // Next itinerary data
4592661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
460da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
461908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey      // Get string and stage count
462fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      std::string ItinStageString;
4632661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      unsigned NStages = 0;
4642661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      if (ItinData)
4652661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
466fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
467fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Get string and operand cycle count
468fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      std::string ItinOperandCycleString;
4692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      unsigned NOperandCycles = 0;
47063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng      std::string ItinBypassString;
4712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      if (ItinData) {
4722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
4732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                        NOperandCycles);
4742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
4752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryBypassString(Name, ItinData, ItinBypassString,
4762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                  NOperandCycles);
4772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      }
47863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
479fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Check to see if stage already exists and create if it doesn't
480fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      unsigned FindStage = 0;
481fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      if (NStages > 0) {
482fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        FindStage = ItinStageMap[ItinStageString];
483fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        if (FindStage == 0) {
484234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
485234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          StageTable += ItinStageString + ", // " + itostr(StageCount);
486234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          if (NStages > 1)
487234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick            StageTable += "-" + itostr(StageCount + NStages - 1);
488234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          StageTable += "\n";
489fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Record Itin class number.
490fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          ItinStageMap[ItinStageString] = FindStage = StageCount;
491fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          StageCount += NStages;
492fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        }
493fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      }
494da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
495fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Check to see if operand cycle already exists and create if it doesn't
496fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      unsigned FindOperandCycle = 0;
497fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      if (NOperandCycles > 0) {
4983881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
4993881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng        FindOperandCycle = ItinOperandMap[ItinOperandString];
500fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        if (FindOperandCycle == 0) {
501fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Emit as  cycle, // index
502234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          OperandCycleTable += ItinOperandCycleString + ", // ";
503234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          std::string OperandIdxComment = itostr(OperandCycleCount);
504234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          if (NOperandCycles > 1)
505234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick            OperandIdxComment += "-"
506234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick              + itostr(OperandCycleCount + NOperandCycles - 1);
507234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          OperandCycleTable += OperandIdxComment + "\n";
508fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Record Itin class number.
509da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick          ItinOperandMap[ItinOperandCycleString] =
510fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin            FindOperandCycle = OperandCycleCount;
51163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng          // Emit as bypass, // index
512234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
513fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          OperandCycleCount += NOperandCycles;
514fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        }
5150d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey      }
516da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5175f54ce347368105260be2cec497b6a4199dc5789Evan Cheng      // Set up itinerary as location and location + stage count
5182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
5195f54ce347368105260be2cec497b6a4199dc5789Evan Cheng      InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
5205f54ce347368105260be2cec497b6a4199dc5789Evan Cheng                                    FindOperandCycle,
5215f54ce347368105260be2cec497b6a4199dc5789Evan Cheng                                    FindOperandCycle + NOperandCycles};
5225f54ce347368105260be2cec497b6a4199dc5789Evan Cheng
523908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey      // Inject - empty slots will be 0, 0
5242661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      ItinList[SchedClassIdx] = Intinerary;
5250d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
5260d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
52763d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
5287f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey  // Closing stage
5292661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
530fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  StageTable += "};\n";
531fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
532fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Closing operand cycles
5332661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OperandCycleTable += "  0 // End operand cycles\n";
534fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OperandCycleTable += "};\n";
535fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
5362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  BypassTable += " 0 // End bypass tables\n";
53763d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  BypassTable += "};\n";
53863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
539fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Emit tables.
540fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OS << StageTable;
541fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OS << OperandCycleTable;
54263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  OS << BypassTable;
5430d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
5440d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
5450d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
5462661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitProcessorData - Generate data for processor itineraries that were
5472661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
5482661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// Itineraries for each processor. The Itinerary lists are indexed on
5492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// CodeGenSchedClass::Index.
5500d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
551234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trickvoid SubtargetEmitter::
5522661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitItineraries(raw_ostream &OS,
5532661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
554fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick
555cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  // Multiple processor models may share an itinerary record. Emit it once.
556cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  SmallPtrSet<Record*, 8> ItinsDefSet;
557cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
5582661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each processor's machine model
559f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<std::vector<InstrItinerary> >::iterator
5602661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      ProcItinListsIter = ProcItinLists.begin();
5612661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
56248605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
563cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
5642661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    Record *ItinsDef = PI->ItinsDef;
565cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick    if (!ItinsDefSet.insert(ItinsDef))
566cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick      continue;
567f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
568908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Get processor itinerary name
5692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = ItinsDef->getName();
570da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Get the itinerary list for the processor.
5722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
57348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
574fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick
5752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n";
5762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "static const llvm::InstrItinerary ";
5772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    if (ItinList.empty()) {
5782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      OS << '*' << Name << " = 0;\n";
5792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      continue;
5802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    }
581da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Begin processor itinerary table
5832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << Name << "[] = {\n";
5842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
5852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // For each itinerary class in CodeGenSchedClass::Index order.
5862661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
5872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      InstrItinerary &Intinerary = ItinList[j];
5882661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
5892661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      // Emit Itinerary in the form of
5902661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      // { firstStage, lastStage, firstCycle, lastCycle } // index
5912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      OS << "  { " <<
5922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.NumMicroOps << ", " <<
5932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.FirstStage << ", " <<
5942661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.LastStage << ", " <<
5952661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.FirstOperandCycle << ", " <<
5962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.LastOperandCycle << " }" <<
5972661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
5980d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
5992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // End processor itinerary table
6002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "  { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
601fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick    OS << "};\n";
6020d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
60310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey}
60410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
605c8e41c591741b3da1077f7000274ad040bef8002Sylvestre Ledru// Emit either the value defined in the TableGen Record, or the default
6062661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// value defined in the C++ header. The Record is null if the processor does not
6072661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// define a model.
6082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
6092661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                         const char *Name, char Separator) {
6102661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OS << "  ";
6112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  int V = R ? R->getValueAsInt(Name) : -1;
6122661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (V >= 0)
6132661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << V << Separator << " // " << Name;
6142661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  else
6152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "MCSchedModel::Default" << Name << Separator;
6162661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OS << '\n';
6172661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
6182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
61940096d26937cd47c865464bef7b28550bc20c631Andrew Trickvoid SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
62040096d26937cd47c865464bef7b28550bc20c631Andrew Trick                                              raw_ostream &OS) {
62140096d26937cd47c865464bef7b28550bc20c631Andrew Trick  char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
62240096d26937cd47c865464bef7b28550bc20c631Andrew Trick
62340096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "\n// {Name, NumUnits, SuperIdx}\n";
62440096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "static const llvm::MCProcResourceDesc "
62540096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << ProcModel.ModelName << "ProcResources" << "[] = {\n"
62640096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "  {DBGFIELD(\"InvalidUnit\")     0, 0}" << Sep << "\n";
62740096d26937cd47c865464bef7b28550bc20c631Andrew Trick
62840096d26937cd47c865464bef7b28550bc20c631Andrew Trick  for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
62940096d26937cd47c865464bef7b28550bc20c631Andrew Trick    Record *PRDef = ProcModel.ProcResourceDefs[i];
63040096d26937cd47c865464bef7b28550bc20c631Andrew Trick
63140096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Find the SuperIdx
63240096d26937cd47c865464bef7b28550bc20c631Andrew Trick    unsigned SuperIdx = 0;
63340096d26937cd47c865464bef7b28550bc20c631Andrew Trick    Record *SuperDef = 0;
63440096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PRDef->getValueInit("Super")->isComplete()) {
63540096d26937cd47c865464bef7b28550bc20c631Andrew Trick      SuperDef =
63640096d26937cd47c865464bef7b28550bc20c631Andrew Trick        SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
63740096d26937cd47c865464bef7b28550bc20c631Andrew Trick      SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
63840096d26937cd47c865464bef7b28550bc20c631Andrew Trick    }
63940096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Emit the ProcResourceDesc
64040096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (i+1 == e)
64140096d26937cd47c865464bef7b28550bc20c631Andrew Trick      Sep = ' ';
64240096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "  {DBGFIELD(\"" << PRDef->getName() << "\") ";
64340096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PRDef->getName().size() < 15)
64440096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS.indent(15 - PRDef->getName().size());
64540096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx
64640096d26937cd47c865464bef7b28550bc20c631Andrew Trick       << "}" << Sep << " // #" << i+1;
64740096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (SuperDef)
64840096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << ", Super=" << SuperDef->getName();
64940096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "\n";
65040096d26937cd47c865464bef7b28550bc20c631Andrew Trick  }
65140096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "};\n";
65240096d26937cd47c865464bef7b28550bc20c631Andrew Trick}
65340096d26937cd47c865464bef7b28550bc20c631Andrew Trick
65452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Find the WriteRes Record that defines processor resources for this
65552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// SchedWrite.
65652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew TrickRecord *SubtargetEmitter::FindWriteResources(
65752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  Record *WriteDef, const CodeGenProcModel &ProcModel) {
65852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
65952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check if the SchedWrite is already subtarget-specific and directly
66052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // specifies a set of processor resources.
66152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  if (WriteDef->isSubClassOf("SchedWriteRes"))
66252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    return WriteDef;
66352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
66452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check this processor's list of write resources.
66552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (RecIter WRI = ProcModel.WriteResDefs.begin(),
66652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
66752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!(*WRI)->isSubClassOf("WriteRes"))
66852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
66952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (WriteDef == (*WRI)->getValueAsDef("WriteType"))
67052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      return *WRI;
67152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
67252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  throw TGError(ProcModel.ModelDef->getLoc(),
67352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                std::string("Processor does not define resources for ")
67452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                + WriteDef->getName());
67552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
67652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
67752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// Find the ReadAdvance record for the given SchedRead on this processor or
67852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// return NULL.
67952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew TrickRecord *SubtargetEmitter::FindReadAdvance(Record *ReadDef,
68052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                          const CodeGenProcModel &ProcModel) {
68152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check for SchedReads that directly specify a ReadAdvance.
68252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  if (ReadDef->isSubClassOf("SchedReadAdvance"))
68352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    return ReadDef;
68452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
68552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check this processor's ReadAdvanceList.
68652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
68752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
68852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!(*RAI)->isSubClassOf("ReadAdvance"))
68952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
69052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (ReadDef == (*RAI)->getValueAsDef("ReadType"))
69152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      return *RAI;
69252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
69352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  if (ReadDef->getName() != "ReadDefault") {
69452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    throw TGError(ProcModel.ModelDef->getLoc(),
69552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  std::string("Processor does not define resources for ")
69652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  + ReadDef->getName());
69752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
69852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  return NULL;
69952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
70052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
70152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Generate the SchedClass table for this processor and update global
70252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// tables. Must be called for each processor in order.
70352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trickvoid SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
70452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                           SchedClassTables &SchedTables) {
70552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
70652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  if (!ProcModel.hasInstrSchedModel())
70752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    return;
70852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
70952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
71052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
71152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
71252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCTab.resize(SCTab.size() + 1);
71352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    MCSchedClassDesc &SCDesc = SCTab.back();
714e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    // SCDesc.Name is guarded by NDEBUG
71552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumMicroOps = 0;
71652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.BeginGroup = false;
71752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.EndGroup = false;
71852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.WriteProcResIdx = 0;
71952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.WriteLatencyIdx = 0;
72052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.ReadAdvanceIdx = 0;
72152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
72252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // A Variant SchedClass has no resources of its own.
72352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!SCI->Transitions.empty()) {
72452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
72552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
72652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
72752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
72852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Determine if the SchedClass is actually reachable on this processor. If
72952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // not don't try to locate the processor resources, it will fail.
73052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // If ProcIndices contains 0, this class applies to all processors.
73152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
73252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCI->ProcIndices[0] != 0) {
73352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
73452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                SCI->ProcIndices.end(), ProcModel.Index);
73552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (PIPos == SCI->ProcIndices.end())
73652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        continue;
73752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
73852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    IdxVec Writes = SCI->Writes;
73952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    IdxVec Reads = SCI->Reads;
74052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCI->ItinClassDef) {
74152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs");
74252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // Check this processor's itinerary class resources.
74352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (RecIter II = ProcModel.ItinRWDefs.begin(),
74452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
74552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
74652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
74752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick            != Matched.end()) {
74852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
74952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                              Writes, Reads);
75052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
75152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
75252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
75352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (Writes.empty()) {
75452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        DEBUG(dbgs() << ProcModel.ItinsDef->getName()
75552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick              << " does not have resources for itinerary class "
75652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick              << SCI->ItinClassDef->getName() << '\n');
75752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
75852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
75952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else if (!SCI->InstRWs.empty()) {
76052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      assert(SCI->Writes.empty() && SCI->Reads.empty() &&
76152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             "InstRW class should not have its own ReadWrites");
76252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      Record *RWDef = 0;
76352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
76452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick           RWI != RWE; ++RWI) {
76552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
76652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
76752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          RWDef = *RWI;
76852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
76952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
77052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
77152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (RWDef) {
77252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
77352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                            Writes, Reads);
77452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
77552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
77652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Sum resources across all operand writes.
77752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry> WriteProcResources;
77852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry> WriteLatencies;
7793b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    std::vector<std::string> WriterNames;
78052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
78152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
78252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxVec WriteSeq;
78352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedModels.expandRWSequence(*WI, WriteSeq, /*IsRead=*/false);
78452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
78552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // For each operand, create a latency entry.
78652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      MCWriteLatencyEntry WLEntry;
78752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WLEntry.Cycles = 0;
7883b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      unsigned WriteID = WriteSeq.back();
7893b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
7903b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      // If this Write is not referenced by a ReadAdvance, don't distinguish it
7913b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      // from other WriteLatency entries.
7923b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      if (!SchedModels.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef)) {
7933b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        WriteID = 0;
7943b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      }
7953b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WLEntry.WriteResourceID = WriteID;
79652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
79752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
79852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick           WSI != WSE; ++WSI) {
79952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
80052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        Record *WriteDef = SchedModels.getSchedWrite(*WSI).TheDef;
80152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        Record *WriteRes = FindWriteResources(WriteDef, ProcModel);
80252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
80352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        // Mark the parent class as invalid for unsupported write types.
80452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (WriteRes->getValueAsBit("Unsupported")) {
80552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
80652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
80752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
80852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
80952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
81052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
81152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
81252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
81352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        // Create an entry for each ProcResource listed in WriteRes.
81452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
81552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        std::vector<int64_t> Cycles =
81652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteRes->getValueAsListOfInts("ResourceCycles");
81752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        for (unsigned PRIdx = 0, PREnd = PRVec.size();
81852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             PRIdx != PREnd; ++PRIdx) {
81952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          MCWriteProcResEntry WPREntry;
82052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
82152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
82252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          if (Cycles.size() > PRIdx)
82352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick            WPREntry.Cycles = Cycles[PRIdx];
82452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          else
82552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick            WPREntry.Cycles = 1;
82652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteProcResources.push_back(WPREntry);
82752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
82852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
82952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.push_back(WLEntry);
83052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
83152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Create an entry for each operand Read in this SchedClass.
83252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Entries must be sorted first by UseIdx then by WriteResourceID.
83352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    for (unsigned UseIdx = 0, EndIdx = Reads.size();
83452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         UseIdx != EndIdx; ++UseIdx) {
83552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      Record *ReadDef = SchedModels.getSchedRead(Reads[UseIdx]).TheDef;
83652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      Record *ReadAdvance = FindReadAdvance(ReadDef, ProcModel);
83752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (!ReadAdvance)
83852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        continue;
83952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
84052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // Mark the parent class as invalid for unsupported write types.
84152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (ReadAdvance->getValueAsBit("Unsupported")) {
84252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
84352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        break;
84452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
84552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
84652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxVec WriteIDs;
84752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (ValidWrites.empty())
84852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        WriteIDs.push_back(0);
84952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      else {
85052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
85152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             VWI != VWE; ++VWI) {
85252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
85352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
85452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
85552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::sort(WriteIDs.begin(), WriteIDs.end());
85652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
85752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        MCReadAdvanceEntry RAEntry;
85852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.UseIdx = UseIdx;
85952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.WriteResourceID = *WI;
86052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
86152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        ReadAdvanceEntries.push_back(RAEntry);
86252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
86352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
86452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
86552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteProcResources.clear();
86652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.clear();
86752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      ReadAdvanceEntries.clear();
86852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
86952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Add the information for this SchedClass to the global tables using basic
87052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // compression.
87152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    //
87252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // WritePrecRes entries are sorted by ProcResIdx.
87352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::sort(WriteProcResources.begin(), WriteProcResources.end(),
87452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick              LessWriteProcResources());
87552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
87652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumWriteProcResEntries = WriteProcResources.size();
87752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry>::iterator WPRPos =
87852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.WriteProcResources.begin(),
87952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.WriteProcResources.end(),
88052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  WriteProcResources.begin(), WriteProcResources.end());
88152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (WPRPos != SchedTables.WriteProcResources.end())
88252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
88352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
88452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
88552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
88652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                            WriteProcResources.end());
88752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
88852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Latency entries must remain in operand order.
88952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
89052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry>::iterator WLPos =
89152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.WriteLatencies.begin(),
89252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.WriteLatencies.end(),
89352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  WriteLatencies.begin(), WriteLatencies.end());
8943b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    if (WLPos != SchedTables.WriteLatencies.end()) {
8953b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      unsigned idx = WLPos - SchedTables.WriteLatencies.begin();
8963b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SCDesc.WriteLatencyIdx = idx;
8973b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i)
8983b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) ==
8993b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick            std::string::npos) {
9003b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick          SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i];
9013b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        }
9023b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    }
90352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
90452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
9053b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(),
9063b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                        WriteLatencies.begin(),
9073b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                        WriteLatencies.end());
9083b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SchedTables.WriterNames.insert(SchedTables.WriterNames.end(),
9093b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                     WriterNames.begin(), WriterNames.end());
91052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
91152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // ReadAdvanceEntries must remain in operand order.
91252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
91352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry>::iterator RAPos =
91452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.ReadAdvanceEntries.begin(),
91552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.ReadAdvanceEntries.end(),
91652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
91752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (RAPos != SchedTables.ReadAdvanceEntries.end())
91852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
91952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
92052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
92152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
92252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                            ReadAdvanceEntries.end());
92352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
92452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
92552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
92652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
927544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick// Emit SchedClass tables for all processors and associated global tables.
928544c88039f16706d6764c65fda276a11f2c586d6Andrew Trickvoid SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
929544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick                                            raw_ostream &OS) {
930544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global WriteProcResTable.
931544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {ProcResourceIdx, Cycles}\n"
932544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCWriteProcResEntry "
933544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteProcResTable[] = {\n"
934544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  { 0,  0}, // Invalid\n";
935544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
936544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       WPRIdx != WPREnd; ++WPRIdx) {
937544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
938544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
939544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", WPREntry.Cycles) << "}";
940544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (WPRIdx + 1 < WPREnd)
941544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
942544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << " // #" << WPRIdx << '\n';
943544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
944544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "WriteProcResTable\n";
945544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
946544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global WriteLatencyTable.
947544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {Cycles, WriteResourceID}\n"
948544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCWriteLatencyEntry "
949544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteLatencyTable[] = {\n"
950544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  { 0,  0}, // Invalid\n";
951544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
952544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       WLIdx != WLEnd; ++WLIdx) {
953544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
954544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << format("%2d", WLEntry.Cycles) << ", "
955544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", WLEntry.WriteResourceID) << "}";
956544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (WLIdx + 1 < WLEnd)
957544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
9583b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n';
959544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
960544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "WriteLatencyTable\n";
961544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
962544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global ReadAdvanceTable.
963544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
964544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCReadAdvanceEntry "
965544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "ReadAdvanceTable[] = {\n"
966544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  {0,  0,  0}, // Invalid\n";
967544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
968544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       RAIdx != RAEnd; ++RAIdx) {
969544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
970544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << RAEntry.UseIdx << ", "
971544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", RAEntry.WriteResourceID) << ", "
972544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", RAEntry.Cycles) << "}";
973544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (RAIdx + 1 < RAEnd)
974544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
975544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << " // #" << RAIdx << '\n';
976544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
977544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "ReadAdvanceTable\n";
978544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
979544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit a SchedClass table for each processor.
980544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
981544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
982544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (!PI->hasInstrSchedModel())
983544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      continue;
984544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
985544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    std::vector<MCSchedClassDesc> &SCTab =
986544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      SchedTables.ProcSchedClasses[1 + PI - SchedModels.procModelBegin()];
987544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
988544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
989544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
990544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "static const llvm::MCSchedClassDesc "
991544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << PI->ModelName << "SchedClasses[] = {\n";
992544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
993544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    // The first class is always invalid. We no way to distinguish it except by
994544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    // name and position.
995e4095f95ac2480aabbe289f41723b53ac1c82a98Andrew Trick    assert(SchedModels.getSchedClass(0).Name == "NoItinerary"
996544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick           && "invalid class not first");
997544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {DBGFIELD(\"InvalidSchedClass\")  "
998544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << MCSchedClassDesc::InvalidNumMicroOps
999544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << ", 0, 0,  0, 0,  0, 0,  0, 0},\n";
1000544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1001544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
1002544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      MCSchedClassDesc &MCDesc = SCTab[SCIdx];
1003544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
1004544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << "  {DBGFIELD(\"" << SchedClass.Name << "\") ";
1005544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      if (SchedClass.Name.size() < 18)
1006544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick        OS.indent(18 - SchedClass.Name.size());
1007544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << MCDesc.NumMicroOps
1008544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
1009544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.WriteProcResIdx)
1010544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumWriteProcResEntries
1011544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.WriteLatencyIdx)
1012544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumWriteLatencyEntries
1013544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.ReadAdvanceIdx)
1014544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumReadAdvanceEntries << "}";
1015544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      if (SCIdx + 1 < SCEnd)
1016544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick        OS << ',';
1017544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << " // #" << SCIdx << '\n';
1018544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    }
1019544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "}; // " << PI->ModelName << "SchedClasses\n";
1020544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1021544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick}
1022544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
10232661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
10242661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each processor model.
10252661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
10262661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
102740096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Emit processor resource table.
102840096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PI->hasInstrSchedModel())
102940096d26937cd47c865464bef7b28550bc20c631Andrew Trick      EmitProcessorResources(*PI, OS);
103040096d26937cd47c865464bef7b28550bc20c631Andrew Trick    else if(!PI->ProcResourceDefs.empty())
103140096d26937cd47c865464bef7b28550bc20c631Andrew Trick      throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
103252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                    "ProcResources without defining WriteRes SchedWriteRes");
103340096d26937cd47c865464bef7b28550bc20c631Andrew Trick
10342661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Begin processor itinerary properties
10352661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n";
10362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
10372661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
10382661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
10392661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
10402661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
1041d43b5c97cff06d7840b974ca84fa0639d2567968Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
1042e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << "  " << PI->Index << ", // Processor ID\n";
1043e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    if (PI->hasInstrSchedModel())
1044e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick      OS << "  " << PI->ModelName << "ProcResources" << ",\n"
1045e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << PI->ModelName << "SchedClasses" << ",\n"
1046e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << PI->ProcResourceDefs.size()+1 << ",\n"
1047e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << (SchedModels.schedClassEnd()
1048e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick                     - SchedModels.schedClassBegin()) << ",\n";
1049e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    else
1050e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick      OS << "  0, 0, 0, 0, // No instruction-level machine model.\n";
10512661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    if (SchedModels.hasItineraryClasses())
105240096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << "  " << PI->ItinsDef->getName() << ");\n";
10532661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    else
105440096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << "  0); // No Itinerary\n";
10552661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
10562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
10572661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
105810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey//
105910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey// EmitProcessorLookup - generate cpu name to itinerary lookup table.
106010b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey//
10611a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
106210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // Gather and sort processor information
106310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  std::vector<Record*> ProcessorList =
106410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey                          Records.getAllDerivedDefinitions("Processor");
106542d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
106610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
106710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // Begin processor table
106810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "\n";
106910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
10701a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetInfoKV "
10712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick     << Target << "ProcSchedKV[] = {\n";
1072da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
107310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // For each processor
107410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
107510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Next processor
107610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    Record *Processor = ProcessorList[i];
107710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
10784222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Processor->getValueAsString("Name");
10792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &ProcModelName =
108048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SchedModels.getModelForProc(Processor).ModelName;
1081da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
108210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Emit as { "cpu", procinit },
108340096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "  { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
1084da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
108510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on ''if more in the list'' emit comma
108610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    if (++i < N) OS << ",";
1087da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
108810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    OS << "\n";
108910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  }
1090da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
109110b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // End processor table
109210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "};\n";
10930d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
10940d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
10950d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
10962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
10970d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
10982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
109940096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "#ifdef DBGFIELD\n"
110040096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
110140096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#endif\n"
110240096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#ifndef NDEBUG\n"
110340096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#define DBGFIELD(x) x,\n"
110440096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#else\n"
110540096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#define DBGFIELD(x)\n"
110640096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#endif\n";
110740096d26937cd47c865464bef7b28550bc20c631Andrew Trick
11082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
11092661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<std::vector<InstrItinerary> > ProcItinLists;
11106cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey    // Emit the stage data
11112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitStageAndOperandCycleData(OS, ProcItinLists);
11122661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitItineraries(OS, ProcItinLists);
11136cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey  }
1114544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// ===============================================================\n"
1115544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "// Data tables for the new per-operand machine model.\n";
111640096d26937cd47c865464bef7b28550bc20c631Andrew Trick
111752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  SchedClassTables SchedTables;
111852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
111952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
112052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    GenSchedClassTables(*PI, SchedTables);
112152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
1122544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitSchedClassTables(SchedTables, OS);
1123544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1124544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit the processor machine model
1125544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitProcessorModels(OS);
1126544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit the processor lookup data
1127544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitProcessorLookup(OS);
112852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
112940096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "#undef DBGFIELD";
11300d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
11310d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
11324d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trickvoid SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName,
11334d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                                             raw_ostream &OS) {
11344d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  OS << "unsigned " << ClassName
11354d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
11364d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << " const TargetSchedModel *SchedModel) const {\n";
11374d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
11384d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
11394d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  std::sort(Prologs.begin(), Prologs.end(), LessRecord());
11404d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  for (std::vector<Record*>::const_iterator
11414d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) {
11424d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << (*PI)->getValueAsString("Code") << '\n';
11434d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
11444d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  IdxVec VariantClasses;
11454d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
11464d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
11474d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    if (SCI->Transitions.empty())
11484d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      continue;
11494d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    VariantClasses.push_back(SCI - SchedModels.schedClassBegin());
11504d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
11514d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  if (!VariantClasses.empty()) {
11524d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << "  switch (SchedClass) {\n";
11534d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end();
11544d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         VCI != VCE; ++VCI) {
11554d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI);
11564d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      OS << "  case " << *VCI << ": // " << SC.Name << '\n';
11574d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      IdxVec ProcIndices;
11584d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      for (std::vector<CodeGenSchedTransition>::const_iterator
11594d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             TI = SC.Transitions.begin(), TE = SC.Transitions.end();
11604d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           TI != TE; ++TI) {
11614d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        IdxVec PI;
11624d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(),
11634d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                       ProcIndices.begin(), ProcIndices.end(),
11644d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                       std::back_inserter(PI));
11654d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        ProcIndices.swap(PI);
11664d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      }
11674d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
11684d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           PI != PE; ++PI) {
11694d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    ";
11704d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        if (*PI != 0)
11714d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << "if (SchedModel->getProcessorID() == " << *PI << ") ";
11724d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName
11734d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           << '\n';
11744d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        for (std::vector<CodeGenSchedTransition>::const_iterator
11754d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick               TI = SC.Transitions.begin(), TE = SC.Transitions.end();
11764d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             TI != TE; ++TI) {
11774d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << "      if (";
11784d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          if (*PI != 0 && !std::count(TI->ProcIndices.begin(),
11794d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                                      TI->ProcIndices.end(), *PI)) {
11804d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick              continue;
11814d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          }
11824d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end();
11834d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick               RI != RE; ++RI) {
11844d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick            if (RI != TI->PredTerm.begin())
11854d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick              OS << "\n          && ";
11864d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick            OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
11874d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          }
11884d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << ")\n"
11894d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             << "        return " << TI->ToClassIdx << "; // "
11904d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n';
11914d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        }
11924d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    }\n";
11934d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        if (*PI == 0)
11944d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          break;
11954d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      }
11964d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      unsigned SCIdx = 0;
11974d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      if (SC.ItinClassDef)
11984d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        SCIdx = SchedModels.getSchedClassIdxForItin(SC.ItinClassDef);
11994d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      else
12004d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        SCIdx = SchedModels.findSchedClassIdx(SC.Writes, SC.Reads);
12014d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      if (SCIdx != *VCI)
12024d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    return " << SCIdx << ";\n";
12034d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      OS << "    break;\n";
12044d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    }
12054d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << "  };\n";
12064d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
12074d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  OS << "  report_fatal_error(\"Expected a variant SchedClass\");\n"
12084d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "} // " << ClassName << "::resolveSchedClass\n";
12094d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick}
12104d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
12110d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
1212581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// ParseFeaturesFunction - Produces a subtarget specific function for parsing
1213581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// the subtarget features string.
1214581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey//
121594214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengvoid SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
121694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng                                             unsigned NumFeatures,
121794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng                                             unsigned NumProcs) {
1218f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> Features =
1219f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                       Records.getAllDerivedDefinitions("SubtargetFeature");
122042d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(Features.begin(), Features.end(), LessRecord());
1221581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey
1222da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
1223da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick     << "// subtarget options.\n"
1224276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng     << "void llvm::";
1225581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << Target;
12260ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
1227f0fd3afeffcb41202147f755bf770061f189a42bDavid Greene     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
12283f696e568bae8afa5986e7af48156c2bac041ba7Hal Finkel     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
122994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
123094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (Features.empty()) {
123194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "}\n";
123294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return;
123394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  }
123494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
123534aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick  OS << "  InitMCProcessorInfo(CPU, FS);\n"
123634aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick     << "  uint64_t Bits = getFeatureBits();\n";
12374222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
1238f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  for (unsigned i = 0; i < Features.size(); i++) {
1239f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next record
1240f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *R = Features[i];
12414222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Instance = R->getName();
12424222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Value = R->getValueAsString("Value");
12434222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Attribute = R->getValueAsString("Attribute");
124419c95507443ebd4f1cee80917d540c8bd27f8fe1Evan Cheng
1245db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen    if (Value=="true" || Value=="false")
12460ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      OS << "  if ((Bits & " << Target << "::"
12470ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng         << Instance << ") != 0) "
1248db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen         << Attribute << " = " << Value << ";\n";
1249db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen    else
12500ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      OS << "  if ((Bits & " << Target << "::"
12510ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng         << Instance << ") != 0 && "
125294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng         << Attribute << " < " << Value << ") "
125394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng         << Attribute << " = " << Value << ";\n";
12546cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey  }
125541a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov
1256276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng  OS << "}\n";
1257581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey}
1258581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey
125941a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov//
1260b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// SubtargetEmitter::run - Main subtarget enumeration emitter.
1261b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
12621a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::run(raw_ostream &OS) {
12636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
1264b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
1265ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
1266ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "#undef GET_SUBTARGETINFO_ENUM\n";
1267ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng
1268ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "namespace llvm {\n";
1269ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  Enumeration(OS, "SubtargetFeature", true);
1270ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "} // End llvm namespace \n";
1271ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
1272ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng
127394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
127494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
1275928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
127694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
1277c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0
1278c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "namespace {\n";
1279c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif
128094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumFeatures = FeatureKeyValues(OS);
1281c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
128294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumProcs = CPUKeyValues(OS);
1283c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
12842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  EmitSchedModel(OS);
1285c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
1286c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0
1287c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "}\n";
1288c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif
128994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
129094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  // MCInstrInfo initialization routine.
129194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "static inline void Init" << Target
129259ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "MCSubtargetInfo(MCSubtargetInfo *II, "
129359ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "StringRef TT, StringRef CPU, StringRef FS) {\n";
129459ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng  OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
129594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumFeatures)
129694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "FeatureKV, ";
129794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
129894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
129994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumProcs)
130094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "SubTypeKV, ";
130194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
130294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
1303544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << '\n'; OS.indent(22);
1304e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << Target << "ProcSchedKV, "
1305e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteProcResTable, "
1306e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteLatencyTable, "
1307e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "ReadAdvanceTable, ";
13082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
1309e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << '\n'; OS.indent(22);
1310e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << Target << "Stages, "
131194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "OperandCycles, "
1312a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick       << Target << "ForwardingPaths, ";
131394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  } else
1314e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << "0, 0, 0, ";
131594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
131694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
131794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
131894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
131994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
132094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
132194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
132294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
132394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
132494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#include \"llvm/Support/Debug.h\"\n";
132594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#include \"llvm/Support/raw_ostream.h\"\n";
132694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  ParseFeaturesFunction(OS, NumFeatures, NumProcs);
132794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
132894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
132994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
13305b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng  // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
133194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
133294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_HEADER\n";
133394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
133494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  std::string ClassName = Target + "GenSubtargetInfo";
133594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
1336dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta  OS << "class DFAPacketizer;\n";
13375b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng  OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
13380ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
13390ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "StringRef FS);\n"
1340dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta     << "public:\n"
13414d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "  unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *DefMI,"
13424d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << " const TargetSchedModel *SchedModel) const;\n"
1343464f3a332f81364ee09794f9502f0b25671149c6Sebastian Pop     << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
1344dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta     << " const;\n"
134594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng     << "};\n";
134694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
134794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
134894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
134994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
135094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
135194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_CTOR\n";
135294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
1353ee290ba35af88393ba18dd19e6e39d50c7872534Andrew Trick  OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n";
135494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
13551a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
13561a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
1357544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
1358544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCWriteProcResEntry "
1359544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteProcResTable[];\n";
1360544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCWriteLatencyEntry "
1361544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteLatencyTable[];\n";
1362544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCReadAdvanceEntry "
1363544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "ReadAdvanceTable[];\n";
1364544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
13652661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
13661a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer    OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
13671a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer    OS << "extern const unsigned " << Target << "OperandCycles[];\n";
1368a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick    OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
1369c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  }
1370c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng
13710ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
13720ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "StringRef FS)\n"
13735b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng     << "  : TargetSubtargetInfo() {\n"
137459ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "  InitMCSubtargetInfo(TT, CPU, FS, ";
137594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumFeatures)
137694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "FeatureKV, ";
137794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
137894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
137994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumProcs)
138094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "SubTypeKV, ";
138194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
138294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
1383e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << '\n'; OS.indent(22);
1384e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << Target << "ProcSchedKV, "
1385e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteProcResTable, "
1386e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteLatencyTable, "
1387e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "ReadAdvanceTable, ";
1388e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << '\n'; OS.indent(22);
13892661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
1390e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << Target << "Stages, "
139194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "OperandCycles, "
1392a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick       << Target << "ForwardingPaths, ";
139394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  } else
1394e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << "0, 0, 0, ";
139594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1396544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
13974d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  EmitSchedModelHelpers(ClassName, OS);
13984d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
139994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
140094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
140194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
1402b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
14036f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
14046f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace llvm {
14056f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
14066f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenvoid EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
14072661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  CodeGenTarget CGTarget(RK);
14082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SubtargetEmitter(RK, CGTarget).run(OS);
14096f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen}
14106f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
14116f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End llvm namespace
1412