DFAPacketizerEmitter.cpp revision 239462
1234285Sdim//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine-----===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This class parses the Schedule.td file and produces an API that can be used 11234285Sdim// to reason about whether an instruction can be added to a packet on a VLIW 12234285Sdim// architecture. The class internally generates a deterministic finite 13234285Sdim// automaton (DFA) that models all possible mappings of machine instructions 14234285Sdim// to functional units as instructions are added to a packet. 15234285Sdim// 16234285Sdim//===----------------------------------------------------------------------===// 17234285Sdim 18239462Sdim#include "CodeGenTarget.h" 19239462Sdim#include "llvm/ADT/DenseSet.h" 20234285Sdim#include "llvm/TableGen/Record.h" 21239462Sdim#include "llvm/TableGen/TableGenBackend.h" 22234285Sdim#include <list> 23239462Sdim#include <map> 24239462Sdim#include <string> 25234285Sdimusing namespace llvm; 26234285Sdim 27234285Sdim// 28239462Sdim// class DFAPacketizerEmitter: class that generates and prints out the DFA 29239462Sdim// for resource tracking. 30234285Sdim// 31239462Sdimnamespace { 32239462Sdimclass DFAPacketizerEmitter { 33239462Sdimprivate: 34239462Sdim std::string TargetName; 35239462Sdim // 36239462Sdim // allInsnClasses is the set of all possible resources consumed by an 37239462Sdim // InstrStage. 38239462Sdim // 39239462Sdim DenseSet<unsigned> allInsnClasses; 40239462Sdim RecordKeeper &Records; 41239462Sdim 42239462Sdimpublic: 43239462Sdim DFAPacketizerEmitter(RecordKeeper &R); 44239462Sdim 45239462Sdim // 46239462Sdim // collectAllInsnClasses: Populate allInsnClasses which is a set of units 47239462Sdim // used in each stage. 48239462Sdim // 49239462Sdim void collectAllInsnClasses(const std::string &Name, 50239462Sdim Record *ItinData, 51239462Sdim unsigned &NStages, 52239462Sdim raw_ostream &OS); 53239462Sdim 54239462Sdim void run(raw_ostream &OS); 55239462Sdim}; 56239462Sdim} // End anonymous namespace. 57239462Sdim 58239462Sdim// 59239462Sdim// 60234285Sdim// State represents the usage of machine resources if the packet contains 61234285Sdim// a set of instruction classes. 62234285Sdim// 63234285Sdim// Specifically, currentState is a set of bit-masks. 64234285Sdim// The nth bit in a bit-mask indicates whether the nth resource is being used 65234285Sdim// by this state. The set of bit-masks in a state represent the different 66234285Sdim// possible outcomes of transitioning to this state. 67234285Sdim// For example: consider a two resource architecture: resource L and resource M 68234285Sdim// with three instruction classes: L, M, and L_or_M. 69234285Sdim// From the initial state (currentState = 0x00), if we add instruction class 70234285Sdim// L_or_M we will transition to a state with currentState = [0x01, 0x10]. This 71234285Sdim// represents the possible resource states that can result from adding a L_or_M 72234285Sdim// instruction 73234285Sdim// 74234285Sdim// Another way of thinking about this transition is we are mapping a NDFA with 75234285Sdim// two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10]. 76234285Sdim// 77234285Sdim// 78234285Sdimnamespace { 79234285Sdimclass State { 80234285Sdim public: 81234285Sdim static int currentStateNum; 82234285Sdim int stateNum; 83234285Sdim bool isInitial; 84234285Sdim std::set<unsigned> stateInfo; 85234285Sdim 86234285Sdim State(); 87234285Sdim State(const State &S); 88234285Sdim 89234285Sdim // 90234285Sdim // canAddInsnClass - Returns true if an instruction of type InsnClass is a 91234285Sdim // valid transition from this state, i.e., can an instruction of type InsnClass 92234285Sdim // be added to the packet represented by this state. 93234285Sdim // 94234285Sdim // PossibleStates is the set of valid resource states that ensue from valid 95234285Sdim // transitions. 96234285Sdim // 97239462Sdim bool canAddInsnClass(unsigned InsnClass) const; 98239462Sdim // 99239462Sdim // AddInsnClass - Return all combinations of resource reservation 100239462Sdim // which are possible from this state (PossibleStates). 101239462Sdim // 102239462Sdim void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); 103234285Sdim}; 104234285Sdim} // End anonymous namespace. 105234285Sdim 106234285Sdim 107234285Sdimnamespace { 108234285Sdimstruct Transition { 109234285Sdim public: 110234285Sdim static int currentTransitionNum; 111234285Sdim int transitionNum; 112234285Sdim State *from; 113234285Sdim unsigned input; 114234285Sdim State *to; 115234285Sdim 116234285Sdim Transition(State *from_, unsigned input_, State *to_); 117234285Sdim}; 118234285Sdim} // End anonymous namespace. 119234285Sdim 120234285Sdim 121234285Sdim// 122234285Sdim// Comparators to keep set of states sorted. 123234285Sdim// 124234285Sdimnamespace { 125234285Sdimstruct ltState { 126234285Sdim bool operator()(const State *s1, const State *s2) const; 127234285Sdim}; 128239462Sdim 129239462Sdimstruct ltTransition { 130239462Sdim bool operator()(const Transition *s1, const Transition *s2) const; 131239462Sdim}; 132234285Sdim} // End anonymous namespace. 133234285Sdim 134234285Sdim 135234285Sdim// 136234285Sdim// class DFA: deterministic finite automaton for processor resource tracking. 137234285Sdim// 138234285Sdimnamespace { 139234285Sdimclass DFA { 140234285Sdimpublic: 141234285Sdim DFA(); 142234285Sdim 143234285Sdim // Set of states. Need to keep this sorted to emit the transition table. 144234285Sdim std::set<State*, ltState> states; 145234285Sdim 146234285Sdim // Map from a state to the list of transitions with that state as source. 147239462Sdim std::map<State*, std::set<Transition*, ltTransition>, ltState> 148239462Sdim stateTransitions; 149234285Sdim State *currentState; 150234285Sdim 151234285Sdim // Highest valued Input seen. 152234285Sdim unsigned LargestInput; 153234285Sdim 154234285Sdim // 155234285Sdim // Modify the DFA. 156234285Sdim // 157234285Sdim void initialize(); 158234285Sdim void addState(State *); 159234285Sdim void addTransition(Transition *); 160234285Sdim 161234285Sdim // 162234285Sdim // getTransition - Return the state when a transition is made from 163234285Sdim // State From with Input I. If a transition is not found, return NULL. 164234285Sdim // 165234285Sdim State *getTransition(State *, unsigned); 166234285Sdim 167234285Sdim // 168234285Sdim // isValidTransition: Predicate that checks if there is a valid transition 169234285Sdim // from state From on input InsnClass. 170234285Sdim // 171234285Sdim bool isValidTransition(State *From, unsigned InsnClass); 172234285Sdim 173234285Sdim // 174234285Sdim // writeTable: Print out a table representing the DFA. 175234285Sdim // 176234285Sdim void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName); 177234285Sdim}; 178234285Sdim} // End anonymous namespace. 179234285Sdim 180234285Sdim 181234285Sdim// 182234285Sdim// Constructors for State, Transition, and DFA 183234285Sdim// 184234285SdimState::State() : 185234285Sdim stateNum(currentStateNum++), isInitial(false) {} 186234285Sdim 187234285Sdim 188234285SdimState::State(const State &S) : 189234285Sdim stateNum(currentStateNum++), isInitial(S.isInitial), 190234285Sdim stateInfo(S.stateInfo) {} 191234285Sdim 192234285Sdim 193234285SdimTransition::Transition(State *from_, unsigned input_, State *to_) : 194234285Sdim transitionNum(currentTransitionNum++), from(from_), input(input_), 195234285Sdim to(to_) {} 196234285Sdim 197234285Sdim 198234285SdimDFA::DFA() : 199234285Sdim LargestInput(0) {} 200234285Sdim 201234285Sdim 202234285Sdimbool ltState::operator()(const State *s1, const State *s2) const { 203234285Sdim return (s1->stateNum < s2->stateNum); 204234285Sdim} 205234285Sdim 206239462Sdimbool ltTransition::operator()(const Transition *s1, const Transition *s2) const { 207239462Sdim return (s1->input < s2->input); 208239462Sdim} 209234285Sdim 210234285Sdim// 211239462Sdim// AddInsnClass - Return all combinations of resource reservation 212239462Sdim// which are possible from this state (PossibleStates). 213234285Sdim// 214239462Sdimvoid State::AddInsnClass(unsigned InsnClass, 215234285Sdim std::set<unsigned> &PossibleStates) { 216234285Sdim // 217234285Sdim // Iterate over all resource states in currentState. 218234285Sdim // 219234285Sdim 220234285Sdim for (std::set<unsigned>::iterator SI = stateInfo.begin(); 221234285Sdim SI != stateInfo.end(); ++SI) { 222234285Sdim unsigned thisState = *SI; 223234285Sdim 224234285Sdim // 225234285Sdim // Iterate over all possible resources used in InsnClass. 226234285Sdim // For ex: for InsnClass = 0x11, all resources = {0x01, 0x10}. 227234285Sdim // 228234285Sdim 229234285Sdim DenseSet<unsigned> VisitedResourceStates; 230234285Sdim for (unsigned int j = 0; j < sizeof(InsnClass) * 8; ++j) { 231234285Sdim if ((0x1 << j) & InsnClass) { 232234285Sdim // 233234285Sdim // For each possible resource used in InsnClass, generate the 234234285Sdim // resource state if that resource was used. 235234285Sdim // 236234285Sdim unsigned ResultingResourceState = thisState | (0x1 << j); 237234285Sdim // 238234285Sdim // Check if the resulting resource state can be accommodated in this 239234285Sdim // packet. 240234285Sdim // We compute ResultingResourceState OR thisState. 241234285Sdim // If the result of the OR is different than thisState, it implies 242234285Sdim // that there is at least one resource that can be used to schedule 243234285Sdim // InsnClass in the current packet. 244234285Sdim // Insert ResultingResourceState into PossibleStates only if we haven't 245234285Sdim // processed ResultingResourceState before. 246234285Sdim // 247234285Sdim if ((ResultingResourceState != thisState) && 248234285Sdim (VisitedResourceStates.count(ResultingResourceState) == 0)) { 249234285Sdim VisitedResourceStates.insert(ResultingResourceState); 250234285Sdim PossibleStates.insert(ResultingResourceState); 251234285Sdim } 252234285Sdim } 253234285Sdim } 254234285Sdim } 255234285Sdim 256234285Sdim} 257234285Sdim 258234285Sdim 259239462Sdim// 260239462Sdim// canAddInsnClass - Quickly verifies if an instruction of type InsnClass is a 261239462Sdim// valid transition from this state i.e., can an instruction of type InsnClass 262239462Sdim// be added to the packet represented by this state. 263239462Sdim// 264239462Sdimbool State::canAddInsnClass(unsigned InsnClass) const { 265239462Sdim for (std::set<unsigned>::const_iterator SI = stateInfo.begin(); 266239462Sdim SI != stateInfo.end(); ++SI) { 267239462Sdim if (~*SI & InsnClass) 268239462Sdim return true; 269239462Sdim } 270239462Sdim return false; 271239462Sdim} 272239462Sdim 273239462Sdim 274234285Sdimvoid DFA::initialize() { 275234285Sdim currentState->isInitial = true; 276234285Sdim} 277234285Sdim 278234285Sdim 279234285Sdimvoid DFA::addState(State *S) { 280234285Sdim assert(!states.count(S) && "State already exists"); 281234285Sdim states.insert(S); 282234285Sdim} 283234285Sdim 284234285Sdim 285234285Sdimvoid DFA::addTransition(Transition *T) { 286234285Sdim // Update LargestInput. 287234285Sdim if (T->input > LargestInput) 288234285Sdim LargestInput = T->input; 289234285Sdim 290234285Sdim // Add the new transition. 291239462Sdim bool Added = stateTransitions[T->from].insert(T).second; 292239462Sdim assert(Added && "Cannot have multiple states for the same input"); 293239462Sdim (void)Added; 294234285Sdim} 295234285Sdim 296234285Sdim 297234285Sdim// 298234285Sdim// getTransition - Return the state when a transition is made from 299234285Sdim// State From with Input I. If a transition is not found, return NULL. 300234285Sdim// 301234285SdimState *DFA::getTransition(State *From, unsigned I) { 302234285Sdim // Do we have a transition from state From? 303234285Sdim if (!stateTransitions.count(From)) 304234285Sdim return NULL; 305234285Sdim 306234285Sdim // Do we have a transition from state From with Input I? 307239462Sdim Transition TVal(NULL, I, NULL); 308239462Sdim // Do not count this temporal instance 309239462Sdim Transition::currentTransitionNum--; 310239462Sdim std::set<Transition*, ltTransition>::iterator T = 311239462Sdim stateTransitions[From].find(&TVal); 312239462Sdim if (T != stateTransitions[From].end()) 313239462Sdim return (*T)->to; 314234285Sdim 315234285Sdim return NULL; 316234285Sdim} 317234285Sdim 318234285Sdim 319234285Sdimbool DFA::isValidTransition(State *From, unsigned InsnClass) { 320234285Sdim return (getTransition(From, InsnClass) != NULL); 321234285Sdim} 322234285Sdim 323234285Sdim 324234285Sdimint State::currentStateNum = 0; 325234285Sdimint Transition::currentTransitionNum = 0; 326234285Sdim 327239462SdimDFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): 328234285Sdim TargetName(CodeGenTarget(R).getName()), 329234285Sdim allInsnClasses(), Records(R) {} 330234285Sdim 331234285Sdim 332234285Sdim// 333234285Sdim// writeTableAndAPI - Print out a table representing the DFA and the 334234285Sdim// associated API to create a DFA packetizer. 335234285Sdim// 336234285Sdim// Format: 337234285Sdim// DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid 338234285Sdim// transitions. 339234285Sdim// DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable for 340234285Sdim// the ith state. 341234285Sdim// 342234285Sdim// 343234285Sdimvoid DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { 344234285Sdim std::set<State*, ltState>::iterator SI = states.begin(); 345234285Sdim // This table provides a map to the beginning of the transitions for State s 346234285Sdim // in DFAStateInputTable. 347234285Sdim std::vector<int> StateEntry(states.size()); 348234285Sdim 349234285Sdim OS << "namespace llvm {\n\n"; 350234285Sdim OS << "const int " << TargetName << "DFAStateInputTable[][2] = {\n"; 351234285Sdim 352234285Sdim // Tracks the total valid transitions encountered so far. It is used 353234285Sdim // to construct the StateEntry table. 354234285Sdim int ValidTransitions = 0; 355234285Sdim for (unsigned i = 0; i < states.size(); ++i, ++SI) { 356234285Sdim StateEntry[i] = ValidTransitions; 357234285Sdim for (unsigned j = 0; j <= LargestInput; ++j) { 358234285Sdim assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); 359239462Sdim State *To = getTransition(*SI, j); 360239462Sdim if (To == NULL) 361234285Sdim continue; 362234285Sdim 363234285Sdim OS << "{" << j << ", " 364239462Sdim << To->stateNum 365234285Sdim << "}, "; 366234285Sdim ++ValidTransitions; 367234285Sdim } 368234285Sdim 369234285Sdim // If there are no valid transitions from this stage, we need a sentinel 370234285Sdim // transition. 371234285Sdim if (ValidTransitions == StateEntry[i]) { 372234285Sdim OS << "{-1, -1},"; 373234285Sdim ++ValidTransitions; 374234285Sdim } 375234285Sdim 376234285Sdim OS << "\n"; 377234285Sdim } 378234285Sdim OS << "};\n\n"; 379234285Sdim OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n"; 380234285Sdim 381234285Sdim // Multiply i by 2 since each entry in DFAStateInputTable is a set of 382234285Sdim // two numbers. 383234285Sdim for (unsigned i = 0; i < states.size(); ++i) 384234285Sdim OS << StateEntry[i] << ", "; 385234285Sdim 386234285Sdim OS << "\n};\n"; 387234285Sdim OS << "} // namespace\n"; 388234285Sdim 389234285Sdim 390234285Sdim // 391234285Sdim // Emit DFA Packetizer tables if the target is a VLIW machine. 392234285Sdim // 393234285Sdim std::string SubTargetClassName = TargetName + "GenSubtargetInfo"; 394234285Sdim OS << "\n" << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n"; 395234285Sdim OS << "namespace llvm {\n"; 396234285Sdim OS << "DFAPacketizer *" << SubTargetClassName << "::" 397234285Sdim << "createDFAPacketizer(const InstrItineraryData *IID) const {\n" 398234285Sdim << " return new DFAPacketizer(IID, " << TargetName 399234285Sdim << "DFAStateInputTable, " << TargetName << "DFAStateEntryTable);\n}\n\n"; 400234285Sdim OS << "} // End llvm namespace \n"; 401234285Sdim} 402234285Sdim 403234285Sdim 404234285Sdim// 405234285Sdim// collectAllInsnClasses - Populate allInsnClasses which is a set of units 406234285Sdim// used in each stage. 407234285Sdim// 408239462Sdimvoid DFAPacketizerEmitter::collectAllInsnClasses(const std::string &Name, 409234285Sdim Record *ItinData, 410234285Sdim unsigned &NStages, 411234285Sdim raw_ostream &OS) { 412234285Sdim // Collect processor itineraries. 413234285Sdim std::vector<Record*> ProcItinList = 414234285Sdim Records.getAllDerivedDefinitions("ProcessorItineraries"); 415234285Sdim 416234285Sdim // If just no itinerary then don't bother. 417234285Sdim if (ProcItinList.size() < 2) 418234285Sdim return; 419234285Sdim std::map<std::string, unsigned> NameToBitsMap; 420234285Sdim 421234285Sdim // Parse functional units for all the itineraries. 422234285Sdim for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) { 423234285Sdim Record *Proc = ProcItinList[i]; 424234285Sdim std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU"); 425234285Sdim 426234285Sdim // Convert macros to bits for each stage. 427234285Sdim for (unsigned i = 0, N = FUs.size(); i < N; ++i) 428234285Sdim NameToBitsMap[FUs[i]->getName()] = (unsigned) (1U << i); 429234285Sdim } 430234285Sdim 431234285Sdim const std::vector<Record*> &StageList = 432234285Sdim ItinData->getValueAsListOfDefs("Stages"); 433234285Sdim 434234285Sdim // The number of stages. 435234285Sdim NStages = StageList.size(); 436234285Sdim 437234285Sdim // For each unit. 438234285Sdim unsigned UnitBitValue = 0; 439234285Sdim 440234285Sdim // Compute the bitwise or of each unit used in this stage. 441234285Sdim for (unsigned i = 0; i < NStages; ++i) { 442234285Sdim const Record *Stage = StageList[i]; 443234285Sdim 444234285Sdim // Get unit list. 445234285Sdim const std::vector<Record*> &UnitList = 446234285Sdim Stage->getValueAsListOfDefs("Units"); 447234285Sdim 448234285Sdim for (unsigned j = 0, M = UnitList.size(); j < M; ++j) { 449234285Sdim // Conduct bitwise or. 450234285Sdim std::string UnitName = UnitList[j]->getName(); 451234285Sdim assert(NameToBitsMap.count(UnitName)); 452234285Sdim UnitBitValue |= NameToBitsMap[UnitName]; 453234285Sdim } 454234285Sdim 455234285Sdim if (UnitBitValue != 0) 456234285Sdim allInsnClasses.insert(UnitBitValue); 457234285Sdim } 458234285Sdim} 459234285Sdim 460234285Sdim 461234285Sdim// 462234285Sdim// Run the worklist algorithm to generate the DFA. 463234285Sdim// 464239462Sdimvoid DFAPacketizerEmitter::run(raw_ostream &OS) { 465234285Sdim 466234285Sdim // Collect processor iteraries. 467234285Sdim std::vector<Record*> ProcItinList = 468234285Sdim Records.getAllDerivedDefinitions("ProcessorItineraries"); 469234285Sdim 470234285Sdim // 471234285Sdim // Collect the instruction classes. 472234285Sdim // 473234285Sdim for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) { 474234285Sdim Record *Proc = ProcItinList[i]; 475234285Sdim 476234285Sdim // Get processor itinerary name. 477234285Sdim const std::string &Name = Proc->getName(); 478234285Sdim 479234285Sdim // Skip default. 480234285Sdim if (Name == "NoItineraries") 481234285Sdim continue; 482234285Sdim 483234285Sdim // Sanity check for at least one instruction itinerary class. 484234285Sdim unsigned NItinClasses = 485234285Sdim Records.getAllDerivedDefinitions("InstrItinClass").size(); 486234285Sdim if (NItinClasses == 0) 487234285Sdim return; 488234285Sdim 489234285Sdim // Get itinerary data list. 490234285Sdim std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID"); 491234285Sdim 492234285Sdim // Collect instruction classes for all itinerary data. 493234285Sdim for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) { 494234285Sdim Record *ItinData = ItinDataList[j]; 495234285Sdim unsigned NStages; 496234285Sdim collectAllInsnClasses(Name, ItinData, NStages, OS); 497234285Sdim } 498234285Sdim } 499234285Sdim 500234285Sdim 501234285Sdim // 502234285Sdim // Run a worklist algorithm to generate the DFA. 503234285Sdim // 504234285Sdim DFA D; 505234285Sdim State *Initial = new State; 506234285Sdim Initial->isInitial = true; 507234285Sdim Initial->stateInfo.insert(0x0); 508234285Sdim D.addState(Initial); 509234285Sdim SmallVector<State*, 32> WorkList; 510234285Sdim std::map<std::set<unsigned>, State*> Visited; 511234285Sdim 512234285Sdim WorkList.push_back(Initial); 513234285Sdim 514234285Sdim // 515234285Sdim // Worklist algorithm to create a DFA for processor resource tracking. 516234285Sdim // C = {set of InsnClasses} 517234285Sdim // Begin with initial node in worklist. Initial node does not have 518234285Sdim // any consumed resources, 519234285Sdim // ResourceState = 0x0 520234285Sdim // Visited = {} 521234285Sdim // While worklist != empty 522234285Sdim // S = first element of worklist 523234285Sdim // For every instruction class C 524234285Sdim // if we can accommodate C in S: 525234285Sdim // S' = state with resource states = {S Union C} 526234285Sdim // Add a new transition: S x C -> S' 527234285Sdim // If S' is not in Visited: 528234285Sdim // Add S' to worklist 529234285Sdim // Add S' to Visited 530234285Sdim // 531234285Sdim while (!WorkList.empty()) { 532234285Sdim State *current = WorkList.pop_back_val(); 533234285Sdim for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(), 534234285Sdim CE = allInsnClasses.end(); CI != CE; ++CI) { 535234285Sdim unsigned InsnClass = *CI; 536234285Sdim 537234285Sdim std::set<unsigned> NewStateResources; 538234285Sdim // 539234285Sdim // If we haven't already created a transition for this input 540234285Sdim // and the state can accommodate this InsnClass, create a transition. 541234285Sdim // 542234285Sdim if (!D.getTransition(current, InsnClass) && 543239462Sdim current->canAddInsnClass(InsnClass)) { 544234285Sdim State *NewState = NULL; 545239462Sdim current->AddInsnClass(InsnClass, NewStateResources); 546239462Sdim assert(NewStateResources.size() && "New states must be generated"); 547234285Sdim 548234285Sdim // 549234285Sdim // If we have seen this state before, then do not create a new state. 550234285Sdim // 551234285Sdim // 552234285Sdim std::map<std::set<unsigned>, State*>::iterator VI; 553234285Sdim if ((VI = Visited.find(NewStateResources)) != Visited.end()) 554234285Sdim NewState = VI->second; 555234285Sdim else { 556234285Sdim NewState = new State; 557234285Sdim NewState->stateInfo = NewStateResources; 558234285Sdim D.addState(NewState); 559234285Sdim Visited[NewStateResources] = NewState; 560234285Sdim WorkList.push_back(NewState); 561234285Sdim } 562234285Sdim 563234285Sdim Transition *NewTransition = new Transition(current, InsnClass, 564234285Sdim NewState); 565234285Sdim D.addTransition(NewTransition); 566234285Sdim } 567234285Sdim } 568234285Sdim } 569234285Sdim 570234285Sdim // Print out the table. 571234285Sdim D.writeTableAndAPI(OS, TargetName); 572234285Sdim} 573239462Sdim 574239462Sdimnamespace llvm { 575239462Sdim 576239462Sdimvoid EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) { 577239462Sdim emitSourceFileHeader("Target DFA Packetizer Tables", OS); 578239462Sdim DFAPacketizerEmitter(RK).run(OS); 579239462Sdim} 580239462Sdim 581239462Sdim} // End llvm namespace 582