10b57cec5SDimitry Andric //===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This class parses the Schedule.td file and produces an API that can be used 100b57cec5SDimitry Andric // to reason about whether an instruction can be added to a packet on a VLIW 110b57cec5SDimitry Andric // architecture. The class internally generates a deterministic finite 120b57cec5SDimitry Andric // automaton (DFA) that models all possible mappings of machine instructions 130b57cec5SDimitry Andric // to functional units as instructions are added to a packet. 140b57cec5SDimitry Andric // 150b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 160b57cec5SDimitry Andric 17*0fca6ea1SDimitry Andric #include "Common/CodeGenSchedule.h" 18*0fca6ea1SDimitry Andric #include "Common/CodeGenTarget.h" 198bcb0991SDimitry Andric #include "DFAEmitter.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 210b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 23480093f4SDimitry Andric #include "llvm/TableGen/Record.h" 24480093f4SDimitry Andric #include "llvm/TableGen/TableGenBackend.h" 250b57cec5SDimitry Andric #include <cassert> 260b57cec5SDimitry Andric #include <cstdint> 2706c3fb27SDimitry Andric #include <deque> 280b57cec5SDimitry Andric #include <map> 290b57cec5SDimitry Andric #include <set> 300b57cec5SDimitry Andric #include <string> 318bcb0991SDimitry Andric #include <unordered_map> 320b57cec5SDimitry Andric #include <vector> 330b57cec5SDimitry Andric 34fe6060f1SDimitry Andric #define DEBUG_TYPE "dfa-emitter" 35fe6060f1SDimitry Andric 360b57cec5SDimitry Andric using namespace llvm; 370b57cec5SDimitry Andric 38480093f4SDimitry Andric // We use a uint64_t to represent a resource bitmask. 39480093f4SDimitry Andric #define DFA_MAX_RESOURCES 64 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric namespace { 42480093f4SDimitry Andric using ResourceVector = SmallVector<uint64_t, 4>; 430b57cec5SDimitry Andric 44480093f4SDimitry Andric struct ScheduleClass { 45480093f4SDimitry Andric /// The parent itinerary index (processor model ID). 46480093f4SDimitry Andric unsigned ItineraryID; 470b57cec5SDimitry Andric 48480093f4SDimitry Andric /// Index within this itinerary of the schedule class. 49480093f4SDimitry Andric unsigned Idx; 500b57cec5SDimitry Andric 51480093f4SDimitry Andric /// The index within the uniqued set of required resources of Resources. 52480093f4SDimitry Andric unsigned ResourcesIdx; 530b57cec5SDimitry Andric 54480093f4SDimitry Andric /// Conjunctive list of resource requirements: 55480093f4SDimitry Andric /// {a|b, b|c} => (a OR b) AND (b or c). 56480093f4SDimitry Andric /// Resources are unique across all itineraries. 57480093f4SDimitry Andric ResourceVector Resources; 58480093f4SDimitry Andric }; 590b57cec5SDimitry Andric 60480093f4SDimitry Andric // Generates and prints out the DFA for resource tracking. 610b57cec5SDimitry Andric class DFAPacketizerEmitter { 620b57cec5SDimitry Andric private: 630b57cec5SDimitry Andric std::string TargetName; 640b57cec5SDimitry Andric RecordKeeper &Records; 650b57cec5SDimitry Andric 66480093f4SDimitry Andric UniqueVector<ResourceVector> UniqueResources; 67480093f4SDimitry Andric std::vector<ScheduleClass> ScheduleClasses; 68480093f4SDimitry Andric std::map<std::string, uint64_t> FUNameToBitsMap; 69480093f4SDimitry Andric std::map<unsigned, uint64_t> ComboBitToBitsMap; 70480093f4SDimitry Andric 710b57cec5SDimitry Andric public: 720b57cec5SDimitry Andric DFAPacketizerEmitter(RecordKeeper &R); 730b57cec5SDimitry Andric 74480093f4SDimitry Andric // Construct a map of function unit names to bits. 75*0fca6ea1SDimitry Andric int collectAllFuncUnits(ArrayRef<const CodeGenProcModel *> ProcModels); 760b57cec5SDimitry Andric 77480093f4SDimitry Andric // Construct a map from a combo function unit bit to the bits of all included 78480093f4SDimitry Andric // functional units. 79480093f4SDimitry Andric int collectAllComboFuncs(ArrayRef<Record *> ComboFuncList); 800b57cec5SDimitry Andric 81480093f4SDimitry Andric ResourceVector getResourcesForItinerary(Record *Itinerary); 82480093f4SDimitry Andric void createScheduleClasses(unsigned ItineraryIdx, const RecVec &Itineraries); 830b57cec5SDimitry Andric 848bcb0991SDimitry Andric // Emit code for a subset of itineraries. 858bcb0991SDimitry Andric void emitForItineraries(raw_ostream &OS, 86480093f4SDimitry Andric std::vector<const CodeGenProcModel *> &ProcItinList, 878bcb0991SDimitry Andric std::string DFAName); 888bcb0991SDimitry Andric 890b57cec5SDimitry Andric void run(raw_ostream &OS); 900b57cec5SDimitry Andric }; 910b57cec5SDimitry Andric } // end anonymous namespace 920b57cec5SDimitry Andric 93480093f4SDimitry Andric DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R) 945ffd83dbSDimitry Andric : TargetName(std::string(CodeGenTarget(R).getName())), Records(R) {} 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric int DFAPacketizerEmitter::collectAllFuncUnits( 97480093f4SDimitry Andric ArrayRef<const CodeGenProcModel *> ProcModels) { 980b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------" 990b57cec5SDimitry Andric "----------------------\n"); 1000b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "collectAllFuncUnits"); 101480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " (" << ProcModels.size() << " itineraries)\n"); 102480093f4SDimitry Andric 103480093f4SDimitry Andric std::set<Record *> ProcItinList; 104480093f4SDimitry Andric for (const CodeGenProcModel *Model : ProcModels) 105480093f4SDimitry Andric ProcItinList.insert(Model->ItinsDef); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric int totalFUs = 0; 1080b57cec5SDimitry Andric // Parse functional units for all the itineraries. 109480093f4SDimitry Andric for (Record *Proc : ProcItinList) { 1100b57cec5SDimitry Andric std::vector<Record *> FUs = Proc->getValueAsListOfDefs("FU"); 1110b57cec5SDimitry Andric 112480093f4SDimitry Andric LLVM_DEBUG(dbgs() << " FU:" 113480093f4SDimitry Andric << " (" << FUs.size() << " FUs) " << Proc->getName()); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric // Convert macros to bits for each stage. 1160b57cec5SDimitry Andric unsigned numFUs = FUs.size(); 1170b57cec5SDimitry Andric for (unsigned j = 0; j < numFUs; ++j) { 1180b57cec5SDimitry Andric assert((j < DFA_MAX_RESOURCES) && 1190b57cec5SDimitry Andric "Exceeded maximum number of representable resources"); 120480093f4SDimitry Andric uint64_t FuncResources = 1ULL << j; 1215ffd83dbSDimitry Andric FUNameToBitsMap[std::string(FUs[j]->getName())] = FuncResources; 1220b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " " << FUs[j]->getName() << ":0x" 1230b57cec5SDimitry Andric << Twine::utohexstr(FuncResources)); 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric totalFUs += numFUs; 1260b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "\n"); 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric return totalFUs; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 131*0fca6ea1SDimitry Andric int DFAPacketizerEmitter::collectAllComboFuncs( 132*0fca6ea1SDimitry Andric ArrayRef<Record *> ComboFuncList) { 1330b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "-------------------------------------------------------" 1340b57cec5SDimitry Andric "----------------------\n"); 1350b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "collectAllComboFuncs"); 1360b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n"); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric int numCombos = 0; 1390b57cec5SDimitry Andric for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) { 1400b57cec5SDimitry Andric Record *Func = ComboFuncList[i]; 1410b57cec5SDimitry Andric std::vector<Record *> FUs = Func->getValueAsListOfDefs("CFD"); 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " CFD:" << i << " (" << FUs.size() << " combo FUs) " 1440b57cec5SDimitry Andric << Func->getName() << "\n"); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // Convert macros to bits for each stage. 1470b57cec5SDimitry Andric for (unsigned j = 0, N = FUs.size(); j < N; ++j) { 1480b57cec5SDimitry Andric assert((j < DFA_MAX_RESOURCES) && 1490b57cec5SDimitry Andric "Exceeded maximum number of DFA resources"); 1500b57cec5SDimitry Andric Record *FuncData = FUs[j]; 1510b57cec5SDimitry Andric Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc"); 1520b57cec5SDimitry Andric const std::vector<Record *> &FuncList = 1530b57cec5SDimitry Andric FuncData->getValueAsListOfDefs("FuncList"); 1545ffd83dbSDimitry Andric const std::string &ComboFuncName = std::string(ComboFunc->getName()); 155480093f4SDimitry Andric uint64_t ComboBit = FUNameToBitsMap[ComboFuncName]; 156480093f4SDimitry Andric uint64_t ComboResources = ComboBit; 1570b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " combo: " << ComboFuncName << ":0x" 1580b57cec5SDimitry Andric << Twine::utohexstr(ComboResources) << "\n"); 159fe6060f1SDimitry Andric for (auto *K : FuncList) { 160fe6060f1SDimitry Andric std::string FuncName = std::string(K->getName()); 161480093f4SDimitry Andric uint64_t FuncResources = FUNameToBitsMap[FuncName]; 1620b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " " << FuncName << ":0x" 1630b57cec5SDimitry Andric << Twine::utohexstr(FuncResources) << "\n"); 1640b57cec5SDimitry Andric ComboResources |= FuncResources; 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric ComboBitToBitsMap[ComboBit] = ComboResources; 1670b57cec5SDimitry Andric numCombos++; 1680b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x" 1690b57cec5SDimitry Andric << Twine::utohexstr(ComboBit) << " = 0x" 1700b57cec5SDimitry Andric << Twine::utohexstr(ComboResources) << "\n"); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric return numCombos; 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 176480093f4SDimitry Andric ResourceVector 177480093f4SDimitry Andric DFAPacketizerEmitter::getResourcesForItinerary(Record *Itinerary) { 178480093f4SDimitry Andric ResourceVector Resources; 179480093f4SDimitry Andric assert(Itinerary); 180480093f4SDimitry Andric for (Record *StageDef : Itinerary->getValueAsListOfDefs("Stages")) { 181480093f4SDimitry Andric uint64_t StageResources = 0; 182480093f4SDimitry Andric for (Record *Unit : StageDef->getValueAsListOfDefs("Units")) { 1835ffd83dbSDimitry Andric StageResources |= FUNameToBitsMap[std::string(Unit->getName())]; 184480093f4SDimitry Andric } 185480093f4SDimitry Andric if (StageResources != 0) 186480093f4SDimitry Andric Resources.push_back(StageResources); 187480093f4SDimitry Andric } 188480093f4SDimitry Andric return Resources; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 191480093f4SDimitry Andric void DFAPacketizerEmitter::createScheduleClasses(unsigned ItineraryIdx, 192480093f4SDimitry Andric const RecVec &Itineraries) { 193480093f4SDimitry Andric unsigned Idx = 0; 194480093f4SDimitry Andric for (Record *Itinerary : Itineraries) { 195480093f4SDimitry Andric if (!Itinerary) { 196480093f4SDimitry Andric ScheduleClasses.push_back({ItineraryIdx, Idx++, 0, ResourceVector{}}); 197480093f4SDimitry Andric continue; 1980b57cec5SDimitry Andric } 199480093f4SDimitry Andric ResourceVector Resources = getResourcesForItinerary(Itinerary); 200480093f4SDimitry Andric ScheduleClasses.push_back( 201480093f4SDimitry Andric {ItineraryIdx, Idx++, UniqueResources.insert(Resources), Resources}); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric // 2060b57cec5SDimitry Andric // Run the worklist algorithm to generate the DFA. 2070b57cec5SDimitry Andric // 2080b57cec5SDimitry Andric void DFAPacketizerEmitter::run(raw_ostream &OS) { 20906c3fb27SDimitry Andric emitSourceFileHeader("Target DFA Packetizer Tables", 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"); 2225ffd83dbSDimitry Andric ItinsByNamespace[std::string(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")); 2380b57cec5SDimitry Andric 2390b57cec5SDimitry 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); 2450b57cec5SDimitry Andric } 2460b57cec5SDimitry Andric 247480093f4SDimitry Andric // Output the mapping from ScheduleClass to ResourcesIdx. 248480093f4SDimitry Andric unsigned Idx = 0; 2495ffd83dbSDimitry Andric OS << "constexpr unsigned " << TargetName << DFAName 2505ffd83dbSDimitry Andric << "ResourceIndices[] = {"; 251480093f4SDimitry Andric for (const ScheduleClass &SC : ScheduleClasses) { 252480093f4SDimitry Andric if (Idx++ % 32 == 0) 253480093f4SDimitry Andric OS << "\n "; 254480093f4SDimitry Andric OS << SC.ResourcesIdx << ", "; 255480093f4SDimitry Andric } 256480093f4SDimitry Andric OS << "\n};\n\n"; 257480093f4SDimitry Andric 258480093f4SDimitry Andric // And the mapping from Itinerary index into the previous table. 2595ffd83dbSDimitry Andric OS << "constexpr unsigned " << TargetName << DFAName 260480093f4SDimitry Andric << "ProcResourceIndexStart[] = {\n"; 261480093f4SDimitry Andric OS << " 0, // NoSchedModel\n"; 262480093f4SDimitry Andric for (const CodeGenProcModel *Model : ProcModels) { 263480093f4SDimitry Andric OS << " " << ProcModelStartIdx[Model] << ", // " << Model->ModelName 264480093f4SDimitry Andric << "\n"; 265480093f4SDimitry Andric } 266e8d8bef9SDimitry Andric OS << " " << ScheduleClasses.size() << "\n};\n\n"; 267480093f4SDimitry Andric 2688bcb0991SDimitry Andric // The type of a state in the nondeterministic automaton we're defining. 269480093f4SDimitry Andric using NfaStateTy = uint64_t; 2700b57cec5SDimitry Andric 2718bcb0991SDimitry Andric // Given a resource state, return all resource states by applying 2728bcb0991SDimitry Andric // InsnClass. 273480093f4SDimitry Andric auto applyInsnClass = [&](const ResourceVector &InsnClass, 274480093f4SDimitry Andric NfaStateTy State) -> std::deque<NfaStateTy> { 275480093f4SDimitry Andric std::deque<NfaStateTy> V(1, State); 2768bcb0991SDimitry Andric // Apply every stage in the class individually. 277480093f4SDimitry Andric for (NfaStateTy Stage : InsnClass) { 2788bcb0991SDimitry Andric // Apply this stage to every existing member of V in turn. 2798bcb0991SDimitry Andric size_t Sz = V.size(); 2808bcb0991SDimitry Andric for (unsigned I = 0; I < Sz; ++I) { 281480093f4SDimitry Andric NfaStateTy S = V.front(); 2828bcb0991SDimitry Andric V.pop_front(); 2830b57cec5SDimitry Andric 2848bcb0991SDimitry Andric // For this stage, state combination, try all possible resources. 2858bcb0991SDimitry Andric for (unsigned J = 0; J < DFA_MAX_RESOURCES; ++J) { 286480093f4SDimitry Andric NfaStateTy ResourceMask = 1ULL << J; 2878bcb0991SDimitry Andric if ((ResourceMask & Stage) == 0) 2888bcb0991SDimitry Andric // This resource isn't required by this stage. 2890b57cec5SDimitry Andric continue; 290480093f4SDimitry Andric NfaStateTy Combo = ComboBitToBitsMap[ResourceMask]; 2918bcb0991SDimitry Andric if (Combo && ((~S & Combo) != Combo)) 2928bcb0991SDimitry Andric // This combo units bits are not available. 2938bcb0991SDimitry Andric continue; 294480093f4SDimitry Andric NfaStateTy ResultingResourceState = S | ResourceMask | Combo; 2958bcb0991SDimitry Andric if (ResultingResourceState == S) 2968bcb0991SDimitry Andric continue; 2978bcb0991SDimitry Andric V.push_back(ResultingResourceState); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric } 3008bcb0991SDimitry Andric } 3018bcb0991SDimitry Andric return V; 3028bcb0991SDimitry Andric }; 3030b57cec5SDimitry Andric 3048bcb0991SDimitry Andric // Given a resource state, return a quick (conservative) guess as to whether 3058bcb0991SDimitry Andric // InsnClass can be applied. This is a filter for the more heavyweight 3068bcb0991SDimitry Andric // applyInsnClass. 307480093f4SDimitry Andric auto canApplyInsnClass = [](const ResourceVector &InsnClass, 3088bcb0991SDimitry Andric NfaStateTy State) -> bool { 309480093f4SDimitry Andric for (NfaStateTy Resources : InsnClass) { 3108bcb0991SDimitry Andric if ((State | Resources) == State) 3118bcb0991SDimitry Andric return false; 3128bcb0991SDimitry Andric } 3138bcb0991SDimitry Andric return true; 3148bcb0991SDimitry Andric }; 3158bcb0991SDimitry Andric 3168bcb0991SDimitry Andric DfaEmitter Emitter; 3178bcb0991SDimitry Andric std::deque<NfaStateTy> Worklist(1, 0); 3188bcb0991SDimitry Andric std::set<NfaStateTy> SeenStates; 3198bcb0991SDimitry Andric SeenStates.insert(Worklist.front()); 3208bcb0991SDimitry Andric while (!Worklist.empty()) { 3218bcb0991SDimitry Andric NfaStateTy State = Worklist.front(); 3228bcb0991SDimitry Andric Worklist.pop_front(); 323480093f4SDimitry Andric for (const ResourceVector &Resources : UniqueResources) { 324480093f4SDimitry Andric if (!canApplyInsnClass(Resources, State)) 3258bcb0991SDimitry Andric continue; 326480093f4SDimitry Andric unsigned ResourcesID = UniqueResources.idFor(Resources); 327480093f4SDimitry Andric for (uint64_t NewState : applyInsnClass(Resources, State)) { 3288bcb0991SDimitry Andric if (SeenStates.emplace(NewState).second) 3298bcb0991SDimitry Andric Worklist.emplace_back(NewState); 330480093f4SDimitry Andric Emitter.addTransition(State, NewState, ResourcesID); 3310b57cec5SDimitry Andric } 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3358bcb0991SDimitry Andric std::string TargetAndDFAName = TargetName + DFAName; 3368bcb0991SDimitry Andric Emitter.emit(TargetAndDFAName, OS); 3378bcb0991SDimitry Andric OS << "} // end anonymous namespace\n\n"; 3388bcb0991SDimitry Andric 3398bcb0991SDimitry Andric std::string SubTargetClassName = TargetName + "GenSubtargetInfo"; 3408bcb0991SDimitry Andric OS << "namespace llvm {\n"; 3418bcb0991SDimitry Andric OS << "DFAPacketizer *" << SubTargetClassName << "::" 3428bcb0991SDimitry Andric << "create" << DFAName 3438bcb0991SDimitry Andric << "DFAPacketizer(const InstrItineraryData *IID) const {\n" 3448bcb0991SDimitry Andric << " static Automaton<uint64_t> A(ArrayRef<" << TargetAndDFAName 3458bcb0991SDimitry Andric << "Transition>(" << TargetAndDFAName << "Transitions), " 3468bcb0991SDimitry Andric << TargetAndDFAName << "TransitionInfo);\n" 347480093f4SDimitry Andric << " unsigned ProcResIdxStart = " << TargetAndDFAName 348480093f4SDimitry Andric << "ProcResourceIndexStart[IID->SchedModel.ProcID];\n" 349480093f4SDimitry Andric << " unsigned ProcResIdxNum = " << TargetAndDFAName 350480093f4SDimitry Andric << "ProcResourceIndexStart[IID->SchedModel.ProcID + 1] - " 351480093f4SDimitry Andric "ProcResIdxStart;\n" 352480093f4SDimitry Andric << " return new DFAPacketizer(IID, A, {&" << TargetAndDFAName 353480093f4SDimitry Andric << "ResourceIndices[ProcResIdxStart], ProcResIdxNum});\n" 3548bcb0991SDimitry Andric << "\n}\n\n"; 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 35706c3fb27SDimitry Andric static TableGen::Emitter::OptClass<DFAPacketizerEmitter> 35806c3fb27SDimitry Andric X("gen-dfa-packetizer", "Generate DFA Packetizer for VLIW targets"); 359