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"
1640096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/ADT/STLExtras.h"
174ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/ADT/StringExtras.h"
186f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/MC/MCInstrItineraries.h"
194ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/Support/Debug.h"
204ffd89fa4d2788611187d1a534d2ed46adf1702cChandler Carruth#include "llvm/Support/Format.h"
2140096d26937cd47c865464bef7b28550bc20c631Andrew Trick#include "llvm/TableGen/Error.h"
226f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/Record.h"
236f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen#include "llvm/TableGen/TableGenBackend.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
30dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#define DEBUG_TYPE "subtarget-emitter"
31dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
326f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace {
336f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenclass SubtargetEmitter {
3452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Each processor has a SchedClassDesc table with an entry for each SchedClass.
3552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // The SchedClassDesc table indexes into a global write resource table, write
3652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // latency table, and read advance table.
3752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  struct SchedClassTables {
3852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<std::vector<MCSchedClassDesc> > ProcSchedClasses;
3952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry> WriteProcResources;
4052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry> WriteLatencies;
413b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    std::vector<std::string> WriterNames;
4252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
4352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
4452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Reserve an invalid entry at index 0
4552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SchedClassTables() {
4652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      ProcSchedClasses.resize(1);
4752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteProcResources.resize(1);
4852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.resize(1);
493b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WriterNames.push_back("InvalidWrite");
5052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      ReadAdvanceEntries.resize(1);
5152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
5252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  };
5352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
5452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  struct LessWriteProcResources {
5552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    bool operator()(const MCWriteProcResEntry &LHS,
5652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                    const MCWriteProcResEntry &RHS) {
5752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
5852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
5952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  };
606f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
616f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  RecordKeeper &Records;
622661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  CodeGenSchedModels &SchedModels;
636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  std::string Target;
646f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
656f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void Enumeration(raw_ostream &OS, const char *ClassName, bool isBits);
666f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  unsigned FeatureKeyValues(raw_ostream &OS);
676f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  unsigned CPUKeyValues(raw_ostream &OS);
686f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void FormItineraryStageString(const std::string &Names,
696f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                Record *ItinData, std::string &ItinString,
706f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                unsigned &NStages);
716f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
726f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                       unsigned &NOperandCycles);
736f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void FormItineraryBypassString(const std::string &Names,
746f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                 Record *ItinData,
756f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                                 std::string &ItinString, unsigned NOperandCycles);
762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitStageAndOperandCycleData(raw_ostream &OS,
772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                    std::vector<std::vector<InstrItinerary> >
782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                      &ProcItinLists);
792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitItineraries(raw_ostream &OS,
802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                       std::vector<std::vector<InstrItinerary> >
812661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                         &ProcItinLists);
822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitProcessorProp(raw_ostream &OS, const Record *R, const char *Name,
836f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                         char Separator);
8440096d26937cd47c865464bef7b28550bc20c631Andrew Trick  void EmitProcessorResources(const CodeGenProcModel &ProcModel,
8540096d26937cd47c865464bef7b28550bc20c631Andrew Trick                              raw_ostream &OS);
8692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *FindWriteResources(const CodeGenSchedRW &SchedWrite,
8752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                             const CodeGenProcModel &ProcModel);
8892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
8992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                          const CodeGenProcModel &ProcModel);
901754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick  void ExpandProcResources(RecVec &PRVec, std::vector<int64_t> &Cycles,
911754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick                           const CodeGenProcModel &ProcModel);
9252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  void GenSchedClassTables(const CodeGenProcModel &ProcModel,
9352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                           SchedClassTables &SchedTables);
94544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
952661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitProcessorModels(raw_ostream &OS);
966f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void EmitProcessorLookup(raw_ostream &OS);
974d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  void EmitSchedModelHelpers(std::string ClassName, raw_ostream &OS);
982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  void EmitSchedModel(raw_ostream &OS);
996f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
1006f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen                             unsigned NumProcs);
1016f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1026f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenpublic:
1032661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
1042661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
1056f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1066f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  void run(raw_ostream &o);
1076f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1086f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen};
1096f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End anonymous namespace
1106f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
1117dc02047fbb4b014e914458f54ea539c8ae58316Jim Laskey//
112581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// Enumeration - Emit the specified class as an enumeration.
113b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
1141a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::Enumeration(raw_ostream &OS,
115581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey                                   const char *ClassName,
116581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey                                   bool isBits) {
117908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Get all records of class and sort
118f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
11942d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(DefList.begin(), DefList.end(), LessRecord());
1204bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey
121b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  unsigned N = DefList.size();
12294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (N == 0)
12394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return;
124b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  if (N > 64) {
125b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    errs() << "Too many (> 64) subtarget features!\n";
126b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    exit(1);
127b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng  }
128b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng
12994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace " << Target << " {\n";
13094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
131ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  // For bit flag enumerations with more than 32 items, emit constants.
132ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  // Emit an enum for everything else.
133ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  if (isBits && N > 32) {
134ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // For each record
135ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    for (unsigned i = 0; i < N; i++) {
136ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Next record
137ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      Record *Def = DefList[i];
13894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
139ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Get and emit name and expression (1 << i)
140ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "  const uint64_t " << Def->getName() << " = 1ULL << " << i << ";\n";
141ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    }
142ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  } else {
143ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // Open enumeration
144ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    OS << "enum {\n";
145da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
146ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // For each record
147ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    for (unsigned i = 0; i < N;) {
148ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Next record
149ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      Record *Def = DefList[i];
150da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
151ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Get and emit name
152ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "  " << Def->getName();
153908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
154ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // If bit flags then emit expression (1 << i)
155ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      if (isBits)  OS << " = " << " 1ULL << " << i;
156da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
157ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      // Depending on 'if more in the list' emit comma
158ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      if (++i < N) OS << ",";
159ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen
160ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen      OS << "\n";
161ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    }
162da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
163ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    // Close enumeration
164ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen    OS << "};\n";
165ac1ed44d95789400edc334fab6680b7bcf7d61a9Jakob Stoklund Olesen  }
16694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
16794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "}\n";
168b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
169b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
170b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
1714222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// FeatureKeyValues - Emit data of all the subtarget features.  Used by the
1724222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling// command line.
173b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
17494214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
175908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Gather and sort all the features
176f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> FeatureList =
177f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                           Records.getAllDerivedDefinitions("SubtargetFeature");
17894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
17994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (FeatureList.empty())
18094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return 0;
18194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
1827c9a7728d9dd248ebee8f2dd969d303711d487a9Jim Grosbach  std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
183b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
184908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin feature table
185581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << "// Sorted (by key) array of values for CPU features.\n"
1861a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetFeatureKV " << Target
1871a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "FeatureKV[] = {\n";
188da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
189908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each feature
19094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumFeatures = 0;
191dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey  for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
192f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next feature
193f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *Feature = FeatureList[i];
194f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
1954222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Feature->getName();
1964222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &CommandLineName = Feature->getValueAsString("Name");
1974222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Desc = Feature->getValueAsString("Desc");
198da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
199dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey    if (CommandLineName.empty()) continue;
200da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
201da4231f134989af7dc6bd3408821ba573def27b2Jim Grosbach    // Emit as { "feature", "description", featureEnum, i1 | i2 | ... | in }
202b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    OS << "  { "
203f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey       << "\"" << CommandLineName << "\", "
204b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"" << Desc << "\", "
20594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "::" << Name << ", ";
2064222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
207da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick    const std::vector<Record*> &ImpliesList =
2084222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      Feature->getValueAsListOfDefs("Implies");
209da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
2104222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    if (ImpliesList.empty()) {
211b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng      OS << "0ULL";
2124222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    } else {
2134222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
21494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng        OS << Target << "::" << ImpliesList[j]->getName();
2154222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling        if (++j < M) OS << " | ";
2164222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling      }
2174222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    }
2184222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
2194222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    OS << " }";
22094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    ++NumFeatures;
221da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
22210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on 'if more in the list' emit comma
223dbe4006cf3cf0802dc318a5f2070c04c326e170bJim Laskey    if ((i + 1) < N) OS << ",";
224da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
225f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    OS << "\n";
226b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  }
227da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
228908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // End feature table
229b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  OS << "};\n";
230b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
23194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  return NumFeatures;
232b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
233b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
234b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
235b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// CPUKeyValues - Emit data of all the subtarget processors.  Used by command
236b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// line.
237b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
23894214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengunsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
239908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Gather and sort processor information
240f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> ProcessorList =
241f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                          Records.getAllDerivedDefinitions("Processor");
24242d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
243b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
244908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin processor table
245581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << "// Sorted (by key) array of values for CPU subtype.\n"
2461a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetFeatureKV " << Target
2471a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "SubTypeKV[] = {\n";
248da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
249908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each processor
250f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
251f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next processor
252f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *Processor = ProcessorList[i];
253f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
2544222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Processor->getValueAsString("Name");
255da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick    const std::vector<Record*> &FeatureList =
256b0e103d46bf8799ac5523157a6ed4a78d1751a89Chris Lattner      Processor->getValueAsListOfDefs("Features");
257da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
258908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Emit as { "cpu", "description", f1 | f2 | ... fn },
259b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    OS << "  { "
260b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"" << Name << "\", "
261b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey       << "\"Select the " << Name << " processor\", ";
262da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
263f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    if (FeatureList.empty()) {
264b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng      OS << "0ULL";
265b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey    } else {
266f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      for (unsigned j = 0, M = FeatureList.size(); j < M;) {
26794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng        OS << Target << "::" << FeatureList[j]->getName();
268f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey        if (++j < M) OS << " | ";
2694bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey      }
2704bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey    }
271da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
2724222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    // The "0" is for the "implies" section of this data structure.
273b6a638898a92d5cd782209fbeb673fe7846a29ebEvan Cheng    OS << ", 0ULL }";
274da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
27510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on 'if more in the list' emit comma
276f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    if (++i < N) OS << ",";
277da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
278f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    OS << "\n";
2794bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey  }
280da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
281908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // End processor table
282b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey  OS << "};\n";
283b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
28494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  return ProcessorList.size();
2854bb9cbb73075c350eadaf51d2dab8403764c9a60Jim Laskey}
286b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
287581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey//
288fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryStageString - Compose a string containing the stage
289fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// data initialization for the specified itinerary.  N is the number
290fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// of stages.
2910d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
292928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikovvoid SubtargetEmitter::FormItineraryStageString(const std::string &Name,
293928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov                                                Record *ItinData,
294fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                                                std::string &ItinString,
295fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                                                unsigned &NStages) {
296f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  // Get states list
2974222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling  const std::vector<Record*> &StageList =
2984222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    ItinData->getValueAsListOfDefs("Stages");
299908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
300908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // For each stage
301f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  unsigned N = NStages = StageList.size();
3028dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb  for (unsigned i = 0; i < N;) {
303f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next stage
3044222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const Record *Stage = StageList[i];
305da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
30696085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
3070d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    int Cycles = Stage->getValueAsInt("Cycles");
3087f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey    ItinString += "  { " + itostr(Cycles) + ", ";
309da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
310f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Get unit list
3114222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
312da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
313908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // For each unit
314f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    for (unsigned j = 0, M = UnitList.size(); j < M;) {
315f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      // Add name and bitwise or
316928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov      ItinString += Name + "FU::" + UnitList[j]->getName();
317f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      if (++j < M) ItinString += " | ";
3180d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
319da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
3201a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin    int TimeInc = Stage->getValueAsInt("TimeInc");
3211a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin    ItinString += ", " + itostr(TimeInc);
3221a8f36e3ce5b9c230781b66600c81536128abfb5David Goodwin
32396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    int Kind = Stage->getValueAsInt("Kind");
32496085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov    ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
32596085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov
326908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Close off stage
327908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    ItinString += " }";
3288dadf6b13a7cdd5b5b30c3b7af310c9756e4c68eChristopher Lamb    if (++i < N) ItinString += ", ";
3290d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
3300d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
3310d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
3320d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
333fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// FormItineraryOperandCycleString - Compose a string containing the
334fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// operand cycle initialization for the specified itinerary.  N is the
335fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin// number of operands that has cycles specified.
3360d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
337fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwinvoid SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
338fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin                         std::string &ItinString, unsigned &NOperandCycles) {
339fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Get operand cycle list
340fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  const std::vector<int64_t> &OperandCycleList =
341fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    ItinData->getValueAsListOfInts("OperandCycles");
342fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
343fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // For each operand cycle
344fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  unsigned N = NOperandCycles = OperandCycleList.size();
345fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  for (unsigned i = 0; i < N;) {
346fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    // Next operand cycle
347fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    const int OCycle = OperandCycleList[i];
348da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
349fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    ItinString += "  " + itostr(OCycle);
350fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin    if (++i < N) ItinString += ", ";
351fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  }
352fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin}
353fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
35463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Chengvoid SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
35563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 Record *ItinData,
35663d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 std::string &ItinString,
35763d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng                                                 unsigned NOperandCycles) {
35863d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  const std::vector<Record*> &BypassList =
35963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinData->getValueAsListOfDefs("Bypasses");
36063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  unsigned N = BypassList.size();
3613881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  unsigned i = 0;
3623881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  for (; i < N;) {
36363d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinString += Name + "Bypass::" + BypassList[i]->getName();
3643881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (++i < NOperandCycles) ItinString += ", ";
36563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  }
3663881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  for (; i < NOperandCycles;) {
36763d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng    ItinString += " 0";
3683881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (++i < NOperandCycles) ItinString += ", ";
36963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  }
37063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng}
37163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
372fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin//
3732661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
3742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
3752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// by CodeGenSchedClass::Index.
376fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin//
3772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::
3782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitStageAndOperandCycleData(raw_ostream &OS,
3792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                             std::vector<std::vector<InstrItinerary> >
3802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                               &ProcItinLists) {
381908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey
382cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  // Multiple processor models may share an itinerary record. Emit it once.
383cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  SmallPtrSet<Record*, 8> ItinsDefSet;
384cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
385928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov  // Emit functional units for all the itineraries.
3862661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
3872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
388928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
389cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick    if (!ItinsDefSet.insert(PI->ItinsDef))
390cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick      continue;
391cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
3922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
393928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    if (FUs.empty())
394928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov      continue;
395928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
3962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = PI->ItinsDef->getName();
3972661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n// Functional units for \"" << Name << "\"\n"
398928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov       << "namespace " << Name << "FU {\n";
399928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
400928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
401b460a3382961c5be9952a75d46228f624edbd39fHal Finkel      OS << "  const unsigned " << FUs[j]->getName()
402b460a3382961c5be9952a75d46228f624edbd39fHal Finkel         << " = 1 << " << j << ";\n";
403928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
404928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov    OS << "}\n";
40563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4062661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
4073881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    if (BPs.size()) {
4083881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
4093881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng         << "\"\n" << "namespace " << Name << "Bypass {\n";
41063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4111a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer      OS << "  const unsigned NoBypass = 0;\n";
4123881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
4131a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer        OS << "  const unsigned " << BPs[j]->getName()
4143881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng           << " = 1 << " << j << ";\n";
41563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
4163881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng      OS << "}\n";
4173881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng    }
418928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov  }
419928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
420908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey  // Begin stages table
4211a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string StageTable = "\nextern const llvm::InstrStage " + Target +
4221a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer                           "Stages[] = {\n";
42396085a36dbb9cf251c81bc150e41ea9c952c99c0Anton Korobeynikov  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
424da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
425fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Begin operand cycle table
4261a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string OperandCycleTable = "extern const unsigned " + Target +
42794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    "OperandCycles[] = {\n";
428fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OperandCycleTable += "  0, // No itinerary\n";
42963d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
43063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  // Begin pipeline bypass table
4311a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  std::string BypassTable = "extern const unsigned " + Target +
432a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick    "ForwardingPaths[] = {\n";
4332661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  BypassTable += " 0, // No itinerary\n";
434da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
4352661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each Itinerary across all processors, add a unique entry to the stages,
4362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // operand cycles, and pipepine bypess tables. Then add the new Itinerary
4372661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // object with computed offsets to the ProcItinLists result.
438fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  unsigned StageCount = 1, OperandCycleCount = 1;
4393881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng  std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
4402661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
4412661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
4422661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const CodeGenProcModel &ProcModel = *PI;
443da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
4442661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Add process itinerary to the list.
4452661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    ProcItinLists.resize(ProcItinLists.size()+1);
446d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick
4472661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // If this processor defines no itineraries, then leave the itinerary list
4482661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // empty.
4492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
4501ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    if (!ProcModel.hasItineraries())
451d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick      continue;
452d85934b3e5a96040e199e1b098705eb56cde584aAndrew Trick
4532661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = ProcModel.ItinsDef->getName();
454da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
4551ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    ItinList.resize(SchedModels.numInstrSchedClasses());
4561ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    assert(ProcModel.ItinDefList.size() == ItinList.size() && "bad Itins");
4571ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick
4581ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    for (unsigned SchedClassIdx = 0, SchedClassEnd = ItinList.size();
4592661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
4602661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
461f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey      // Next itinerary data
4622661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
463da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
464908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey      // Get string and stage count
465fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      std::string ItinStageString;
4662661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      unsigned NStages = 0;
4672661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      if (ItinData)
4682661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
469fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
470fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Get string and operand cycle count
471fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      std::string ItinOperandCycleString;
4722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      unsigned NOperandCycles = 0;
47363d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng      std::string ItinBypassString;
4742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      if (ItinData) {
4752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
4762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                        NOperandCycles);
4772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
4782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        FormItineraryBypassString(Name, ItinData, ItinBypassString,
4792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                  NOperandCycles);
4802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      }
48163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
482fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Check to see if stage already exists and create if it doesn't
483fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      unsigned FindStage = 0;
484fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      if (NStages > 0) {
485fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        FindStage = ItinStageMap[ItinStageString];
486fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        if (FindStage == 0) {
487234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
488234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          StageTable += ItinStageString + ", // " + itostr(StageCount);
489234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          if (NStages > 1)
490234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick            StageTable += "-" + itostr(StageCount + NStages - 1);
491234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          StageTable += "\n";
492fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Record Itin class number.
493fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          ItinStageMap[ItinStageString] = FindStage = StageCount;
494fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          StageCount += NStages;
495fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        }
496fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      }
497da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
498fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      // Check to see if operand cycle already exists and create if it doesn't
499fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      unsigned FindOperandCycle = 0;
500fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin      if (NOperandCycles > 0) {
5013881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng        std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
5023881cb7a5d54c0011b40997adcd742e1c7b91abdEvan Cheng        FindOperandCycle = ItinOperandMap[ItinOperandString];
503fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        if (FindOperandCycle == 0) {
504fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Emit as  cycle, // index
505234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          OperandCycleTable += ItinOperandCycleString + ", // ";
506234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          std::string OperandIdxComment = itostr(OperandCycleCount);
507234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          if (NOperandCycles > 1)
508234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick            OperandIdxComment += "-"
509234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick              + itostr(OperandCycleCount + NOperandCycles - 1);
510234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          OperandCycleTable += OperandIdxComment + "\n";
511fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          // Record Itin class number.
512da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick          ItinOperandMap[ItinOperandCycleString] =
513fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin            FindOperandCycle = OperandCycleCount;
51463d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng          // Emit as bypass, // index
515234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trick          BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
516fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin          OperandCycleCount += NOperandCycles;
517fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin        }
5180d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey      }
519da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5205f54ce347368105260be2cec497b6a4199dc5789Evan Cheng      // Set up itinerary as location and location + stage count
5212661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
5225f54ce347368105260be2cec497b6a4199dc5789Evan Cheng      InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
5235f54ce347368105260be2cec497b6a4199dc5789Evan Cheng                                    FindOperandCycle,
5245f54ce347368105260be2cec497b6a4199dc5789Evan Cheng                                    FindOperandCycle + NOperandCycles};
5255f54ce347368105260be2cec497b6a4199dc5789Evan Cheng
526908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey      // Inject - empty slots will be 0, 0
5272661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      ItinList[SchedClassIdx] = Intinerary;
5280d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
5290d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
53063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
5317f39c14f52262a154285df9180f5edcdabe2d7dfJim Laskey  // Closing stage
5322661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  StageTable += "  { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
533fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  StageTable += "};\n";
534fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
535fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Closing operand cycles
5362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OperandCycleTable += "  0 // End operand cycles\n";
537fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OperandCycleTable += "};\n";
538fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin
5392661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  BypassTable += " 0 // End bypass tables\n";
54063d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  BypassTable += "};\n";
54163d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng
542fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  // Emit tables.
543fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OS << StageTable;
544fac8541dd40e01aa2b52962516f9ae67c99720ccDavid Goodwin  OS << OperandCycleTable;
54563d66eed16a6ee4e838f2f7a4c8299def0722c20Evan Cheng  OS << BypassTable;
5460d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
5470d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
5480d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
5492661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitProcessorData - Generate data for processor itineraries that were
5502661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
5512661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// Itineraries for each processor. The Itinerary lists are indexed on
5522661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// CodeGenSchedClass::Index.
5530d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
554234823297e0fc0babddd2ab84054bf68f64a54d1Andrew Trickvoid SubtargetEmitter::
5552661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew TrickEmitItineraries(raw_ostream &OS,
5562661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                std::vector<std::vector<InstrItinerary> > &ProcItinLists) {
557fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick
558cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  // Multiple processor models may share an itinerary record. Emit it once.
559cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick  SmallPtrSet<Record*, 8> ItinsDefSet;
560cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
5612661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each processor's machine model
562f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<std::vector<InstrItinerary> >::iterator
5632661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      ProcItinListsIter = ProcItinLists.begin();
5642661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
56548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
566cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick
5672661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    Record *ItinsDef = PI->ItinsDef;
568cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick    if (!ItinsDefSet.insert(ItinsDef))
569cb94192ff01fabdd492e9b229683e5d98aa2099fAndrew Trick      continue;
570f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey
571908ae27a9073e2f105f8a0a4dd092d7fea8472a4Jim Laskey    // Get processor itinerary name
5722661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &Name = ItinsDef->getName();
573da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Get the itinerary list for the processor.
5752661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
57648605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick    std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
577fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick
5782661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n";
5792661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "static const llvm::InstrItinerary ";
5802661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    if (ItinList.empty()) {
581dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      OS << '*' << Name << " = nullptr;\n";
5822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      continue;
5832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    }
584da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
5852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Begin processor itinerary table
5862661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << Name << "[] = {\n";
5872661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
5882661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // For each itinerary class in CodeGenSchedClass::Index order.
5892661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
5902661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      InstrItinerary &Intinerary = ItinList[j];
5912661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
5922661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      // Emit Itinerary in the form of
5932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      // { firstStage, lastStage, firstCycle, lastCycle } // index
5942661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick      OS << "  { " <<
5952661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.NumMicroOps << ", " <<
5962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.FirstStage << ", " <<
5972661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.LastStage << ", " <<
5982661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.FirstOperandCycle << ", " <<
5992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        Intinerary.LastOperandCycle << " }" <<
6002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick        ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
6010d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey    }
6022661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // End processor itinerary table
6032661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "  { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
604fc992996f751e0941951b6d08d8f1e80ebec1385Andrew Trick    OS << "};\n";
6050d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey  }
60610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey}
60710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
608c8e41c591741b3da1077f7000274ad040bef8002Sylvestre Ledru// Emit either the value defined in the TableGen Record, or the default
6092661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// value defined in the C++ header. The Record is null if the processor does not
6102661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// define a model.
6112661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
6122661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick                                         const char *Name, char Separator) {
6132661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OS << "  ";
6142661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  int V = R ? R->getValueAsInt(Name) : -1;
6152661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  if (V >= 0)
6162661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << V << Separator << " // " << Name;
6172661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  else
6182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "MCSchedModel::Default" << Name << Separator;
6192661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  OS << '\n';
6202661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
6212661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
62240096d26937cd47c865464bef7b28550bc20c631Andrew Trickvoid SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
62340096d26937cd47c865464bef7b28550bc20c631Andrew Trick                                              raw_ostream &OS) {
62440096d26937cd47c865464bef7b28550bc20c631Andrew Trick  char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
62540096d26937cd47c865464bef7b28550bc20c631Andrew Trick
6266312cb099734263f348f36a31b8892b1373a7076Andrew Trick  OS << "\n// {Name, NumUnits, SuperIdx, IsBuffered}\n";
62740096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "static const llvm::MCProcResourceDesc "
62840096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << ProcModel.ModelName << "ProcResources" << "[] = {\n"
6296312cb099734263f348f36a31b8892b1373a7076Andrew Trick     << "  {DBGFIELD(\"InvalidUnit\")     0, 0, 0}" << Sep << "\n";
63040096d26937cd47c865464bef7b28550bc20c631Andrew Trick
63140096d26937cd47c865464bef7b28550bc20c631Andrew Trick  for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
63240096d26937cd47c865464bef7b28550bc20c631Andrew Trick    Record *PRDef = ProcModel.ProcResourceDefs[i];
63340096d26937cd47c865464bef7b28550bc20c631Andrew Trick
634dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Record *SuperDef = nullptr;
6351754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    unsigned SuperIdx = 0;
6361754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    unsigned NumUnits = 0;
637a3d82ce19fd825cbf3bf85b5969424217fc40b45Andrew Trick    int BufferSize = PRDef->getValueAsInt("BufferSize");
6381754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    if (PRDef->isSubClassOf("ProcResGroup")) {
6391754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
6401754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end();
6411754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick           RUI != RUE; ++RUI) {
6421754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick        NumUnits += (*RUI)->getValueAsInt("NumUnits");
6431754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      }
6441754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    }
6451754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    else {
6461754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      // Find the SuperIdx
6471754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      if (PRDef->getValueInit("Super")->isComplete()) {
6481754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick        SuperDef = SchedModels.findProcResUnits(
6491754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick          PRDef->getValueAsDef("Super"), ProcModel);
6501754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick        SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
6511754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      }
652157c6c4e8e0b4f5f83289d32f7b67b1ae2e3c357Andrew Trick      NumUnits = PRDef->getValueAsInt("NumUnits");
65340096d26937cd47c865464bef7b28550bc20c631Andrew Trick    }
65440096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Emit the ProcResourceDesc
65540096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (i+1 == e)
65640096d26937cd47c865464bef7b28550bc20c631Andrew Trick      Sep = ' ';
65740096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "  {DBGFIELD(\"" << PRDef->getName() << "\") ";
65840096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PRDef->getName().size() < 15)
65940096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS.indent(15 - PRDef->getName().size());
6601754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    OS << NumUnits << ", " << SuperIdx << ", "
661b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick       << BufferSize << "}" << Sep << " // #" << i+1;
66240096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (SuperDef)
66340096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << ", Super=" << SuperDef->getName();
66440096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "\n";
66540096d26937cd47c865464bef7b28550bc20c631Andrew Trick  }
66640096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "};\n";
66740096d26937cd47c865464bef7b28550bc20c631Andrew Trick}
66840096d26937cd47c865464bef7b28550bc20c631Andrew Trick
66952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Find the WriteRes Record that defines processor resources for this
67052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// SchedWrite.
67152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew TrickRecord *SubtargetEmitter::FindWriteResources(
67292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
67352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
67452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check if the SchedWrite is already subtarget-specific and directly
67552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // specifies a set of processor resources.
67692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
67792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return SchedWrite.TheDef;
67892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick
679dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Record *AliasDef = nullptr;
68092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
68192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick       AI != AE; ++AI) {
68292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    const CodeGenSchedRW &AliasRW =
68392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
6842062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick    if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
6852062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick      Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
6862062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick      if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
6872062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick        continue;
6882062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick    }
68992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef)
69061131ab15fd593a2e295d79fe2714e7bc21f2ec8Joerg Sonnenberger      PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
69192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    "defined for processor " + ProcModel.ModelName +
69292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    " Ensure only one SchedAlias exists per RW.");
69392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    AliasDef = AliasRW.TheDef;
69492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  }
69592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
69692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return AliasDef;
69752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
69852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check this processor's list of write resources.
699dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Record *ResDef = nullptr;
70052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (RecIter WRI = ProcModel.WriteResDefs.begin(),
70152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
70252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!(*WRI)->isSubClassOf("WriteRes"))
70352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
70492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef == (*WRI)->getValueAsDef("WriteType")
70592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
70692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      if (ResDef) {
70761131ab15fd593a2e295d79fe2714e7bc21f2ec8Joerg Sonnenberger        PrintFatalError((*WRI)->getLoc(), "Resources are defined for both "
70892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      "SchedWrite and its alias on processor " +
70992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      ProcModel.ModelName);
71092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      }
71192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      ResDef = *WRI;
71292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    }
71352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
71492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // TODO: If ProcModel has a base model (previous generation processor),
71592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // then call FindWriteResources recursively with that model here.
71692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (!ResDef) {
71761131ab15fd593a2e295d79fe2714e7bc21f2ec8Joerg Sonnenberger    PrintFatalError(ProcModel.ModelDef->getLoc(),
71892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                  std::string("Processor does not define resources for ")
71992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                  + SchedWrite.TheDef->getName());
72092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  }
72192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  return ResDef;
72252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
72352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
72452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// Find the ReadAdvance record for the given SchedRead on this processor or
72552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick/// return NULL.
72692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew TrickRecord *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
72752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                          const CodeGenProcModel &ProcModel) {
72852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check for SchedReads that directly specify a ReadAdvance.
72992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
73092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return SchedRead.TheDef;
73192649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick
73292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // Check this processor's list of aliases for SchedRead.
733dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Record *AliasDef = nullptr;
73492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
73592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick       AI != AE; ++AI) {
73692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    const CodeGenSchedRW &AliasRW =
73792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
7382062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick    if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
7392062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick      Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
7402062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick      if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
7412062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick        continue;
7422062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick    }
74392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef)
74461131ab15fd593a2e295d79fe2714e7bc21f2ec8Joerg Sonnenberger      PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
74592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    "defined for processor " + ProcModel.ModelName +
74692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                    " Ensure only one SchedAlias exists per RW.");
74792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    AliasDef = AliasRW.TheDef;
74892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  }
74992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
75092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    return AliasDef;
75152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
75252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  // Check this processor's ReadAdvanceList.
753dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  Record *ResDef = nullptr;
75452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
75552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
75652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (!(*RAI)->isSubClassOf("ReadAdvance"))
75752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
75892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    if (AliasDef == (*RAI)->getValueAsDef("ReadType")
75992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
76092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      if (ResDef) {
76161131ab15fd593a2e295d79fe2714e7bc21f2ec8Joerg Sonnenberger        PrintFatalError((*RAI)->getLoc(), "Resources are defined for both "
76292649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      "SchedRead and its alias on processor " +
76392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                      ProcModel.ModelName);
76492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      }
76592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      ResDef = *RAI;
76692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick    }
76752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
76892649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // TODO: If ProcModel has a base model (previous generation processor),
76992649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  // then call FindReadAdvance recursively with that model here.
77092649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
77161131ab15fd593a2e295d79fe2714e7bc21f2ec8Joerg Sonnenberger    PrintFatalError(ProcModel.ModelDef->getLoc(),
77252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  std::string("Processor does not define resources for ")
77392649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick                  + SchedRead.TheDef->getName());
77452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
77592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick  return ResDef;
77652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
77752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
7781754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick// Expand an explicit list of processor resources into a full list of implied
779a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick// resource groups and super resources that cover them.
7801754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trickvoid SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
7811754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick                                           std::vector<int64_t> &Cycles,
782a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick                                           const CodeGenProcModel &PM) {
7831754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick  // Default to 1 resource cycle.
7841754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick  Cycles.resize(PRVec.size(), 1);
7851754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick  for (unsigned i = 0, e = PRVec.size(); i != e; ++i) {
786a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick    Record *PRDef = PRVec[i];
7871754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    RecVec SubResources;
788a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick    if (PRDef->isSubClassOf("ProcResGroup"))
789a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick      SubResources = PRDef->getValueAsListOfDefs("Resources");
7901754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    else {
791a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick      SubResources.push_back(PRDef);
792a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick      PRDef = SchedModels.findProcResUnits(PRVec[i], PM);
793a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick      for (Record *SubDef = PRDef;
794a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick           SubDef->getValueInit("Super")->isComplete();) {
795a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick        if (SubDef->isSubClassOf("ProcResGroup")) {
796a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick          // Disallow this for simplicitly.
797a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick          PrintFatalError(SubDef->getLoc(), "Processor resource group "
798a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick                          " cannot be a super resources.");
799a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick        }
800a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick        Record *SuperDef =
801a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick          SchedModels.findProcResUnits(SubDef->getValueAsDef("Super"), PM);
802a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick        PRVec.push_back(SuperDef);
803a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick        Cycles.push_back(Cycles[i]);
804a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick        SubDef = SuperDef;
805a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick      }
8061754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    }
807a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick    for (RecIter PRI = PM.ProcResourceDefs.begin(),
808a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick           PRE = PM.ProcResourceDefs.end();
8091754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick         PRI != PRE; ++PRI) {
810a809c8db3d052e9b7dfaf8665ab3ce1a0b0dc859Andrew Trick      if (*PRI == PRDef || !(*PRI)->isSubClassOf("ProcResGroup"))
8111754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick        continue;
8121754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      RecVec SuperResources = (*PRI)->getValueAsListOfDefs("Resources");
8131754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      RecIter SubI = SubResources.begin(), SubE = SubResources.end();
8146982bdd1193551e65effa3737f2a29d55e7901a5Andrew Trick      for( ; SubI != SubE; ++SubI) {
8156982bdd1193551e65effa3737f2a29d55e7901a5Andrew Trick        if (std::find(SuperResources.begin(), SuperResources.end(), *SubI)
8166982bdd1193551e65effa3737f2a29d55e7901a5Andrew Trick            == SuperResources.end()) {
8171754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick          break;
8186982bdd1193551e65effa3737f2a29d55e7901a5Andrew Trick        }
8191754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      }
8201754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      if (SubI == SubE) {
8211754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick        PRVec.push_back(*PRI);
8221754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick        Cycles.push_back(Cycles[i]);
8231754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick      }
8241754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick    }
8251754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick  }
8261754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick}
8271754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick
82852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// Generate the SchedClass table for this processor and update global
82952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick// tables. Must be called for each processor in order.
83052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trickvoid SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
83152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                           SchedClassTables &SchedTables) {
83252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
83352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  if (!ProcModel.hasInstrSchedModel())
83452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    return;
83552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
83652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
83752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
83852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
839fe05d98c253676d1ae6e0f03efde6b75fdae105dAndrew Trick    DEBUG(SCI->dump(&SchedModels));
840fe05d98c253676d1ae6e0f03efde6b75fdae105dAndrew Trick
84152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCTab.resize(SCTab.size() + 1);
84252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    MCSchedClassDesc &SCDesc = SCTab.back();
843e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    // SCDesc.Name is guarded by NDEBUG
84452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumMicroOps = 0;
84552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.BeginGroup = false;
84652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.EndGroup = false;
84752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.WriteProcResIdx = 0;
84852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.WriteLatencyIdx = 0;
84952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.ReadAdvanceIdx = 0;
85052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
85152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // A Variant SchedClass has no resources of its own.
85282e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick    bool HasVariants = false;
85382e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick    for (std::vector<CodeGenSchedTransition>::const_iterator
85482e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick           TI = SCI->Transitions.begin(), TE = SCI->Transitions.end();
85582e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick         TI != TE; ++TI) {
85682e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick      if (TI->ProcIndices[0] == 0) {
85782e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick        HasVariants = true;
85882e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick        break;
85982e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick      }
86082e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick      IdxIter PIPos = std::find(TI->ProcIndices.begin(),
86182e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick                                TI->ProcIndices.end(), ProcModel.Index);
86282e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick      if (PIPos != TI->ProcIndices.end()) {
86382e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick        HasVariants = true;
86482e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick        break;
86582e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick      }
86682e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick    }
86782e7c4f533a98a16b0cadd5209c1d3dc8ce33d87Andrew Trick    if (HasVariants) {
86852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
86952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      continue;
87052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
87152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
87252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Determine if the SchedClass is actually reachable on this processor. If
87352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // not don't try to locate the processor resources, it will fail.
87452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // If ProcIndices contains 0, this class applies to all processors.
87552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    assert(!SCI->ProcIndices.empty() && "expect at least one procidx");
87652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCI->ProcIndices[0] != 0) {
87752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
87852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                SCI->ProcIndices.end(), ProcModel.Index);
87952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (PIPos == SCI->ProcIndices.end())
88052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        continue;
88152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
88252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    IdxVec Writes = SCI->Writes;
88352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    IdxVec Reads = SCI->Reads;
8841ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    if (!SCI->InstRWs.empty()) {
8851ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      // This class has a default ReadWrite list which can be overriden by
886fe05d98c253676d1ae6e0f03efde6b75fdae105dAndrew Trick      // InstRW definitions.
887dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      Record *RWDef = nullptr;
88852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
88952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick           RWI != RWE; ++RWI) {
89052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
89152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
89252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          RWDef = *RWI;
89352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
89452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
89552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
89652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (RWDef) {
8972062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick        Writes.clear();
8982062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick        Reads.clear();
89952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
90052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                            Writes, Reads);
90152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
90252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
9031ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    if (Writes.empty()) {
9041ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      // Check this processor's itinerary class resources.
9051ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      for (RecIter II = ProcModel.ItinRWDefs.begin(),
9061ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick             IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
9071ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick        RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
9081ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick        if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
9091ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick            != Matched.end()) {
9101ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick          SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
9111ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick                              Writes, Reads);
9121ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick          break;
9131ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick        }
9141ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      }
9151ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      if (Writes.empty()) {
9161ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick        DEBUG(dbgs() << ProcModel.ModelName
9171ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick              << " does not have resources for class " << SCI->Name << '\n');
9181ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      }
9191ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    }
92052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Sum resources across all operand writes.
92152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry> WriteProcResources;
92252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry> WriteLatencies;
9233b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    std::vector<std::string> WriterNames;
92452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
92552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
92652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxVec WriteSeq;
9272062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick      SchedModels.expandRWSeqForProc(*WI, WriteSeq, /*IsRead=*/false,
9282062b1260fa9df3e69e7b4d24a657a0ebb7f8710Andrew Trick                                     ProcModel);
92952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
93052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // For each operand, create a latency entry.
93152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      MCWriteLatencyEntry WLEntry;
93252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WLEntry.Cycles = 0;
9333b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      unsigned WriteID = WriteSeq.back();
9343b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
9353b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      // If this Write is not referenced by a ReadAdvance, don't distinguish it
9363b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      // from other WriteLatency entries.
9371ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      if (!SchedModels.hasReadOfWrite(
9381ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick            SchedModels.getSchedWrite(WriteID).TheDef)) {
9393b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        WriteID = 0;
9403b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      }
9413b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      WLEntry.WriteResourceID = WriteID;
94252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
94352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
94452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick           WSI != WSE; ++WSI) {
94552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
94692649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        Record *WriteRes =
94792649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick          FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
94852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
94952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        // Mark the parent class as invalid for unsupported write types.
95052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        if (WriteRes->getValueAsBit("Unsupported")) {
95152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
95252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          break;
95352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
95452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
95552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
95652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
95752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
95852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
95952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        // Create an entry for each ProcResource listed in WriteRes.
96052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
96152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        std::vector<int64_t> Cycles =
96252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteRes->getValueAsListOfInts("ResourceCycles");
9631754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick
9641754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick        ExpandProcResources(PRVec, Cycles, ProcModel);
9651754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick
96652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        for (unsigned PRIdx = 0, PREnd = PRVec.size();
96752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             PRIdx != PREnd; ++PRIdx) {
96852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          MCWriteProcResEntry WPREntry;
96952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
97052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
9711754aca83af1658c832706889c0e2933f8dfa8eeAndrew Trick          WPREntry.Cycles = Cycles[PRIdx];
972c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          // If this resource is already used in this sequence, add the current
973c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          // entry's cycles so that the same resource appears to be used
974c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          // serially, rather than multiple parallel uses. This is important for
975c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          // in-order machine where the resource consumption is a hazard.
976c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          unsigned WPRIdx = 0, WPREnd = WriteProcResources.size();
977c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          for( ; WPRIdx != WPREnd; ++WPRIdx) {
978c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick            if (WriteProcResources[WPRIdx].ProcResourceIdx
979c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick                == WPREntry.ProcResourceIdx) {
980c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick              WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles;
981c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick              break;
982c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick            }
983c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          }
984c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick          if (WPRIdx == WPREnd)
985c812110023c714f773cd176f4e4d63b4e9fbdbefAndrew Trick            WriteProcResources.push_back(WPREntry);
98652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
98752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
98852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.push_back(WLEntry);
98952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
99052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Create an entry for each operand Read in this SchedClass.
99152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Entries must be sorted first by UseIdx then by WriteResourceID.
99252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    for (unsigned UseIdx = 0, EndIdx = Reads.size();
99352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         UseIdx != EndIdx; ++UseIdx) {
99492649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick      Record *ReadAdvance =
99592649883119aaa8edd9ccf612eaaff5ccc8fcc77Andrew Trick        FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
99652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (!ReadAdvance)
99752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        continue;
99852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
99952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      // Mark the parent class as invalid for unsupported write types.
100052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (ReadAdvance->getValueAsBit("Unsupported")) {
100152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
100252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        break;
100352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
100452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
100552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      IdxVec WriteIDs;
100652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      if (ValidWrites.empty())
100752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        WriteIDs.push_back(0);
100852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      else {
100952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
101052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick             VWI != VWE; ++VWI) {
101152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick          WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
101252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        }
101352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
101452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::sort(WriteIDs.begin(), WriteIDs.end());
101552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
101652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        MCReadAdvanceEntry RAEntry;
101752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.UseIdx = UseIdx;
101852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.WriteResourceID = *WI;
101952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
102052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick        ReadAdvanceEntries.push_back(RAEntry);
102152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      }
102252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
102352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
102452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteProcResources.clear();
102552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      WriteLatencies.clear();
102652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      ReadAdvanceEntries.clear();
102752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
102852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Add the information for this SchedClass to the global tables using basic
102952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // compression.
103052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    //
103152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // WritePrecRes entries are sorted by ProcResIdx.
103252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::sort(WriteProcResources.begin(), WriteProcResources.end(),
103352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick              LessWriteProcResources());
103452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
103552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumWriteProcResEntries = WriteProcResources.size();
103652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteProcResEntry>::iterator WPRPos =
103752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.WriteProcResources.begin(),
103852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.WriteProcResources.end(),
103952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  WriteProcResources.begin(), WriteProcResources.end());
104052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (WPRPos != SchedTables.WriteProcResources.end())
104152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
104252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
104352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
104452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
104552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                            WriteProcResources.end());
104652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
104752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // Latency entries must remain in operand order.
104852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
104952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCWriteLatencyEntry>::iterator WLPos =
105052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.WriteLatencies.begin(),
105152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.WriteLatencies.end(),
105252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  WriteLatencies.begin(), WriteLatencies.end());
10533b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    if (WLPos != SchedTables.WriteLatencies.end()) {
10543b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      unsigned idx = WLPos - SchedTables.WriteLatencies.begin();
10553b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SCDesc.WriteLatencyIdx = idx;
10563b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i)
10573b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) ==
10583b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick            std::string::npos) {
10593b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick          SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i];
10603b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick        }
10613b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    }
106252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
106352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
10643b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(),
10653b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                        WriteLatencies.begin(),
10663b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                        WriteLatencies.end());
10673b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick      SchedTables.WriterNames.insert(SchedTables.WriterNames.end(),
10683b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick                                     WriterNames.begin(), WriterNames.end());
106952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
107052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    // ReadAdvanceEntries must remain in operand order.
107152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
107252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    std::vector<MCReadAdvanceEntry>::iterator RAPos =
107352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      std::search(SchedTables.ReadAdvanceEntries.begin(),
107452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  SchedTables.ReadAdvanceEntries.end(),
107552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                  ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
107652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    if (RAPos != SchedTables.ReadAdvanceEntries.end())
107752c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
107852c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    else {
107952c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
108052c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick      SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
108152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                                            ReadAdvanceEntries.end());
108252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    }
108352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
108452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick}
108552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
1086544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick// Emit SchedClass tables for all processors and associated global tables.
1087544c88039f16706d6764c65fda276a11f2c586d6Andrew Trickvoid SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
1088544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick                                            raw_ostream &OS) {
1089544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global WriteProcResTable.
1090544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {ProcResourceIdx, Cycles}\n"
1091544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCWriteProcResEntry "
1092544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteProcResTable[] = {\n"
1093544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  { 0,  0}, // Invalid\n";
1094544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
1095544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       WPRIdx != WPREnd; ++WPRIdx) {
1096544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
1097544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
1098544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", WPREntry.Cycles) << "}";
1099544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (WPRIdx + 1 < WPREnd)
1100544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
1101544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << " // #" << WPRIdx << '\n';
1102544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1103544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "WriteProcResTable\n";
1104544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1105544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global WriteLatencyTable.
1106544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {Cycles, WriteResourceID}\n"
1107544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCWriteLatencyEntry "
1108544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteLatencyTable[] = {\n"
1109544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  { 0,  0}, // Invalid\n";
1110544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
1111544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       WLIdx != WLEnd; ++WLIdx) {
1112544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
1113544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << format("%2d", WLEntry.Cycles) << ", "
1114544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", WLEntry.WriteResourceID) << "}";
1115544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (WLIdx + 1 < WLEnd)
1116544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
11173b8fb648c6e1c519b7e0f487f4fb511744869d35Andrew Trick    OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n';
1118544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1119544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "WriteLatencyTable\n";
1120544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1121544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit global ReadAdvanceTable.
1122544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
1123544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "extern const llvm::MCReadAdvanceEntry "
1124544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "ReadAdvanceTable[] = {\n"
1125544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "  {0,  0,  0}, // Invalid\n";
1126544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
1127544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       RAIdx != RAEnd; ++RAIdx) {
1128544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
1129544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {" << RAEntry.UseIdx << ", "
1130544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", RAEntry.WriteResourceID) << ", "
1131544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << format("%2d", RAEntry.Cycles) << "}";
1132544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (RAIdx + 1 < RAEnd)
1133544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << ',';
1134544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << " // #" << RAIdx << '\n';
1135544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1136544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "}; // " << Target << "ReadAdvanceTable\n";
1137544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1138544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit a SchedClass table for each processor.
1139544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
1140544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
1141544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    if (!PI->hasInstrSchedModel())
1142544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      continue;
1143544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1144544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    std::vector<MCSchedClassDesc> &SCTab =
1145322ff8834532915a4de0210a083672008d6499b6Rafael Espindola      SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())];
1146544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1147544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
1148544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
1149544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "static const llvm::MCSchedClassDesc "
1150544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << PI->ModelName << "SchedClasses[] = {\n";
1151544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1152544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    // The first class is always invalid. We no way to distinguish it except by
1153544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    // name and position.
11541ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    assert(SchedModels.getSchedClass(0).Name == "NoInstrModel"
1155544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick           && "invalid class not first");
1156544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "  {DBGFIELD(\"InvalidSchedClass\")  "
1157544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << MCSchedClassDesc::InvalidNumMicroOps
1158544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick       << ", 0, 0,  0, 0,  0, 0,  0, 0},\n";
1159544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1160544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
1161544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      MCSchedClassDesc &MCDesc = SCTab[SCIdx];
1162544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
1163544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << "  {DBGFIELD(\"" << SchedClass.Name << "\") ";
1164544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      if (SchedClass.Name.size() < 18)
1165544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick        OS.indent(18 - SchedClass.Name.size());
1166544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << MCDesc.NumMicroOps
1167544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
1168544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.WriteProcResIdx)
1169544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumWriteProcResEntries
1170544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.WriteLatencyIdx)
1171544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumWriteLatencyEntries
1172544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << format("%2d", MCDesc.ReadAdvanceIdx)
1173544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick         << ", " << MCDesc.NumReadAdvanceEntries << "}";
1174544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      if (SCIdx + 1 < SCEnd)
1175544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick        OS << ',';
1176544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick      OS << " // #" << SCIdx << '\n';
1177544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    }
1178544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick    OS << "}; // " << PI->ModelName << "SchedClasses\n";
1179544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  }
1180544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick}
1181544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
11822661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
11832661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  // For each processor model.
11842661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
11852661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
118640096d26937cd47c865464bef7b28550bc20c631Andrew Trick    // Emit processor resource table.
118740096d26937cd47c865464bef7b28550bc20c631Andrew Trick    if (PI->hasInstrSchedModel())
118840096d26937cd47c865464bef7b28550bc20c631Andrew Trick      EmitProcessorResources(*PI, OS);
118940096d26937cd47c865464bef7b28550bc20c631Andrew Trick    else if(!PI->ProcResourceDefs.empty())
119061131ab15fd593a2e295d79fe2714e7bc21f2ec8Joerg Sonnenberger      PrintFatalError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
119152c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick                    "ProcResources without defining WriteRes SchedWriteRes");
119240096d26937cd47c865464bef7b28550bc20c631Andrew Trick
11932661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    // Begin processor itinerary properties
11942661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "\n";
11952661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    OS << "static const llvm::MCSchedModel " << PI->ModelName << "(\n";
11962661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
1197b86a0cdb674549d8493043331cecd9cbf53b80daAndrew Trick    EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ',');
1198dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ',');
11992661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
12002661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
1201d43b5c97cff06d7840b974ca84fa0639d2567968Andrew Trick    EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
1202070156437752179833b1e5fddd50caa03fd7c12fAndrew Trick
1203070156437752179833b1e5fddd50caa03fd7c12fAndrew Trick    OS << "  " << (bool)(PI->ModelDef ?
1204070156437752179833b1e5fddd50caa03fd7c12fAndrew Trick                         PI->ModelDef->getValueAsBit("CompleteModel") : 0)
1205070156437752179833b1e5fddd50caa03fd7c12fAndrew Trick       << ", // " << "CompleteModel\n";
1206070156437752179833b1e5fddd50caa03fd7c12fAndrew Trick
1207e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << "  " << PI->Index << ", // Processor ID\n";
1208e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    if (PI->hasInstrSchedModel())
1209e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick      OS << "  " << PI->ModelName << "ProcResources" << ",\n"
1210e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << PI->ModelName << "SchedClasses" << ",\n"
1211e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << PI->ProcResourceDefs.size()+1 << ",\n"
1212e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick         << "  " << (SchedModels.schedClassEnd()
1213e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick                     - SchedModels.schedClassBegin()) << ",\n";
1214e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    else
1215e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick      OS << "  0, 0, 0, 0, // No instruction-level machine model.\n";
12161ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    if (SchedModels.hasItineraries())
121740096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << "  " << PI->ItinsDef->getName() << ");\n";
12182661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    else
121940096d26937cd47c865464bef7b28550bc20c631Andrew Trick      OS << "  0); // No Itinerary\n";
12202661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  }
12212661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick}
12222661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick
122310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey//
122410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey// EmitProcessorLookup - generate cpu name to itinerary lookup table.
122510b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey//
12261a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
122710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // Gather and sort processor information
122810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  std::vector<Record*> ProcessorList =
122910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey                          Records.getAllDerivedDefinitions("Processor");
123042d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
123110b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
123210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // Begin processor table
123310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "\n";
123410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
12351a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer     << "extern const llvm::SubtargetInfoKV "
12362661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick     << Target << "ProcSchedKV[] = {\n";
1237da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
123810b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // For each processor
123910b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
124010b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Next processor
124110b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    Record *Processor = ProcessorList[i];
124210b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey
12434222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Name = Processor->getValueAsString("Name");
12442661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    const std::string &ProcModelName =
124548605c340614fc1fb2ae1d975fc565a4188182e0Andrew Trick      SchedModels.getModelForProc(Processor).ModelName;
1246da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
124710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Emit as { "cpu", procinit },
124840096d26937cd47c865464bef7b28550bc20c631Andrew Trick    OS << "  { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
1249da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
125010b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    // Depending on ''if more in the list'' emit comma
125110b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    if (++i < N) OS << ",";
1252da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
125310b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey    OS << "\n";
125410b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  }
1255da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick
125610b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  // End processor table
125710b1dd99f342d2d7af51dd43f3840f3bf40b0b87Jim Laskey  OS << "};\n";
12580d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
12590d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
12600d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
12612661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
12620d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
12632661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trickvoid SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
126440096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "#ifdef DBGFIELD\n"
126540096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
126640096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#endif\n"
126740096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#ifndef NDEBUG\n"
126840096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#define DBGFIELD(x) x,\n"
126940096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#else\n"
127040096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#define DBGFIELD(x)\n"
127140096d26937cd47c865464bef7b28550bc20c631Andrew Trick     << "#endif\n";
127240096d26937cd47c865464bef7b28550bc20c631Andrew Trick
12731ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick  if (SchedModels.hasItineraries()) {
12742661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    std::vector<std::vector<InstrItinerary> > ProcItinLists;
12756cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey    // Emit the stage data
12762661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitStageAndOperandCycleData(OS, ProcItinLists);
12772661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick    EmitItineraries(OS, ProcItinLists);
12786cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey  }
1279544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "\n// ===============================================================\n"
1280544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << "// Data tables for the new per-operand machine model.\n";
128140096d26937cd47c865464bef7b28550bc20c631Andrew Trick
128252c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  SchedClassTables SchedTables;
128352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
128452c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick         PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
128552c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick    GenSchedClassTables(*PI, SchedTables);
128652c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick  }
1287544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitSchedClassTables(SchedTables, OS);
1288544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
1289544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit the processor machine model
1290544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitProcessorModels(OS);
1291544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  // Emit the processor lookup data
1292544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  EmitProcessorLookup(OS);
129352c3a1d654a9d0af500a99cff4cd40c314ffb122Andrew Trick
129440096d26937cd47c865464bef7b28550bc20c631Andrew Trick  OS << "#undef DBGFIELD";
12950d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey}
12960d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey
12974d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trickvoid SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName,
12984d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                                             raw_ostream &OS) {
12994d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  OS << "unsigned " << ClassName
13004d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
13014d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << " const TargetSchedModel *SchedModel) const {\n";
13024d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
13034d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
13044d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  std::sort(Prologs.begin(), Prologs.end(), LessRecord());
13054d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  for (std::vector<Record*>::const_iterator
13064d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) {
13074d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << (*PI)->getValueAsString("Code") << '\n';
13084d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
13094d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  IdxVec VariantClasses;
13104d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
13114d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
13124d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    if (SCI->Transitions.empty())
13134d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      continue;
13141ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick    VariantClasses.push_back(SCI->Index);
13154d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
13164d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  if (!VariantClasses.empty()) {
13174d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << "  switch (SchedClass) {\n";
13184d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end();
13194d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick         VCI != VCE; ++VCI) {
13204d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI);
13214d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      OS << "  case " << *VCI << ": // " << SC.Name << '\n';
13224d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      IdxVec ProcIndices;
13234d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      for (std::vector<CodeGenSchedTransition>::const_iterator
13244d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             TI = SC.Transitions.begin(), TE = SC.Transitions.end();
13254d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           TI != TE; ++TI) {
13264d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        IdxVec PI;
13274d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(),
13284d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                       ProcIndices.begin(), ProcIndices.end(),
13294d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                       std::back_inserter(PI));
13304d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        ProcIndices.swap(PI);
13314d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      }
13324d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
13334d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           PI != PE; ++PI) {
13344d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    ";
13354d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        if (*PI != 0)
13364d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << "if (SchedModel->getProcessorID() == " << *PI << ") ";
13374d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName
13384d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick           << '\n';
13394d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        for (std::vector<CodeGenSchedTransition>::const_iterator
13404d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick               TI = SC.Transitions.begin(), TE = SC.Transitions.end();
13414d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             TI != TE; ++TI) {
13424d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          if (*PI != 0 && !std::count(TI->ProcIndices.begin(),
13434d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick                                      TI->ProcIndices.end(), *PI)) {
13444d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick              continue;
13454d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          }
1346fcce70ad527cec1fc10b855ee072efb562a2521eArnold Schwaighofer          OS << "      if (";
13474d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end();
13484d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick               RI != RE; ++RI) {
13494d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick            if (RI != TI->PredTerm.begin())
13504d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick              OS << "\n          && ";
13514d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick            OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
13524d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          }
13534d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          OS << ")\n"
13544d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             << "        return " << TI->ToClassIdx << "; // "
13554d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick             << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n';
13564d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        }
13574d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        OS << "    }\n";
13584d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick        if (*PI == 0)
13594d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick          break;
13604d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      }
13611ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick      if (SC.isInferred())
13621ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick        OS << "    return " << SC.Index << ";\n";
13634d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick      OS << "    break;\n";
13644d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    }
13654d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick    OS << "  };\n";
13664d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  }
13674d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  OS << "  report_fatal_error(\"Expected a variant SchedClass\");\n"
13684d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "} // " << ClassName << "::resolveSchedClass\n";
13694d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick}
13704d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
13710d841e05677bdc55d003720e85e12d28dfe31862Jim Laskey//
1372581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// ParseFeaturesFunction - Produces a subtarget specific function for parsing
1373581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey// the subtarget features string.
1374581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey//
137594214703d97d8d9dfca88174ffc7e94820a85e62Evan Chengvoid SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
137694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng                                             unsigned NumFeatures,
137794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng                                             unsigned NumProcs) {
1378f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  std::vector<Record*> Features =
1379f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey                       Records.getAllDerivedDefinitions("SubtargetFeature");
138042d24c71df88178eacf244a38b6c48847ee0d39bDuraid Madina  std::sort(Features.begin(), Features.end(), LessRecord());
1381581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey
1382da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick  OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
1383da96cf2029e47baf77df5c1ce6528a04246d6462Andrew Trick     << "// subtarget options.\n"
1384276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng     << "void llvm::";
1385581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey  OS << Target;
13860ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
1387f0fd3afeffcb41202147f755bf770061f189a42bDavid Greene     << "  DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
13883f696e568bae8afa5986e7af48156c2bac041ba7Hal Finkel     << "  DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
138994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
139094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (Features.empty()) {
139194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << "}\n";
139294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    return;
139394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  }
139494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
139534aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick  OS << "  InitMCProcessorInfo(CPU, FS);\n"
139634aadd63346b5f9b98749a306b71fcb00ee6996fAndrew Trick     << "  uint64_t Bits = getFeatureBits();\n";
13974222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling
1398f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey  for (unsigned i = 0; i < Features.size(); i++) {
1399f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    // Next record
1400f7bcde085440d1fd90eba8980ed9c512bc58824dJim Laskey    Record *R = Features[i];
14014222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Instance = R->getName();
14024222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Value = R->getValueAsString("Value");
14034222d806faae71ecc794cfdaa873817873c2f3d8Bill Wendling    const std::string &Attribute = R->getValueAsString("Attribute");
140419c95507443ebd4f1cee80917d540c8bd27f8fe1Evan Cheng
1405db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen    if (Value=="true" || Value=="false")
14060ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      OS << "  if ((Bits & " << Target << "::"
14070ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng         << Instance << ") != 0) "
1408db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen         << Attribute << " = " << Value << ";\n";
1409db01c8ba26f288636d3f574a96af3499ee6d2579Dale Johannesen    else
14100ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng      OS << "  if ((Bits & " << Target << "::"
14110ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng         << Instance << ") != 0 && "
141294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng         << Attribute << " < " << Value << ") "
141394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng         << Attribute << " = " << Value << ";\n";
14146cee630070b1a7183ed56a8404e812629f5ca538Jim Laskey  }
141541a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov
1416276365dd4bc0c2160f91fd8062ae1fc90c86c324Evan Cheng  OS << "}\n";
1417581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey}
1418581a8f79bc1ac3cbe5d621f0b4a0252ab2890bc1Jim Laskey
141941a024385f1220eadc48b48cb4c044a5fbc1b361Anton Korobeynikov//
1420b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey// SubtargetEmitter::run - Main subtarget enumeration emitter.
1421b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey//
14221a55180238dbcf11113f610aea010447e51f595bDaniel Dunbarvoid SubtargetEmitter::run(raw_ostream &OS) {
14236f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen  emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
1424b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey
1425ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
1426ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "#undef GET_SUBTARGETINFO_ENUM\n";
1427ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng
1428ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "namespace llvm {\n";
1429ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  Enumeration(OS, "SubtargetFeature", true);
1430ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "} // End llvm namespace \n";
1431ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng  OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
1432ebdeeab812beec0385b445f3d4c41a114e0d972fEvan Cheng
143394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
143494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_MC_DESC\n";
1435928eb49cae286c95dceecf4442997dd561c6e3b7Anton Korobeynikov
143694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
1437c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0
1438c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "namespace {\n";
1439c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif
144094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumFeatures = FeatureKeyValues(OS);
1441c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
144294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  unsigned NumProcs = CPUKeyValues(OS);
1443c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
14442661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  EmitSchedModel(OS);
1445c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "\n";
1446c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#if 0
1447c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  OS << "}\n";
1448c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng#endif
144994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
145094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  // MCInstrInfo initialization routine.
145194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "static inline void Init" << Target
145259ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "MCSubtargetInfo(MCSubtargetInfo *II, "
145359ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "StringRef TT, StringRef CPU, StringRef FS) {\n";
145459ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng  OS << "  II->InitMCSubtargetInfo(TT, CPU, FS, ";
145594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumFeatures)
145694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "FeatureKV, ";
145794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
1458dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "None, ";
145994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumProcs)
146094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng    OS << Target << "SubTypeKV, ";
146194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
1462dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "None, ";
1463544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << '\n'; OS.indent(22);
1464e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << Target << "ProcSchedKV, "
1465e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteProcResTable, "
1466e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteLatencyTable, "
1467e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "ReadAdvanceTable, ";
14681ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick  if (SchedModels.hasItineraries()) {
1469e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << '\n'; OS.indent(22);
1470e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << Target << "Stages, "
147194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "OperandCycles, "
1472dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines       << Target << "ForwardingPaths";
147394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  } else
1474dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "0, 0, 0";
1475dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  OS << ");\n}\n\n";
147694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
147794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
147894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
147994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
148094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
148194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
148294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n";
148394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
148494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#include \"llvm/Support/Debug.h\"\n";
148594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  ParseFeaturesFunction(OS, NumFeatures, NumProcs);
148694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
148794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
148894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
14895b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng  // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
149094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
149194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_HEADER\n";
149294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
149394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  std::string ClassName = Target + "GenSubtargetInfo";
149494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
1495dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta  OS << "class DFAPacketizer;\n";
14965b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng  OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
14970ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "  explicit " << ClassName << "(StringRef TT, StringRef CPU, "
14980ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "StringRef FS);\n"
1499dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta     << "public:\n"
15004d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick     << "  unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *DefMI,"
150136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines     << " const TargetSchedModel *SchedModel) const override;\n"
1502464f3a332f81364ee09794f9502f0b25671149c6Sebastian Pop     << "  DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
1503dc81e5da271ed394e2029c83458773c4ae2fc5f4Anshuman Dasgupta     << " const;\n"
150494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng     << "};\n";
150594214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
150694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
150794214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
150894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
150994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
151094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#undef GET_SUBTARGETINFO_CTOR\n";
151194214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
1512ee290ba35af88393ba18dd19e6e39d50c7872534Andrew Trick  OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n";
151394214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "namespace llvm {\n";
15141a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
15151a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer  OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
1516544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
1517544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCWriteProcResEntry "
1518544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteProcResTable[];\n";
1519544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCWriteLatencyEntry "
1520544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "WriteLatencyTable[];\n";
1521544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick  OS << "extern const llvm::MCReadAdvanceEntry "
1522544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick     << Target << "ReadAdvanceTable[];\n";
1523544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
15241ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick  if (SchedModels.hasItineraries()) {
15251a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer    OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
15261a2f9886a2a60dbd41216468a240446bbfed3e76Benjamin Kramer    OS << "extern const unsigned " << Target << "OperandCycles[];\n";
1527a11a6287a504d1d7503e744d14314df1e696f506Andrew Trick    OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
1528c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng  }
1529c60f9b752381baa6c4b80c0739034660f1748c84Evan Cheng
15300ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng  OS << ClassName << "::" << ClassName << "(StringRef TT, StringRef CPU, "
15310ddff1b5359433faf2eb1c4ff5320ddcbd42f52fEvan Cheng     << "StringRef FS)\n"
15325b1b4489cf3a0f56f8be0673fc5cc380a32d277bEvan Cheng     << "  : TargetSubtargetInfo() {\n"
153359ee62d2418df8db499eca1ae17f5900dc2dcbbaEvan Cheng     << "  InitMCSubtargetInfo(TT, CPU, FS, ";
153494214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumFeatures)
1535dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), ";
153694214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
1537dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "None, ";
153894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  if (NumProcs)
1539dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "makeArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), ";
154094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  else
1541dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "None, ";
1542e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << '\n'; OS.indent(22);
1543e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << Target << "ProcSchedKV, "
1544e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteProcResTable, "
1545e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "WriteLatencyTable, "
1546e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick     << Target << "ReadAdvanceTable, ";
1547e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick  OS << '\n'; OS.indent(22);
15481ab961f6d3cdd284f5d6c696f3e26eb3627e2c8bAndrew Trick  if (SchedModels.hasItineraries()) {
1549e127dfd0b175b5a336e61fecaad7fc2aec65d95cAndrew Trick    OS << Target << "Stages, "
155094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng       << Target << "OperandCycles, "
1551dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines       << Target << "ForwardingPaths";
155294214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  } else
1553dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    OS << "0, 0, 0";
1554dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  OS << ");\n}\n\n";
1555544c88039f16706d6764c65fda276a11f2c586d6Andrew Trick
15564d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick  EmitSchedModelHelpers(ClassName, OS);
15574d2d1c49d7262c55302a6ffd995e5e13fe522091Andrew Trick
155894214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "} // End llvm namespace \n";
155994214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng
156094214703d97d8d9dfca88174ffc7e94820a85e62Evan Cheng  OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
1561b3b1d5f097a4fbcf134259b743ccbd93d187c6cdJim Laskey}
15626f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
15636f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesennamespace llvm {
15646f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
15656f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesenvoid EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
15662661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  CodeGenTarget CGTarget(RK);
15672661b411ccc81b1fe19194d3f43b2630cbef3f28Andrew Trick  SubtargetEmitter(RK, CGTarget).run(OS);
15686f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen}
15696f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen
15706f36fa981a59461466e12e5056ba209d289b81b1Jakob Stoklund Olesen} // End llvm namespace
1571