1*0b57cec5SDimitry Andric //===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This class parses the Schedule.td file and produces an API that can be used 10*0b57cec5SDimitry Andric // to reason about whether an instruction can be added to a packet on a VLIW 11*0b57cec5SDimitry Andric // architecture. The class internally generates a deterministic finite 12*0b57cec5SDimitry Andric // automaton (DFA) that models all possible mappings of machine instructions 13*0b57cec5SDimitry Andric // to functional units as instructions are added to a packet. 14*0b57cec5SDimitry Andric // 15*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric #define DEBUG_TYPE "dfa-emitter" 18*0b57cec5SDimitry Andric 19480093f4SDimitry Andric #include "CodeGenSchedule.h" 20*0b57cec5SDimitry Andric #include "CodeGenTarget.h" 218bcb0991SDimitry Andric #include "DFAEmitter.h" 22*0b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 23*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 24*0b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 25*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 26*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 27480093f4SDimitry Andric #include "llvm/TableGen/Record.h" 28480093f4SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 29*0b57cec5SDimitry Andric #include <cassert> 30*0b57cec5SDimitry Andric #include <cstdint> 31*0b57cec5SDimitry Andric #include <map> 32*0b57cec5SDimitry Andric #include <set> 33*0b57cec5SDimitry Andric #include <string> 348bcb0991SDimitry Andric #include <unordered_map> 35*0b57cec5SDimitry Andric #include <vector> 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric using namespace llvm; 38*0b57cec5SDimitry Andric 39480093f4SDimitry Andric // We use a uint64_t to represent a resource bitmask. 40480093f4SDimitry Andric #define DFA_MAX_RESOURCES 64 41*0b57cec5SDimitry Andric 42*0b57cec5SDimitry Andric namespace { 43480093f4SDimitry Andric using ResourceVector = SmallVector<uint64_t, 4>; 44*0b57cec5SDimitry Andric 45480093f4SDimitry Andric struct ScheduleClass { 46480093f4SDimitry Andric /// The parent itinerary index (processor model ID). 47480093f4SDimitry Andric unsigned ItineraryID; 48*0b57cec5SDimitry Andric 49480093f4SDimitry Andric /// Index within this itinerary of the schedule class. 50480093f4SDimitry Andric unsigned Idx; 51*0b57cec5SDimitry Andric 52480093f4SDimitry Andric /// The index within the uniqued set of required resources of Resources. 53480093f4SDimitry Andric unsigned ResourcesIdx; 54*0b57cec5SDimitry Andric 55480093f4SDimitry Andric /// Conjunctive list of resource requirements: 56480093f4SDimitry Andric /// {a|b, b|c} => (a OR b) AND (b or c). 57480093f4SDimitry Andric /// Resources are unique across all itineraries. 58480093f4SDimitry Andric ResourceVector Resources; 59480093f4SDimitry Andric }; 60*0b57cec5SDimitry Andric 61480093f4SDimitry Andric // Generates and prints out the DFA for resource tracking. 62*0b57cec5SDimitry Andric class DFAPacketizerEmitter { 63*0b57cec5SDimitry Andric private: 64*0b57cec5SDimitry Andric std::string TargetName; 65*0b57cec5SDimitry Andric RecordKeeper &Records; 66*0b57cec5SDimitry Andric 67480093f4SDimitry Andric UniqueVector<ResourceVector> UniqueResources; 68480093f4SDimitry Andric std::vector<ScheduleClass> ScheduleClasses; 69480093f4SDimitry Andric std::map<std::string, uint64_t> FUNameToBitsMap; 70480093f4SDimitry Andric std::map<unsigned, uint64_t> ComboBitToBitsMap; 71480093f4SDimitry Andric 72*0b57cec5SDimitry Andric public: 73*0b57cec5SDimitry Andric DFAPacketizerEmitter(RecordKeeper &R); 74*0b57cec5SDimitry Andric 75480093f4SDimitry Andric // Construct a map of function unit names to bits. 76480093f4SDimitry Andric int collectAllFuncUnits( 77480093f4SDimitry Andric ArrayRef<const CodeGenProcModel *> ProcModels); 78*0b57cec5SDimitry Andric 79480093f4SDimitry Andric // Construct a map from a combo function unit bit to the bits of all included 80480093f4SDimitry Andric // functional units. 81480093f4SDimitry Andric int collectAllComboFuncs(ArrayRef<Record *> ComboFuncList); 82*0b57cec5SDimitry Andric 83480093f4SDimitry Andric ResourceVector getResourcesForItinerary(Record *Itinerary); 84480093f4SDimitry Andric void createScheduleClasses(unsigned ItineraryIdx, const RecVec &Itineraries); 85*0b57cec5SDimitry Andric 868bcb0991SDimitry Andric // Emit code for a subset of itineraries. 878bcb0991SDimitry Andric void emitForItineraries(raw_ostream &OS, 88480093f4SDimitry Andric std::vector<const CodeGenProcModel *> &ProcItinList, 898bcb0991SDimitry Andric std::string DFAName); 908bcb0991SDimitry Andric 91*0b57cec5SDimitry Andric void run(raw_ostream &OS); 92*0b57cec5SDimitry Andric }; 93*0b57cec5SDimitry Andric } // end anonymous namespace 94*0b57cec5SDimitry Andric 95480093f4SDimitry Andric DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R) 96480093f4SDimitry Andric : TargetName(CodeGenTarget(R).getName()), Records(R) {} 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric int DFAPacketizerEmitter::collectAllFuncUnits( 99480093f4SDimitry Andric ArrayRef<const CodeGenProcModel *> ProcModels) { 100*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------" 101*0b57cec5SDimitry Andric "----------------------\n"); 102*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "collectAllFuncUnits"); 103480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " (" << ProcModels.size() << " itineraries)\n"); 104480093f4SDimitry Andric 105480093f4SDimitry Andric std::set<Record *> ProcItinList; 106480093f4SDimitry Andric for (const CodeGenProcModel *Model : ProcModels) 107480093f4SDimitry Andric ProcItinList.insert(Model->ItinsDef); 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric int totalFUs = 0; 110*0b57cec5SDimitry Andric // Parse functional units for all the itineraries. 111480093f4SDimitry Andric for (Record *Proc : ProcItinList) { 112*0b57cec5SDimitry Andric std::vector<Record *> FUs = Proc->getValueAsListOfDefs("FU"); 113*0b57cec5SDimitry Andric 114480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " FU:" 115480093f4SDimitry Andric << " (" << FUs.size() << " FUs) " << Proc->getName()); 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric // Convert macros to bits for each stage. 118*0b57cec5SDimitry Andric unsigned numFUs = FUs.size(); 119*0b57cec5SDimitry Andric for (unsigned j = 0; j < numFUs; ++j) { 120*0b57cec5SDimitry Andric assert((j < DFA_MAX_RESOURCES) && 121*0b57cec5SDimitry Andric "Exceeded maximum number of representable resources"); 122480093f4SDimitry Andric uint64_t FuncResources = 1ULL << j; 123*0b57cec5SDimitry Andric FUNameToBitsMap[FUs[j]->getName()] = FuncResources; 124*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " " << FUs[j]->getName() << ":0x" 125*0b57cec5SDimitry Andric << Twine::utohexstr(FuncResources)); 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric totalFUs += numFUs; 128*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 129*0b57cec5SDimitry Andric } 130*0b57cec5SDimitry Andric return totalFUs; 131*0b57cec5SDimitry Andric } 132*0b57cec5SDimitry Andric 133480093f4SDimitry Andric int DFAPacketizerEmitter::collectAllComboFuncs(ArrayRef<Record *> ComboFuncList) { 134*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------" 135*0b57cec5SDimitry Andric "----------------------\n"); 136*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "collectAllComboFuncs"); 137*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n"); 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric int numCombos = 0; 140*0b57cec5SDimitry Andric for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) { 141*0b57cec5SDimitry Andric Record *Func = ComboFuncList[i]; 142*0b57cec5SDimitry Andric std::vector<Record *> FUs = Func->getValueAsListOfDefs("CFD"); 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " CFD:" << i << " (" << FUs.size() << " combo FUs) " 145*0b57cec5SDimitry Andric << Func->getName() << "\n"); 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric // Convert macros to bits for each stage. 148*0b57cec5SDimitry Andric for (unsigned j = 0, N = FUs.size(); j < N; ++j) { 149*0b57cec5SDimitry Andric assert((j < DFA_MAX_RESOURCES) && 150*0b57cec5SDimitry Andric "Exceeded maximum number of DFA resources"); 151*0b57cec5SDimitry Andric Record *FuncData = FUs[j]; 152*0b57cec5SDimitry Andric Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc"); 153*0b57cec5SDimitry Andric const std::vector<Record *> &FuncList = 154*0b57cec5SDimitry Andric FuncData->getValueAsListOfDefs("FuncList"); 155*0b57cec5SDimitry Andric const std::string &ComboFuncName = ComboFunc->getName(); 156480093f4SDimitry Andric uint64_t ComboBit = FUNameToBitsMap[ComboFuncName]; 157480093f4SDimitry Andric uint64_t ComboResources = ComboBit; 158*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " combo: " << ComboFuncName << ":0x" 159*0b57cec5SDimitry Andric << Twine::utohexstr(ComboResources) << "\n"); 160*0b57cec5SDimitry Andric for (unsigned k = 0, M = FuncList.size(); k < M; ++k) { 161*0b57cec5SDimitry Andric std::string FuncName = FuncList[k]->getName(); 162480093f4SDimitry Andric uint64_t FuncResources = FUNameToBitsMap[FuncName]; 163*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " " << FuncName << ":0x" 164*0b57cec5SDimitry Andric << Twine::utohexstr(FuncResources) << "\n"); 165*0b57cec5SDimitry Andric ComboResources |= FuncResources; 166*0b57cec5SDimitry Andric } 167*0b57cec5SDimitry Andric ComboBitToBitsMap[ComboBit] = ComboResources; 168*0b57cec5SDimitry Andric numCombos++; 169*0b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x" 170*0b57cec5SDimitry Andric << Twine::utohexstr(ComboBit) << " = 0x" 171*0b57cec5SDimitry Andric << Twine::utohexstr(ComboResources) << "\n"); 172*0b57cec5SDimitry Andric } 173*0b57cec5SDimitry Andric } 174*0b57cec5SDimitry Andric return numCombos; 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric 177480093f4SDimitry Andric ResourceVector 178480093f4SDimitry Andric DFAPacketizerEmitter::getResourcesForItinerary(Record *Itinerary) { 179480093f4SDimitry Andric ResourceVector Resources; 180480093f4SDimitry Andric assert(Itinerary); 181480093f4SDimitry Andric for (Record *StageDef : Itinerary->getValueAsListOfDefs("Stages")) { 182480093f4SDimitry Andric uint64_t StageResources = 0; 183480093f4SDimitry Andric for (Record *Unit : StageDef->getValueAsListOfDefs("Units")) { 184480093f4SDimitry Andric StageResources |= FUNameToBitsMap[Unit->getName()]; 185480093f4SDimitry Andric } 186480093f4SDimitry Andric if (StageResources != 0) 187480093f4SDimitry Andric Resources.push_back(StageResources); 188480093f4SDimitry Andric } 189480093f4SDimitry Andric return Resources; 190*0b57cec5SDimitry Andric } 191*0b57cec5SDimitry Andric 192480093f4SDimitry Andric void DFAPacketizerEmitter::createScheduleClasses(unsigned ItineraryIdx, 193480093f4SDimitry Andric const RecVec &Itineraries) { 194480093f4SDimitry Andric unsigned Idx = 0; 195480093f4SDimitry Andric for (Record *Itinerary : Itineraries) { 196480093f4SDimitry Andric if (!Itinerary) { 197480093f4SDimitry Andric ScheduleClasses.push_back({ItineraryIdx, Idx++, 0, ResourceVector{}}); 198480093f4SDimitry Andric continue; 199*0b57cec5SDimitry Andric } 200480093f4SDimitry Andric ResourceVector Resources = getResourcesForItinerary(Itinerary); 201480093f4SDimitry Andric ScheduleClasses.push_back( 202480093f4SDimitry Andric {ItineraryIdx, Idx++, UniqueResources.insert(Resources), Resources}); 203*0b57cec5SDimitry Andric } 204*0b57cec5SDimitry Andric } 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric // 207*0b57cec5SDimitry Andric // Run the worklist algorithm to generate the DFA. 208*0b57cec5SDimitry Andric // 209*0b57cec5SDimitry Andric void DFAPacketizerEmitter::run(raw_ostream &OS) { 2108bcb0991SDimitry Andric OS << "\n" 2118bcb0991SDimitry Andric << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n"; 2128bcb0991SDimitry Andric OS << "namespace llvm {\n"; 2138bcb0991SDimitry Andric 214480093f4SDimitry Andric CodeGenTarget CGT(Records); 215480093f4SDimitry Andric CodeGenSchedModels CGS(Records, CGT); 2168bcb0991SDimitry Andric 217480093f4SDimitry Andric std::unordered_map<std::string, std::vector<const CodeGenProcModel *>> 218480093f4SDimitry Andric ItinsByNamespace; 219480093f4SDimitry Andric for (const CodeGenProcModel &ProcModel : CGS.procModels()) { 220480093f4SDimitry Andric if (ProcModel.hasItineraries()) { 221480093f4SDimitry Andric auto NS = ProcModel.ItinsDef->getValueAsString("PacketizerNamespace"); 222480093f4SDimitry Andric ItinsByNamespace[NS].push_back(&ProcModel); 223480093f4SDimitry Andric } 224480093f4SDimitry Andric } 2258bcb0991SDimitry Andric 2268bcb0991SDimitry Andric for (auto &KV : ItinsByNamespace) 2278bcb0991SDimitry Andric emitForItineraries(OS, KV.second, KV.first); 2288bcb0991SDimitry Andric OS << "} // end namespace llvm\n"; 2298bcb0991SDimitry Andric } 2308bcb0991SDimitry Andric 2318bcb0991SDimitry Andric void DFAPacketizerEmitter::emitForItineraries( 232480093f4SDimitry Andric raw_ostream &OS, std::vector<const CodeGenProcModel *> &ProcModels, 2338bcb0991SDimitry Andric std::string DFAName) { 234480093f4SDimitry Andric OS << "} // end namespace llvm\n\n"; 235480093f4SDimitry Andric OS << "namespace {\n"; 236480093f4SDimitry Andric collectAllFuncUnits(ProcModels); 237480093f4SDimitry Andric collectAllComboFuncs(Records.getAllDerivedDefinitions("ComboFuncUnits")); 238*0b57cec5SDimitry Andric 239*0b57cec5SDimitry Andric // Collect the itineraries. 240480093f4SDimitry Andric DenseMap<const CodeGenProcModel *, unsigned> ProcModelStartIdx; 241480093f4SDimitry Andric for (const CodeGenProcModel *Model : ProcModels) { 242480093f4SDimitry Andric assert(Model->hasItineraries()); 243480093f4SDimitry Andric ProcModelStartIdx[Model] = ScheduleClasses.size(); 244480093f4SDimitry Andric createScheduleClasses(Model->Index, Model->ItinDefList); 245*0b57cec5SDimitry Andric } 246*0b57cec5SDimitry Andric 247480093f4SDimitry Andric // Output the mapping from ScheduleClass to ResourcesIdx. 248480093f4SDimitry Andric unsigned Idx = 0; 249480093f4SDimitry Andric OS << "unsigned " << TargetName << DFAName << "ResourceIndices[] = {"; 250480093f4SDimitry Andric for (const ScheduleClass &SC : ScheduleClasses) { 251480093f4SDimitry Andric if (Idx++ % 32 == 0) 252480093f4SDimitry Andric OS << "\n "; 253480093f4SDimitry Andric OS << SC.ResourcesIdx << ", "; 254480093f4SDimitry Andric } 255480093f4SDimitry Andric OS << "\n};\n\n"; 256480093f4SDimitry Andric 257480093f4SDimitry Andric // And the mapping from Itinerary index into the previous table. 258480093f4SDimitry Andric OS << "unsigned " << TargetName << DFAName 259480093f4SDimitry Andric << "ProcResourceIndexStart[] = {\n"; 260480093f4SDimitry Andric OS << " 0, // NoSchedModel\n"; 261480093f4SDimitry Andric for (const CodeGenProcModel *Model : ProcModels) { 262480093f4SDimitry Andric OS << " " << ProcModelStartIdx[Model] << ", // " << Model->ModelName 263480093f4SDimitry Andric << "\n"; 264480093f4SDimitry Andric } 265480093f4SDimitry Andric OS << ScheduleClasses.size() << "\n};\n\n"; 266480093f4SDimitry Andric 2678bcb0991SDimitry Andric // The type of a state in the nondeterministic automaton we're defining. 268480093f4SDimitry Andric using NfaStateTy = uint64_t; 269*0b57cec5SDimitry Andric 2708bcb0991SDimitry Andric // Given a resource state, return all resource states by applying 2718bcb0991SDimitry Andric // InsnClass. 272480093f4SDimitry Andric auto applyInsnClass = [&](const ResourceVector &InsnClass, 273480093f4SDimitry Andric NfaStateTy State) -> std::deque<NfaStateTy> { 274480093f4SDimitry Andric std::deque<NfaStateTy> V(1, State); 2758bcb0991SDimitry Andric // Apply every stage in the class individually. 276480093f4SDimitry Andric for (NfaStateTy Stage : InsnClass) { 2778bcb0991SDimitry Andric // Apply this stage to every existing member of V in turn. 2788bcb0991SDimitry Andric size_t Sz = V.size(); 2798bcb0991SDimitry Andric for (unsigned I = 0; I < Sz; ++I) { 280480093f4SDimitry Andric NfaStateTy S = V.front(); 2818bcb0991SDimitry Andric V.pop_front(); 282*0b57cec5SDimitry Andric 2838bcb0991SDimitry Andric // For this stage, state combination, try all possible resources. 2848bcb0991SDimitry Andric for (unsigned J = 0; J < DFA_MAX_RESOURCES; ++J) { 285480093f4SDimitry Andric NfaStateTy ResourceMask = 1ULL << J; 2868bcb0991SDimitry Andric if ((ResourceMask & Stage) == 0) 2878bcb0991SDimitry Andric // This resource isn't required by this stage. 288*0b57cec5SDimitry Andric continue; 289480093f4SDimitry Andric NfaStateTy Combo = ComboBitToBitsMap[ResourceMask]; 2908bcb0991SDimitry Andric if (Combo && ((~S & Combo) != Combo)) 2918bcb0991SDimitry Andric // This combo units bits are not available. 2928bcb0991SDimitry Andric continue; 293480093f4SDimitry Andric NfaStateTy ResultingResourceState = S | ResourceMask | Combo; 2948bcb0991SDimitry Andric if (ResultingResourceState == S) 2958bcb0991SDimitry Andric continue; 2968bcb0991SDimitry Andric V.push_back(ResultingResourceState); 297*0b57cec5SDimitry Andric } 298*0b57cec5SDimitry Andric } 2998bcb0991SDimitry Andric } 3008bcb0991SDimitry Andric return V; 3018bcb0991SDimitry Andric }; 302*0b57cec5SDimitry Andric 3038bcb0991SDimitry Andric // Given a resource state, return a quick (conservative) guess as to whether 3048bcb0991SDimitry Andric // InsnClass can be applied. This is a filter for the more heavyweight 3058bcb0991SDimitry Andric // applyInsnClass. 306480093f4SDimitry Andric auto canApplyInsnClass = [](const ResourceVector &InsnClass, 3078bcb0991SDimitry Andric NfaStateTy State) -> bool { 308480093f4SDimitry Andric for (NfaStateTy Resources : InsnClass) { 3098bcb0991SDimitry Andric if ((State | Resources) == State) 3108bcb0991SDimitry Andric return false; 3118bcb0991SDimitry Andric } 3128bcb0991SDimitry Andric return true; 3138bcb0991SDimitry Andric }; 3148bcb0991SDimitry Andric 3158bcb0991SDimitry Andric DfaEmitter Emitter; 3168bcb0991SDimitry Andric std::deque<NfaStateTy> Worklist(1, 0); 3178bcb0991SDimitry Andric std::set<NfaStateTy> SeenStates; 3188bcb0991SDimitry Andric SeenStates.insert(Worklist.front()); 3198bcb0991SDimitry Andric while (!Worklist.empty()) { 3208bcb0991SDimitry Andric NfaStateTy State = Worklist.front(); 3218bcb0991SDimitry Andric Worklist.pop_front(); 322480093f4SDimitry Andric for (const ResourceVector &Resources : UniqueResources) { 323480093f4SDimitry Andric if (!canApplyInsnClass(Resources, State)) 3248bcb0991SDimitry Andric continue; 325480093f4SDimitry Andric unsigned ResourcesID = UniqueResources.idFor(Resources); 326480093f4SDimitry Andric for (uint64_t NewState : applyInsnClass(Resources, State)) { 3278bcb0991SDimitry Andric if (SeenStates.emplace(NewState).second) 3288bcb0991SDimitry Andric Worklist.emplace_back(NewState); 329480093f4SDimitry Andric Emitter.addTransition(State, NewState, ResourcesID); 330*0b57cec5SDimitry Andric } 331*0b57cec5SDimitry Andric } 332*0b57cec5SDimitry Andric } 333*0b57cec5SDimitry Andric 3348bcb0991SDimitry Andric std::string TargetAndDFAName = TargetName + DFAName; 3358bcb0991SDimitry Andric Emitter.emit(TargetAndDFAName, OS); 3368bcb0991SDimitry Andric OS << "} // end anonymous namespace\n\n"; 3378bcb0991SDimitry Andric 3388bcb0991SDimitry Andric std::string SubTargetClassName = TargetName + "GenSubtargetInfo"; 3398bcb0991SDimitry Andric OS << "namespace llvm {\n"; 3408bcb0991SDimitry Andric OS << "DFAPacketizer *" << SubTargetClassName << "::" 3418bcb0991SDimitry Andric << "create" << DFAName 3428bcb0991SDimitry Andric << "DFAPacketizer(const InstrItineraryData *IID) const {\n" 3438bcb0991SDimitry Andric << " static Automaton<uint64_t> A(ArrayRef<" << TargetAndDFAName 3448bcb0991SDimitry Andric << "Transition>(" << TargetAndDFAName << "Transitions), " 3458bcb0991SDimitry Andric << TargetAndDFAName << "TransitionInfo);\n" 346480093f4SDimitry Andric << " unsigned ProcResIdxStart = " << TargetAndDFAName 347480093f4SDimitry Andric << "ProcResourceIndexStart[IID->SchedModel.ProcID];\n" 348480093f4SDimitry Andric << " unsigned ProcResIdxNum = " << TargetAndDFAName 349480093f4SDimitry Andric << "ProcResourceIndexStart[IID->SchedModel.ProcID + 1] - " 350480093f4SDimitry Andric "ProcResIdxStart;\n" 351480093f4SDimitry Andric << " return new DFAPacketizer(IID, A, {&" << TargetAndDFAName 352480093f4SDimitry Andric << "ResourceIndices[ProcResIdxStart], ProcResIdxNum});\n" 3538bcb0991SDimitry Andric << "\n}\n\n"; 354*0b57cec5SDimitry Andric } 355*0b57cec5SDimitry Andric 356*0b57cec5SDimitry Andric namespace llvm { 357*0b57cec5SDimitry Andric 358*0b57cec5SDimitry Andric void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) { 359*0b57cec5SDimitry Andric emitSourceFileHeader("Target DFA Packetizer Tables", OS); 360*0b57cec5SDimitry Andric DFAPacketizerEmitter(RK).run(OS); 361*0b57cec5SDimitry Andric } 362*0b57cec5SDimitry Andric 363*0b57cec5SDimitry Andric } // end namespace llvm 364