SubtargetEmitter.cpp revision 92649883119aaa8edd9ccf612eaaff5ccc8fcc77
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);
8492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *FindWriteResources(const CodeGenSchedRW &SchedWrite,
8552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                             const CodeGenProcModel &ProcModel);
8692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
8792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                          const CodeGenProcModel &ProcModel);
8852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  void GenSchedClassTables(const CodeGenProcModel &ProcModel,
8952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                           SchedClassTables &SchedTables);
90544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitProcessorModels(raw_ostream &OS);
926f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void EmitProcessorLookup(raw_ostream &OS);
934d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  void EmitSchedModelHelpers(std::string ClassName, raw_ostream &OS);
942661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitSchedModel(raw_ostream &OS);
956f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
966f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                             unsigned NumProcs);
976f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
986f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenpublic:
992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
1002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
1016f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1026f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void run(raw_ostream &o);
1036f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1046f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen};
1056f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End anonymous namespace
1066f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1077dc02047fbb4b014e914458f54ea539c8ae58316Jim Laskey//
108581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// Enumeration - Emit the specified class as an enumeration.
109b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
1101a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::Enumeration(raw_ostream &OS,
111581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey                                   const char *ClassName,
112581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey                                   bool isBits) {
113908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Get all records of class and sort
114f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
11542d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(DefList.begin(), DefList.end(), LessRecord());
1164bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey
117b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  unsigned N = DefList.size();
11894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (N == 0)
11994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return;
120b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  if (N > 64) {
121b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    errs() << "Too many (> 64) subtarget features!\n";
122b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    exit(1);
123b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  }
124b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng
12594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace " << Target << " {\n";
12694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
127ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  // For bit flag enumerations with more than 32 items, emit constants.
128ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  // Emit an enum for everything else.
129ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  if (isBits && N > 32) {
130ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // For each record
131ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    for (unsigned i = 0; i < N; i++) {
132ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Next record
133ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      Record *Def = DefList[i];
13494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
135ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Get and emit name and expression (1 << i)
136ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "  const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
137ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    }
138ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  } else {
139ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // Open enumeration
140ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    OS << "enum {\n";
141da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
142ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // For each record
143ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    for (unsigned i = 0; i < N;) {
144ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Next record
145ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      Record *Def = DefList[i];
146da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
147ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Get and emit name
148ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "  " << Def->getName();
149908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
150ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // If bit flags then emit expression (1 << i)
151ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      if (isBits)  OS << " = " << " 1ULL << " << i;
152da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
153ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Depending on 'if more in the list' emit comma
154ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      if (++i < N) OS << ",";
155ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen
156ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "\n";
157ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    }
158da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
159ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // Close enumeration
160ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    OS << "};\n";
161ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  }
16294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
16394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "}\n";
164b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
165b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
166b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
1674222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// FeatureKeyValues - Emit data of all the subtarget features.  Used by the
1684222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// command line.
169b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
17094214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
171908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Gather and sort all the features
172f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> FeatureList =
173f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                           Records.getAllDerivedDefinitions("SubtargetFeature");
17494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
17594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (FeatureList.empty())
17694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return 0;
17794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
1787c9a7728d9dd248ebee8f2dd969d303711d487a9Jim Grosbach  std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
179b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
180908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin feature table
181581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << "// Sorted (by key) array of values for CPU features.\n"
1821a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetFeatureKV " << Target
1831a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "FeatureKV[] = {\n";
184da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
185908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each feature
18694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumFeatures = 0;
187dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey  for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
188f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next feature
189f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *Feature = FeatureList[i];
190f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
1914222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Feature->getName();
1924222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &CommandLineName = Feature->getValueAsString("Name");
1934222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Desc = Feature->getValueAsString("Desc");
194da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
195dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey    if (CommandLineName.empty()) continue;
196da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
197da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach    // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
198b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    OS << "  { "
199f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey       << "\"" << CommandLineName << "\", "
200b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"" << Desc << "\", "
20194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "::" << Name << ", ";
2024222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
203da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick    const std::vector<Record*> &ImpliesList =
2044222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      Feature->getValueAsListOfDefs("Implies");
205da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
2064222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    if (ImpliesList.empty()) {
207b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng      OS << "0ULL";
2084222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    } else {
2094222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
21094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng        OS << Target << "::" << ImpliesList[j]->getName();
2114222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        if (++j < M) OS << " | ";
2124222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      }
2134222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    }
2144222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
2154222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    OS << " }";
21694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    ++NumFeatures;
217da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
21810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on 'if more in the list' emit comma
219dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey    if ((i + 1) < N) OS << ",";
220da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
221f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    OS << "\n";
222b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  }
223da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
224908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // End feature table
225b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  OS << "};\n";
226b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
22794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  return NumFeatures;
228b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
229b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
230b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
231b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// CPUKeyValues - Emit data of all the subtarget processors.  Used by command
232b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// line.
233b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
23494214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
235908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Gather and sort processor information
236f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> ProcessorList =
237f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                          Records.getAllDerivedDefinitions("Processor");
23842d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
239b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
240908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin processor table
241581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << "// Sorted (by key) array of values for CPU subtype.\n"
2421a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetFeatureKV " << Target
2431a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "SubTypeKV[] = {\n";
244da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
245908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each processor
246f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
247f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next processor
248f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *Processor = ProcessorList[i];
249f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
2504222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Processor->getValueAsString("Name");
251da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick    const std::vector<Record*> &FeatureList =
252b0e103d46bf8799ac5523157a6ed4a78d1751a89Chris Lattner      Processor->getValueAsListOfDefs("Features");
253da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
254908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Emit as { "cpu", "description", f1 | f2 | ... fn },
255b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    OS << "  { "
256b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"" << Name << "\", "
257b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"Select the " << Name << " processor\", ";
258da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
259f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    if (FeatureList.empty()) {
260b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng      OS << "0ULL";
261b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    } else {
262f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      for (unsigned j = 0, M = FeatureList.size(); j < M;) {
26394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng        OS << Target << "::" << FeatureList[j]->getName();
264f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey        if (++j < M) OS << " | ";
2654bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey      }
2664bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey    }
267da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
2684222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    // The "0" is for the "implies" section of this data structure.
269b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    OS << ", 0ULL }";
270da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
27110b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on 'if more in the list' emit comma
272f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    if (++i < N) OS << ",";
273da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
274f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    OS << "\n";
2754bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey  }
276da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
277908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // End processor table
278b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  OS << "};\n";
279b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
28094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  return ProcessorList.size();
2814bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey}
282b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
283581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey//
284fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryStageString - Compose a string containing the stage
285fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// data initialization for the specified itinerary.  N is the number
286fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// of stages.
2870d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
288928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikovvoid SubtargetEmitter::FormItineraryStageString(const std::string &Name,
289928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov                                                Record *ItinData,
290fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                                                std::string &ItinString,
291fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                                                unsigned &NStages) {
292f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  // Get states list
2934222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling  const std::vector<Record*> &StageList =
2944222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    ItinData->getValueAsListOfDefs("Stages");
295908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
296908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each stage
297f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  unsigned N = NStages = StageList.size();
2988dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb  for (unsigned i = 0; i < N;) {
299f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next stage
3004222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const Record *Stage = StageList[i];
301da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
30296085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
3030d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    int Cycles = Stage->getValueAsInt("Cycles");
3047f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey    ItinString += "  { " + itostr(Cycles) + ", ";
305da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
306f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Get unit list
3074222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
308da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
309908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // For each unit
310f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    for (unsigned j = 0, M = UnitList.size(); j < M;) {
311f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      // Add name and bitwise or
312928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov      ItinString += Name + "FU::" + UnitList[j]->getName();
313f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      if (++j < M) ItinString += " | ";
3140d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
315da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
3161a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin    int TimeInc = Stage->getValueAsInt("TimeInc");
3171a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin    ItinString += ", " + itostr(TimeInc);
3181a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin
31996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    int Kind = Stage->getValueAsInt("Kind");
32096085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
32196085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov
322908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Close off stage
323908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    ItinString += " }";
3248dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb    if (++i < N) ItinString += ", ";
3250d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
3260d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
3270d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
3280d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
329fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryOperandCycleString - Compose a string containing the
330fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// operand cycle initialization for the specified itinerary.  N is the
331fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// number of operands that has cycles specified.
3320d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
333fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwinvoid SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
334fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                         std::string &ItinString, unsigned &NOperandCycles) {
335fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Get operand cycle list
336fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  const std::vector<int64_t> &OperandCycleList =
337fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    ItinData->getValueAsListOfInts("OperandCycles");
338fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
339fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // For each operand cycle
340fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  unsigned N = NOperandCycles = OperandCycleList.size();
341fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  for (unsigned i = 0; i < N;) {
342fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    // Next operand cycle
343fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    const int OCycle = OperandCycleList[i];
344da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
345fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    ItinString += "  " + itostr(OCycle);
346fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    if (++i < N) ItinString += ", ";
347fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  }
348fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin}
349fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
35063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Chengvoid SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
35163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 Record *ItinData,
35263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 std::string &ItinString,
35363d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 unsigned NOperandCycles) {
35463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  const std::vector<Record*> &BypassList =
35563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinData->getValueAsListOfDefs("Bypasses");
35663d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  unsigned N = BypassList.size();
3573881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  unsigned i = 0;
3583881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  for (; i < N;) {
35963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinString += Name + "Bypass::" + BypassList[i]->getName();
3603881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (++i < NOperandCycles) ItinString += ", ";
36163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  }
3623881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  for (; i < NOperandCycles;) {
36363d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinString += " 0";
3643881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (++i < NOperandCycles) ItinString += ", ";
36563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  }
36663d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng}
36763d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
368fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin//
3692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
3702661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
3712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// by CodeGenSchedClass::Index.
372fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin//
3732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::
3742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitStageAndOperandCycleData(raw_ostream &OS,
3752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                             std::vector<std::vector<InstrItinerary> >
3762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                               &ProcItinLists) {
377908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
378cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  // Multiple processor models may share an itinerary record. Emit it once.
379cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  SmallPtrSet<Record*, 8> ItinsDefSet;
380cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
381928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov  // Emit functional units for all the itineraries.
3822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
3832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
384928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
385cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick    if (!ItinsDefSet.insert(PI->ItinsDef))
386cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick      continue;
387cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
3882661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
389928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    if (FUs.empty())
390928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov      continue;
391928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
3922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = PI->ItinsDef->getName();
3932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n// Functional units for \"" << Name << "\"\n"
394928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov       << "namespace " << Name << "FU {\n";
395928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
396928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
397b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      OS << "  const unsigned " << FUs[j]->getName()
398b460a3382961c5be9952a75d46228f624edbd39fHal Finkel         << " = 1 << " << j << ";\n";
399928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
400928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    OS << "}\n";
40163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4022661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
4033881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (BPs.size()) {
4043881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
4053881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng         << "\"\n" << "namespace " << Name << "Bypass {\n";
40663d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4071a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer      OS << "  const unsigned NoBypass = 0;\n";
4083881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
4091a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer        OS << "  const unsigned " << BPs[j]->getName()
4103881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng           << " = 1 << " << j << ";\n";
41163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4123881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      OS << "}\n";
4133881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    }
414928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov  }
415928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
416908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin stages table
4171a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string StageTable = "\nextern const llvm::InstrStage " + Target +
4181a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer                           "Stages[] = {\n";
41996085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
420da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
421fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Begin operand cycle table
4221a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string OperandCycleTable = "extern const unsigned " + Target +
42394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    "OperandCycles[] = {\n";
424fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OperandCycleTable += "  0, // No itinerary\n";
42563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
42663d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  // Begin pipeline bypass table
4271a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string BypassTable = "extern const unsigned " + Target +
428a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick    "ForwardingPaths[] = {\n";
4292661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  BypassTable += " 0, // No itinerary\n";
430da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
4312661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each Itinerary across all processors, add a unique entry to the stages,
4322661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // operand cycles, and pipepine bypess tables. Then add the new Itinerary
4332661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // object with computed offsets to the ProcItinLists result.
434fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  unsigned StageCount = 1, OperandCycleCount = 1;
4353881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
4362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
4372661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
4382661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const CodeGenProcModel &ProcModel = *PI;
439da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
4402661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Add process itinerary to the list.
4412661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    ProcItinLists.resize(ProcItinLists.size()+1);
442d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick
4432661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // If this processor defines no itineraries, then leave the itinerary list
4442661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // empty.
4452661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
4462661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    if (ProcModel.ItinDefList.empty())
447d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick      continue;
448d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick
4492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Reserve index==0 for NoItinerary.
4502661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    ItinList.resize(SchedModels.numItineraryClasses()+1);
4512661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
4522661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = ProcModel.ItinsDef->getName();
453da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
454f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // For each itinerary data
4552661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    for (unsigned SchedClassIdx = 0,
4562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick           SchedClassEnd = ProcModel.ItinDefList.size();
4572661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
4582661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
459f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      // Next itinerary data
4602661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
461da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
462908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey      // Get string and stage count
463fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      std::string ItinStageString;
4642661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      unsigned NStages = 0;
4652661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      if (ItinData)
4662661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
467fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
468fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Get string and operand cycle count
469fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      std::string ItinOperandCycleString;
4702661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      unsigned NOperandCycles = 0;
47163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng      std::string ItinBypassString;
4722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      if (ItinData) {
4732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
4742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                        NOperandCycles);
4752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
4762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryBypassString(Name, ItinData, ItinBypassString,
4772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                  NOperandCycles);
4782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      }
47963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
480fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Check to see if stage already exists and create if it doesn't
481fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      unsigned FindStage = 0;
482fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      if (NStages > 0) {
483fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        FindStage = ItinStageMap[ItinStageString];
484fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        if (FindStage == 0) {
485234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
486234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          StageTable += ItinStageString + ", // " + itostr(StageCount);
487234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          if (NStages > 1)
488234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick            StageTable += "-" + itostr(StageCount + NStages - 1);
489234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          StageTable += "\n";
490fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Record Itin class number.
491fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          ItinStageMap[ItinStageString] = FindStage = StageCount;
492fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          StageCount += NStages;
493fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        }
494fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      }
495da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
496fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Check to see if operand cycle already exists and create if it doesn't
497fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      unsigned FindOperandCycle = 0;
498fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      if (NOperandCycles > 0) {
4993881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
5003881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng        FindOperandCycle = ItinOperandMap[ItinOperandString];
501fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        if (FindOperandCycle == 0) {
502fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Emit as  cycle, // index
503234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          OperandCycleTable += ItinOperandCycleString + ", // ";
504234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          std::string OperandIdxComment = itostr(OperandCycleCount);
505234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          if (NOperandCycles > 1)
506234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick            OperandIdxComment += "-"
507234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick              + itostr(OperandCycleCount + NOperandCycles - 1);
508234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          OperandCycleTable += OperandIdxComment + "\n";
509fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Record Itin class number.
510da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick          ItinOperandMap[ItinOperandCycleString] =
511fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin            FindOperandCycle = OperandCycleCount;
51263d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng          // Emit as bypass, // index
513234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
514fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          OperandCycleCount += NOperandCycles;
515fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        }
5160d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey      }
517da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5185f54ce347368105260be2cec497b6a4199dc5789Evan Cheng      // Set up itinerary as location and location + stage count
5192661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
5205f54ce347368105260be2cec497b6a4199dc5789Evan Cheng      InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
5215f54ce347368105260be2cec497b6a4199dc5789Evan Cheng                                    FindOperandCycle,
5225f54ce347368105260be2cec497b6a4199dc5789Evan Cheng                                    FindOperandCycle + NOperandCycles};
5235f54ce347368105260be2cec497b6a4199dc5789Evan Cheng
524908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey      // Inject - empty slots will be 0, 0
5252661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      ItinList[SchedClassIdx] = Intinerary;
5260d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
5270d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
52863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
5297f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey  // Closing stage
5302661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
531fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  StageTable += "};\n";
532fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
533fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Closing operand cycles
5342661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OperandCycleTable += "  0 // End operand cycles\n";
535fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OperandCycleTable += "};\n";
536fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
5372661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  BypassTable += " 0 // End bypass tables\n";
53863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  BypassTable += "};\n";
53963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
540fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Emit tables.
541fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OS << StageTable;
542fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OS << OperandCycleTable;
54363d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  OS << BypassTable;
5440d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
5450d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
5460d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
5472661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitProcessorData - Generate data for processor itineraries that were
5482661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
5492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// Itineraries for each processor. The Itinerary lists are indexed on
5502661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// CodeGenSchedClass::Index.
5510d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
552234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trickvoid SubtargetEmitter::
5532661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitItineraries(raw_ostream &OS,
5542661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
555fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick
556cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  // Multiple processor models may share an itinerary record. Emit it once.
557cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  SmallPtrSet<Record*, 8> ItinsDefSet;
558cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
5592661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each processor's machine model
560f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<std::vector<InstrItinerary> >::iterator
5612661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      ProcItinListsIter = ProcItinLists.begin();
5622661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
56348605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
564cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
5652661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    Record *ItinsDef = PI->ItinsDef;
566cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick    if (!ItinsDefSet.insert(ItinsDef))
567cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick      continue;
568f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
569908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Get processor itinerary name
5702661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = ItinsDef->getName();
571da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Get the itinerary list for the processor.
5732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
57448605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
575fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick
5762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n";
5772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "static const llvm::InstrItinerary ";
5782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    if (ItinList.empty()) {
5792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      OS << '*' << Name << " = 0;\n";
5802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      continue;
5812661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    }
582da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Begin processor itinerary table
5842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << Name << "[] = {\n";
5852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
5862661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // For each itinerary class in CodeGenSchedClass::Index order.
5872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
5882661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      InstrItinerary &Intinerary = ItinList[j];
5892661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
5902661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      // Emit Itinerary in the form of
5912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      // { firstStage, lastStage, firstCycle, lastCycle } // index
5922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      OS << "  { " <<
5932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.NumMicroOps << ", " <<
5942661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.FirstStage << ", " <<
5952661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.LastStage << ", " <<
5962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.FirstOperandCycle << ", " <<
5972661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.LastOperandCycle << " }" <<
5982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
5990d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
6002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // End processor itinerary table
6012661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "  { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
602fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick    OS << "};\n";
6030d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
60410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey}
60510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
606c8e41c591741b3da1077f7000274ad040bef8002Sylvestre Ledru// Emit either the value defined in the TableGen Record, or the default
6072661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// value defined in the C++ header. The Record is null if the processor does not
6082661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// define a model.
6092661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
6102661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                         const char *Name, char Separator) {
6112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OS << "  ";
6122661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  int V = R ? R->getValueAsInt(Name) : -1;
6132661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (V >= 0)
6142661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << V << Separator << " // " << Name;
6152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  else
6162661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "MCSchedModel::Default" << Name << Separator;
6172661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OS << '\n';
6182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
6192661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
62040096d26937cd47c865464bef7b28550bc20c631Andrew Trickvoid SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
62140096d26937cd47c865464bef7b28550bc20c631Andrew Trick                                              raw_ostream &OS) {
62240096d26937cd47c865464bef7b28550bc20c631Andrew Trick  char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
62340096d26937cd47c865464bef7b28550bc20c631Andrew Trick
62440096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "\n// {Name, NumUnits, SuperIdx}\n";
62540096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "static const llvm::MCProcResourceDesc "
62640096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << ProcModel.ModelName << "ProcResources" << "[] = {\n"
62740096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "  {DBGFIELD(\"InvalidUnit\")     0, 0}" << Sep << "\n";
62840096d26937cd47c865464bef7b28550bc20c631Andrew Trick
62940096d26937cd47c865464bef7b28550bc20c631Andrew Trick  for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
63040096d26937cd47c865464bef7b28550bc20c631Andrew Trick    Record *PRDef = ProcModel.ProcResourceDefs[i];
63140096d26937cd47c865464bef7b28550bc20c631Andrew Trick
63240096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Find the SuperIdx
63340096d26937cd47c865464bef7b28550bc20c631Andrew Trick    unsigned SuperIdx = 0;
63440096d26937cd47c865464bef7b28550bc20c631Andrew Trick    Record *SuperDef = 0;
63540096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PRDef->getValueInit("Super")->isComplete()) {
63640096d26937cd47c865464bef7b28550bc20c631Andrew Trick      SuperDef =
63740096d26937cd47c865464bef7b28550bc20c631Andrew Trick        SchedModels.findProcResUnits(PRDef->getValueAsDef("Super"), ProcModel);
63840096d26937cd47c865464bef7b28550bc20c631Andrew Trick      SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
63940096d26937cd47c865464bef7b28550bc20c631Andrew Trick    }
64040096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Emit the ProcResourceDesc
64140096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (i+1 == e)
64240096d26937cd47c865464bef7b28550bc20c631Andrew Trick      Sep = ' ';
64340096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "  {DBGFIELD(\"" << PRDef->getName() << "\") ";
64440096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PRDef->getName().size() < 15)
64540096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS.indent(15 - PRDef->getName().size());
64640096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << PRDef->getValueAsInt("NumUnits") << ", " << SuperIdx
64740096d26937cd47c865464bef7b28550bc20c631Andrew Trick       << "}" << Sep << " // #" << i+1;
64840096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (SuperDef)
64940096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << ", Super=" << SuperDef->getName();
65040096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "\n";
65140096d26937cd47c865464bef7b28550bc20c631Andrew Trick  }
65240096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "};\n";
65340096d26937cd47c865464bef7b28550bc20c631Andrew Trick}
65440096d26937cd47c865464bef7b28550bc20c631Andrew Trick
65552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Find the WriteRes Record that defines processor resources for this
65652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// SchedWrite.
65752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew TrickRecord *SubtargetEmitter::FindWriteResources(
65892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
65952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
66052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check if the SchedWrite is already subtarget-specific and directly
66152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // specifies a set of processor resources.
66292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
66392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return SchedWrite.TheDef;
66492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick
66592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // Check this processor's list of aliases for SchedWrite.
66692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *AliasDef = 0;
66792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
66892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick       AI != AE; ++AI) {
66992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    const CodeGenSchedRW &AliasRW =
67092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
67192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
67292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
67392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      continue;
67492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef)
67592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
67692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    "defined for processor " + ProcModel.ModelName +
67792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    " Ensure only one SchedAlias exists per RW.");
67892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    AliasDef = AliasRW.TheDef;
67992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  }
68092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
68192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return AliasDef;
68252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
68352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check this processor's list of write resources.
68492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *ResDef = 0;
68552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (RecIter WRI = ProcModel.WriteResDefs.begin(),
68652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
68752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!(*WRI)->isSubClassOf("WriteRes"))
68852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
68992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef == (*WRI)->getValueAsDef("WriteType")
69092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
69192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      if (ResDef) {
69292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        throw TGError((*WRI)->getLoc(), "Resources are defined for both "
69392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      "SchedWrite and its alias on processor " +
69492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      ProcModel.ModelName);
69592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      }
69692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      ResDef = *WRI;
69792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    }
69852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
69992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // TODO: If ProcModel has a base model (previous generation processor),
70092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // then call FindWriteResources recursively with that model here.
70192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (!ResDef) {
70292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    throw TGError(ProcModel.ModelDef->getLoc(),
70392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                  std::string("Processor does not define resources for ")
70492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                  + SchedWrite.TheDef->getName());
70592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  }
70692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  return ResDef;
70752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
70852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
70952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// Find the ReadAdvance record for the given SchedRead on this processor or
71052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// return NULL.
71192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew TrickRecord *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
71252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                          const CodeGenProcModel &ProcModel) {
71352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check for SchedReads that directly specify a ReadAdvance.
71492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
71592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return SchedRead.TheDef;
71692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick
71792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // Check this processor's list of aliases for SchedRead.
71892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *AliasDef = 0;
71992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
72092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick       AI != AE; ++AI) {
72192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    const CodeGenSchedRW &AliasRW =
72292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
72392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
72492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
72592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      continue;
72692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef)
72792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      throw TGError(AliasRW.TheDef->getLoc(), "Multiple aliases "
72892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    "defined for processor " + ProcModel.ModelName +
72992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    " Ensure only one SchedAlias exists per RW.");
73092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    AliasDef = AliasRW.TheDef;
73192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  }
73292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
73392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return AliasDef;
73452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
73552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check this processor's ReadAdvanceList.
73692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *ResDef = 0;
73752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
73852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
73952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!(*RAI)->isSubClassOf("ReadAdvance"))
74052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
74192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef == (*RAI)->getValueAsDef("ReadType")
74292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
74392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      if (ResDef) {
74492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        throw TGError((*RAI)->getLoc(), "Resources are defined for both "
74592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      "SchedRead and its alias on processor " +
74692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      ProcModel.ModelName);
74792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      }
74892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      ResDef = *RAI;
74992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    }
75052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
75192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // TODO: If ProcModel has a base model (previous generation processor),
75292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // then call FindReadAdvance recursively with that model here.
75392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
75452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    throw TGError(ProcModel.ModelDef->getLoc(),
75552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  std::string("Processor does not define resources for ")
75692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                  + SchedRead.TheDef->getName());
75752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
75892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  return ResDef;
75952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
76052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
76152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Generate the SchedClass table for this processor and update global
76252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// tables. Must be called for each processor in order.
76352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trickvoid SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
76452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                           SchedClassTables &SchedTables) {
76552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
76652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  if (!ProcModel.hasInstrSchedModel())
76752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    return;
76852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
76952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
77052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
77152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
77252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCTab.resize(SCTab.size() + 1);
77352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    MCSchedClassDesc &SCDesc = SCTab.back();
774e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    // SCDesc.Name is guarded by NDEBUG
77552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumMicroOps = 0;
77652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.BeginGroup = false;
77752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.EndGroup = false;
77852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.WriteProcResIdx = 0;
77952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.WriteLatencyIdx = 0;
78052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.ReadAdvanceIdx = 0;
78152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
78252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // A Variant SchedClass has no resources of its own.
78352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!SCI->Transitions.empty()) {
78452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
78552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
78652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
78752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
78852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Determine if the SchedClass is actually reachable on this processor. If
78952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // not don't try to locate the processor resources, it will fail.
79052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // If ProcIndices contains 0, this class applies to all processors.
79152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
79252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCI->ProcIndices[0] != 0) {
79352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
79452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                SCI->ProcIndices.end(), ProcModel.Index);
79552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (PIPos == SCI->ProcIndices.end())
79652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        continue;
79752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
79852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    IdxVec Writes = SCI->Writes;
79952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    IdxVec Reads = SCI->Reads;
80052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCI->ItinClassDef) {
80152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      assert(SCI->InstRWs.empty() && "ItinClass should not have InstRWs");
80252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // Check this processor's itinerary class resources.
80352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (RecIter II = ProcModel.ItinRWDefs.begin(),
80452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
80552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
80652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
80752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick            != Matched.end()) {
80852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
80952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                              Writes, Reads);
81052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
81152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
81252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
81352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (Writes.empty()) {
81452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        DEBUG(dbgs() << ProcModel.ItinsDef->getName()
81552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick              << " does not have resources for itinerary class "
81652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick              << SCI->ItinClassDef->getName() << '\n');
81752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
81852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
81952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else if (!SCI->InstRWs.empty()) {
82052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      assert(SCI->Writes.empty() && SCI->Reads.empty() &&
82152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             "InstRW class should not have its own ReadWrites");
82252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      Record *RWDef = 0;
82352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
82452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick           RWI != RWE; ++RWI) {
82552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
82652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
82752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          RWDef = *RWI;
82852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
82952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
83052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
83152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (RWDef) {
83252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
83352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                            Writes, Reads);
83452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
83552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
83652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Sum resources across all operand writes.
83752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry> WriteProcResources;
83852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry> WriteLatencies;
8393b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    std::vector<std::string> WriterNames;
84052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
84152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
84252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxVec WriteSeq;
84352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedModels.expandRWSequence(*WI, WriteSeq, /*IsRead=*/false);
84452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
84552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // For each operand, create a latency entry.
84652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      MCWriteLatencyEntry WLEntry;
84752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WLEntry.Cycles = 0;
8483b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      unsigned WriteID = WriteSeq.back();
8493b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
8503b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      // If this Write is not referenced by a ReadAdvance, don't distinguish it
8513b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      // from other WriteLatency entries.
8523b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      if (!SchedModels.hasReadOfWrite(SchedModels.getSchedWrite(WriteID).TheDef)) {
8533b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        WriteID = 0;
8543b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      }
8553b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WLEntry.WriteResourceID = WriteID;
85652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
85752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
85852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick           WSI != WSE; ++WSI) {
85952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
86092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        Record *WriteRes =
86192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick          FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
86252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
86352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        // Mark the parent class as invalid for unsupported write types.
86452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (WriteRes->getValueAsBit("Unsupported")) {
86552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
86652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
86752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
86852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
86952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
87052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
87152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
87252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
87352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        // Create an entry for each ProcResource listed in WriteRes.
87452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
87552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        std::vector<int64_t> Cycles =
87652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteRes->getValueAsListOfInts("ResourceCycles");
87752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        for (unsigned PRIdx = 0, PREnd = PRVec.size();
87852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             PRIdx != PREnd; ++PRIdx) {
87952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          MCWriteProcResEntry WPREntry;
88052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
88152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
88252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          if (Cycles.size() > PRIdx)
88352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick            WPREntry.Cycles = Cycles[PRIdx];
88452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          else
88552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick            WPREntry.Cycles = 1;
88652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteProcResources.push_back(WPREntry);
88752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
88852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
88952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.push_back(WLEntry);
89052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
89152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Create an entry for each operand Read in this SchedClass.
89252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Entries must be sorted first by UseIdx then by WriteResourceID.
89352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    for (unsigned UseIdx = 0, EndIdx = Reads.size();
89452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         UseIdx != EndIdx; ++UseIdx) {
89592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      Record *ReadAdvance =
89692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
89752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (!ReadAdvance)
89852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        continue;
89952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
90052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // Mark the parent class as invalid for unsupported write types.
90152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (ReadAdvance->getValueAsBit("Unsupported")) {
90252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
90352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        break;
90452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
90552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
90652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxVec WriteIDs;
90752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (ValidWrites.empty())
90852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        WriteIDs.push_back(0);
90952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      else {
91052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
91152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             VWI != VWE; ++VWI) {
91252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
91352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
91452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
91552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::sort(WriteIDs.begin(), WriteIDs.end());
91652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
91752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        MCReadAdvanceEntry RAEntry;
91852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.UseIdx = UseIdx;
91952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.WriteResourceID = *WI;
92052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
92152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        ReadAdvanceEntries.push_back(RAEntry);
92252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
92352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
92452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
92552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteProcResources.clear();
92652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.clear();
92752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      ReadAdvanceEntries.clear();
92852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
92952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Add the information for this SchedClass to the global tables using basic
93052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // compression.
93152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    //
93252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // WritePrecRes entries are sorted by ProcResIdx.
93352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::sort(WriteProcResources.begin(), WriteProcResources.end(),
93452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick              LessWriteProcResources());
93552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
93652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumWriteProcResEntries = WriteProcResources.size();
93752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry>::iterator WPRPos =
93852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.WriteProcResources.begin(),
93952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.WriteProcResources.end(),
94052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  WriteProcResources.begin(), WriteProcResources.end());
94152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (WPRPos != SchedTables.WriteProcResources.end())
94252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
94352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
94452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
94552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
94652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                            WriteProcResources.end());
94752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
94852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Latency entries must remain in operand order.
94952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
95052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry>::iterator WLPos =
95152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.WriteLatencies.begin(),
95252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.WriteLatencies.end(),
95352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  WriteLatencies.begin(), WriteLatencies.end());
9543b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    if (WLPos != SchedTables.WriteLatencies.end()) {
9553b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      unsigned idx = WLPos - SchedTables.WriteLatencies.begin();
9563b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SCDesc.WriteLatencyIdx = idx;
9573b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i)
9583b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) ==
9593b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick            std::string::npos) {
9603b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick          SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i];
9613b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        }
9623b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    }
96352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
96452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
9653b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(),
9663b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                        WriteLatencies.begin(),
9673b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                        WriteLatencies.end());
9683b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SchedTables.WriterNames.insert(SchedTables.WriterNames.end(),
9693b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                     WriterNames.begin(), WriterNames.end());
97052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
97152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // ReadAdvanceEntries must remain in operand order.
97252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
97352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry>::iterator RAPos =
97452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.ReadAdvanceEntries.begin(),
97552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.ReadAdvanceEntries.end(),
97652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
97752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (RAPos != SchedTables.ReadAdvanceEntries.end())
97852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
97952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
98052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
98152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
98252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                            ReadAdvanceEntries.end());
98352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
98452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
98552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
98652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
987544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick// Emit SchedClass tables for all processors and associated global tables.
988544c88039f16706d6764c65fda276a11f2c586d6Andrew Trickvoid SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
989544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick                                            raw_ostream &OS) {
990544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global WriteProcResTable.
991544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {ProcResourceIdx, Cycles}\n"
992544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCWriteProcResEntry "
993544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteProcResTable[] = {\n"
994544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  { 0,  0}, // Invalid\n";
995544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
996544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       WPRIdx != WPREnd; ++WPRIdx) {
997544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
998544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
999544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", WPREntry.Cycles) << "}";
1000544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (WPRIdx + 1 < WPREnd)
1001544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
1002544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << " // #" << WPRIdx << '\n';
1003544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1004544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "WriteProcResTable\n";
1005544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1006544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global WriteLatencyTable.
1007544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {Cycles, WriteResourceID}\n"
1008544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCWriteLatencyEntry "
1009544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteLatencyTable[] = {\n"
1010544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  { 0,  0}, // Invalid\n";
1011544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
1012544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       WLIdx != WLEnd; ++WLIdx) {
1013544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
1014544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << format("%2d", WLEntry.Cycles) << ", "
1015544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", WLEntry.WriteResourceID) << "}";
1016544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (WLIdx + 1 < WLEnd)
1017544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
10183b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n';
1019544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1020544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "WriteLatencyTable\n";
1021544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1022544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global ReadAdvanceTable.
1023544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
1024544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCReadAdvanceEntry "
1025544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "ReadAdvanceTable[] = {\n"
1026544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  {0,  0,  0}, // Invalid\n";
1027544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
1028544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       RAIdx != RAEnd; ++RAIdx) {
1029544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
1030544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << RAEntry.UseIdx << ", "
1031544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", RAEntry.WriteResourceID) << ", "
1032544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", RAEntry.Cycles) << "}";
1033544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (RAIdx + 1 < RAEnd)
1034544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
1035544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << " // #" << RAIdx << '\n';
1036544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1037544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "ReadAdvanceTable\n";
1038544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1039544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit a SchedClass table for each processor.
1040544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1041544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1042544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (!PI->hasInstrSchedModel())
1043544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      continue;
1044544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1045544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    std::vector<MCSchedClassDesc> &SCTab =
1046544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      SchedTables.ProcSchedClasses[1 + PI - SchedModels.procModelBegin()];
1047544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1048544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
1049544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
1050544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "static const llvm::MCSchedClassDesc "
1051544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << PI->ModelName << "SchedClasses[] = {\n";
1052544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1053544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    // The first class is always invalid. We no way to distinguish it except by
1054544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    // name and position.
1055e4095f95ac2480aabbe289f41723b53ac1c82a98Andrew Trick    assert(SchedModels.getSchedClass(0).Name == "NoItinerary"
1056544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick           && "invalid class not first");
1057544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {DBGFIELD(\"InvalidSchedClass\")  "
1058544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << MCSchedClassDesc::InvalidNumMicroOps
1059544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << ", 0, 0,  0, 0,  0, 0,  0, 0},\n";
1060544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1061544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
1062544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      MCSchedClassDesc &MCDesc = SCTab[SCIdx];
1063544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
1064544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << "  {DBGFIELD(\"" << SchedClass.Name << "\") ";
1065544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      if (SchedClass.Name.size() < 18)
1066544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick        OS.indent(18 - SchedClass.Name.size());
1067544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << MCDesc.NumMicroOps
1068544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
1069544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.WriteProcResIdx)
1070544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumWriteProcResEntries
1071544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.WriteLatencyIdx)
1072544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumWriteLatencyEntries
1073544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.ReadAdvanceIdx)
1074544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumReadAdvanceEntries << "}";
1075544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      if (SCIdx + 1 < SCEnd)
1076544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick        OS << ',';
1077544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << " // #" << SCIdx << '\n';
1078544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    }
1079544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "}; // " << PI->ModelName << "SchedClasses\n";
1080544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1081544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick}
1082544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
10832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
10842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each processor model.
10852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
10862661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
108740096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Emit processor resource table.
108840096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PI->hasInstrSchedModel())
108940096d26937cd47c865464bef7b28550bc20c631Andrew Trick      EmitProcessorResources(*PI, OS);
109040096d26937cd47c865464bef7b28550bc20c631Andrew Trick    else if(!PI->ProcResourceDefs.empty())
109140096d26937cd47c865464bef7b28550bc20c631Andrew Trick      throw TGError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
109252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                    "ProcResources without defining WriteRes SchedWriteRes");
109340096d26937cd47c865464bef7b28550bc20c631Andrew Trick
10942661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Begin processor itinerary properties
10952661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n";
10962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
10972661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
10982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "MinLatency", ',');
10992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
11002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
1101d43b5c97cff06d7840b974ca84fa0639d2567968Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
1102e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << "  " << PI->Index << ", // Processor ID\n";
1103e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    if (PI->hasInstrSchedModel())
1104e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick      OS << "  " << PI->ModelName << "ProcResources" << ",\n"
1105e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << PI->ModelName << "SchedClasses" << ",\n"
1106e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << PI->ProcResourceDefs.size()+1 << ",\n"
1107e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << (SchedModels.schedClassEnd()
1108e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick                     - SchedModels.schedClassBegin()) << ",\n";
1109e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    else
1110e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick      OS << "  0, 0, 0, 0, // No instruction-level machine model.\n";
11112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    if (SchedModels.hasItineraryClasses())
111240096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << "  " << PI->ItinsDef->getName() << ");\n";
11132661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    else
111440096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << "  0); // No Itinerary\n";
11152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
11162661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
11172661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
111810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey//
111910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey// EmitProcessorLookup - generate cpu name to itinerary lookup table.
112010b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey//
11211a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
112210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // Gather and sort processor information
112310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  std::vector<Record*> ProcessorList =
112410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey                          Records.getAllDerivedDefinitions("Processor");
112542d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
112610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
112710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // Begin processor table
112810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "\n";
112910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
11301a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetInfoKV "
11312661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick     << Target << "ProcSchedKV[] = {\n";
1132da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
113310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // For each processor
113410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
113510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Next processor
113610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    Record *Processor = ProcessorList[i];
113710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
11384222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Processor->getValueAsString("Name");
11392661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &ProcModelName =
114048605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SchedModels.getModelForProc(Processor).ModelName;
1141da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
114210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Emit as { "cpu", procinit },
114340096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "  { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
1144da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
114510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on ''if more in the list'' emit comma
114610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    if (++i < N) OS << ",";
1147da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
114810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    OS << "\n";
114910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  }
1150da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
115110b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // End processor table
115210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "};\n";
11530d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
11540d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
11550d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
11562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
11570d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
11582661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
115940096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "#ifdef DBGFIELD\n"
116040096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
116140096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#endif\n"
116240096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#ifndef NDEBUG\n"
116340096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#define DBGFIELD(x) x,\n"
116440096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#else\n"
116540096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#define DBGFIELD(x)\n"
116640096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#endif\n";
116740096d26937cd47c865464bef7b28550bc20c631Andrew Trick
11682661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
11692661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<std::vector<InstrItinerary> > ProcItinLists;
11706cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey    // Emit the stage data
11712661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitStageAndOperandCycleData(OS, ProcItinLists);
11722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitItineraries(OS, ProcItinLists);
11736cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey  }
1174544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// ===============================================================\n"
1175544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "// Data tables for the new per-operand machine model.\n";
117640096d26937cd47c865464bef7b28550bc20c631Andrew Trick
117752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  SchedClassTables SchedTables;
117852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
117952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
118052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    GenSchedClassTables(*PI, SchedTables);
118152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
1182544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitSchedClassTables(SchedTables, OS);
1183544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1184544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit the processor machine model
1185544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitProcessorModels(OS);
1186544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit the processor lookup data
1187544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitProcessorLookup(OS);
118852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
118940096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "#undef DBGFIELD";
11900d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
11910d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
11924d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trickvoid SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName,
11934d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                                             raw_ostream &OS) {
11944d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  OS << "unsigned " << ClassName
11954d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
11964d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << " const TargetSchedModel *SchedModel) const {\n";
11974d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
11984d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
11994d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  std::sort(Prologs.begin(), Prologs.end(), LessRecord());
12004d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  for (std::vector<Record*>::const_iterator
12014d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) {
12024d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << (*PI)->getValueAsString("Code") << '\n';
12034d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
12044d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  IdxVec VariantClasses;
12054d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
12064d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
12074d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    if (SCI->Transitions.empty())
12084d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      continue;
12094d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    VariantClasses.push_back(SCI - SchedModels.schedClassBegin());
12104d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
12114d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  if (!VariantClasses.empty()) {
12124d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << "  switch (SchedClass) {\n";
12134d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end();
12144d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         VCI != VCE; ++VCI) {
12154d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI);
12164d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      OS << "  case " << *VCI << ": // " << SC.Name << '\n';
12174d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      IdxVec ProcIndices;
12184d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      for (std::vector<CodeGenSchedTransition>::const_iterator
12194d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             TI = SC.Transitions.begin(), TE = SC.Transitions.end();
12204d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           TI != TE; ++TI) {
12214d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        IdxVec PI;
12224d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(),
12234d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                       ProcIndices.begin(), ProcIndices.end(),
12244d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                       std::back_inserter(PI));
12254d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        ProcIndices.swap(PI);
12264d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      }
12274d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
12284d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           PI != PE; ++PI) {
12294d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    ";
12304d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        if (*PI != 0)
12314d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << "if (SchedModel->getProcessorID() == " << *PI << ") ";
12324d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName
12334d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           << '\n';
12344d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        for (std::vector<CodeGenSchedTransition>::const_iterator
12354d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick               TI = SC.Transitions.begin(), TE = SC.Transitions.end();
12364d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             TI != TE; ++TI) {
12374d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << "      if (";
12384d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          if (*PI != 0 && !std::count(TI->ProcIndices.begin(),
12394d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                                      TI->ProcIndices.end(), *PI)) {
12404d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick              continue;
12414d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          }
12424d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end();
12434d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick               RI != RE; ++RI) {
12444d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick            if (RI != TI->PredTerm.begin())
12454d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick              OS << "\n          && ";
12464d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick            OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
12474d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          }
12484d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << ")\n"
12494d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             << "        return " << TI->ToClassIdx << "; // "
12504d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n';
12514d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        }
12524d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    }\n";
12534d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        if (*PI == 0)
12544d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          break;
12554d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      }
12564d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      unsigned SCIdx = 0;
12574d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      if (SC.ItinClassDef)
12584d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        SCIdx = SchedModels.getSchedClassIdxForItin(SC.ItinClassDef);
12594d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      else
12604d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        SCIdx = SchedModels.findSchedClassIdx(SC.Writes, SC.Reads);
12614d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      if (SCIdx != *VCI)
12624d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    return " << SCIdx << ";\n";
12634d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      OS << "    break;\n";
12644d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    }
12654d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << "  };\n";
12664d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
12674d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  OS << "  report_fatal_error(\"Expected a variant SchedClass\");\n"
12684d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "} // " << ClassName << "::resolveSchedClass\n";
12694d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick}
12704d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
12710d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
1272581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// ParseFeaturesFunction - Produces a subtarget specific function for parsing
1273581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// the subtarget features string.
1274581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey//
127594214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengvoid SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
127694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng                                             unsigned NumFeatures,
127794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng                                             unsigned NumProcs) {
1278f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> Features =
1279f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                       Records.getAllDerivedDefinitions("SubtargetFeature");
128042d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(Features.begin(), Features.end(), LessRecord());
1281581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey
1282da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
1283da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick     << "// subtarget options.\n"
1284276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng     << "void llvm::";
1285581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << Target;
12860ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
1287f0fd3afeffcb41202147f755bf770061f189a42bDavid Greene     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
12883f696e568bae8afa5986e7af48156c2bac041ba7Hal Finkel     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
128994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
129094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (Features.empty()) {
129194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "}\n";
129294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return;
129394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  }
129494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
129534aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick  OS << "  InitMCProcessorInfo(CPU, FS);\n"
129634aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick     << "  uint64_t Bits = getFeatureBits();\n";
12974222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
1298f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  for (unsigned i = 0; i < Features.size(); i++) {
1299f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next record
1300f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *R = Features[i];
13014222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Instance = R->getName();
13024222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Value = R->getValueAsString("Value");
13034222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Attribute = R->getValueAsString("Attribute");
130419c95507443ebd4f1cee80917d540c8bd27f8fe1Evan Cheng
1305db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen    if (Value=="true" || Value=="false")
13060ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      OS << "  if ((Bits & " << Target << "::"
13070ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng         << Instance << ") != 0) "
1308db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen         << Attribute << " = " << Value << ";\n";
1309db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen    else
13100ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      OS << "  if ((Bits & " << Target << "::"
13110ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng         << Instance << ") != 0 && "
131294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng         << Attribute << " < " << Value << ") "
131394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng         << Attribute << " = " << Value << ";\n";
13146cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey  }
131541a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov
1316276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng  OS << "}\n";
1317581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey}
1318581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey
131941a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov//
1320b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// SubtargetEmitter::run - Main subtarget enumeration emitter.
1321b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
13221a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::run(raw_ostream &OS) {
13236f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
1324b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
1325ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
1326ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "#undef GET_SUBTARGETINFO_ENUM\n";
1327ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng
1328ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "namespace llvm {\n";
1329ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  Enumeration(OS, "SubtargetFeature", true);
1330ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "} // End llvm namespace \n";
1331ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
1332ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng
133394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
133494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
1335928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
133694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
1337c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0
1338c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "namespace {\n";
1339c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif
134094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumFeatures = FeatureKeyValues(OS);
1341c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
134294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumProcs = CPUKeyValues(OS);
1343c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
13442661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  EmitSchedModel(OS);
1345c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
1346c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0
1347c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "}\n";
1348c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif
134994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
135094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  // MCInstrInfo initialization routine.
135194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "static inline void Init" << Target
135259ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "MCSubtargetInfo(MCSubtargetInfo *II, "
135359ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "StringRef TT, StringRef CPU, StringRef FS) {\n";
135459ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng  OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
135594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumFeatures)
135694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "FeatureKV, ";
135794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
135894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
135994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumProcs)
136094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "SubTypeKV, ";
136194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
136294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
1363544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << '\n'; OS.indent(22);
1364e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << Target << "ProcSchedKV, "
1365e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteProcResTable, "
1366e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteLatencyTable, "
1367e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "ReadAdvanceTable, ";
13682661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
1369e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << '\n'; OS.indent(22);
1370e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << Target << "Stages, "
137194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "OperandCycles, "
1372a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick       << Target << "ForwardingPaths, ";
137394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  } else
1374e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << "0, 0, 0, ";
137594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
137694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
137794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
137894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
137994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
138094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
138194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
138294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
138394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
138494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#include \"llvm/Support/Debug.h\"\n";
138594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#include \"llvm/Support/raw_ostream.h\"\n";
138694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  ParseFeaturesFunction(OS, NumFeatures, NumProcs);
138794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
138894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
138994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
13905b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng  // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
139194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
139294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_HEADER\n";
139394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
139494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  std::string ClassName = Target + "GenSubtargetInfo";
139594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
1396dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta  OS << "class DFAPacketizer;\n";
13975b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng  OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
13980ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
13990ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "StringRef FS);\n"
1400dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta     << "public:\n"
14014d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "  unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *DefMI,"
14024d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << " const TargetSchedModel *SchedModel) const;\n"
1403464f3a332f81364ee09794f9502f0b25671149c6Sebastian Pop     << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
1404dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta     << " const;\n"
140594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng     << "};\n";
140694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
140794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
140894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
140994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
141094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
141194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_CTOR\n";
141294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
1413ee290ba35af88393ba18dd19e6e39d50c7872534Andrew Trick  OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n";
141494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
14151a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
14161a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
1417544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
1418544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCWriteProcResEntry "
1419544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteProcResTable[];\n";
1420544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCWriteLatencyEntry "
1421544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteLatencyTable[];\n";
1422544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCReadAdvanceEntry "
1423544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "ReadAdvanceTable[];\n";
1424544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
14252661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
14261a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer    OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
14271a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer    OS << "extern const unsigned " << Target << "OperandCycles[];\n";
1428a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick    OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
1429c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  }
1430c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng
14310ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
14320ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "StringRef FS)\n"
14335b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng     << "  : TargetSubtargetInfo() {\n"
143459ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "  InitMCSubtargetInfo(TT, CPU, FS, ";
143594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumFeatures)
143694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "FeatureKV, ";
143794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
143894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
143994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumProcs)
144094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "SubTypeKV, ";
144194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
144294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "0, ";
1443e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << '\n'; OS.indent(22);
1444e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << Target << "ProcSchedKV, "
1445e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteProcResTable, "
1446e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteLatencyTable, "
1447e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "ReadAdvanceTable, ";
1448e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << '\n'; OS.indent(22);
14492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (SchedModels.hasItineraryClasses()) {
1450e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << Target << "Stages, "
145194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "OperandCycles, "
1452a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick       << Target << "ForwardingPaths, ";
145394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  } else
1454e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << "0, 0, 0, ";
145594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << NumFeatures << ", " << NumProcs << ");\n}\n\n";
1456544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
14574d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  EmitSchedModelHelpers(ClassName, OS);
14584d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
145994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
146094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
146194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
1462b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
14636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
14646f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace llvm {
14656f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
14666f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenvoid EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
14672661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  CodeGenTarget CGTarget(RK);
14682661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SubtargetEmitter(RK, CGTarget).run(OS);
14696f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen}
14706f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
14716f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End llvm namespace
1472