Store State objects by value in TableGen's DFAPacketizerEmitter

Removes some extra manual dynamic memory allocation/management. It does
get a bit quirky having to make State's members mutable and
pointers/references to const rather than non-const, but that's a
necessary workaround to dealing with the std::set elements.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206807 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Blaikie 2014-04-21 22:35:11 +00:00
parent 32eba65e0c
commit c37ae28d93

View File

@ -82,11 +82,13 @@ namespace {
class State { class State {
public: public:
static int currentStateNum; static int currentStateNum;
int stateNum; // stateNum is the only member used for equality/ordering, all other members
bool isInitial; // can be mutated even in const State objects.
std::set<unsigned> stateInfo; const int stateNum;
typedef std::map<unsigned, State *> TransitionMap; mutable bool isInitial;
TransitionMap Transitions; mutable std::set<unsigned> stateInfo;
typedef std::map<unsigned, const State *> TransitionMap;
mutable TransitionMap Transitions;
State(); State();
State(const State &S); State(const State &S);
@ -108,16 +110,16 @@ class State {
// AddInsnClass - Return all combinations of resource reservation // AddInsnClass - Return all combinations of resource reservation
// which are possible from this state (PossibleStates). // which are possible from this state (PossibleStates).
// //
void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates) const;
// //
// addTransition - Add a transition from this state given the input InsnClass // addTransition - Add a transition from this state given the input InsnClass
// //
void addTransition(unsigned InsnClass, State *To); void addTransition(unsigned InsnClass, const State *To) const;
// //
// hasTransition - Returns true if there is a transition from this state // hasTransition - Returns true if there is a transition from this state
// given the input InsnClass // given the input InsnClass
// //
bool hasTransition(unsigned InsnClass); bool hasTransition(unsigned InsnClass) const;
}; };
} // End anonymous namespace. } // End anonymous namespace.
@ -128,10 +130,9 @@ namespace {
class DFA { class DFA {
public: public:
DFA(); DFA();
~DFA();
// Set of states. Need to keep this sorted to emit the transition table. // Set of states. Need to keep this sorted to emit the transition table.
typedef std::set<State *, less_ptr<State> > StateSet; typedef std::set<State> StateSet;
StateSet states; StateSet states;
State *currentState; State *currentState;
@ -139,7 +140,7 @@ public:
// //
// Modify the DFA. // Modify the DFA.
// //
void addState(State *); const State &newState();
// //
// writeTable: Print out a table representing the DFA. // writeTable: Print out a table representing the DFA.
@ -162,14 +163,10 @@ State::State(const State &S) :
DFA::DFA(): currentState(nullptr) {} DFA::DFA(): currentState(nullptr) {}
DFA::~DFA() {
DeleteContainerPointers(states);
}
// //
// addTransition - Add a transition from this state given the input InsnClass // addTransition - Add a transition from this state given the input InsnClass
// //
void State::addTransition(unsigned InsnClass, State *To) { void State::addTransition(unsigned InsnClass, const State *To) const {
assert(!Transitions.count(InsnClass) && assert(!Transitions.count(InsnClass) &&
"Cannot have multiple transitions for the same input"); "Cannot have multiple transitions for the same input");
Transitions[InsnClass] = To; Transitions[InsnClass] = To;
@ -179,7 +176,7 @@ void State::addTransition(unsigned InsnClass, State *To) {
// hasTransition - Returns true if there is a transition from this state // hasTransition - Returns true if there is a transition from this state
// given the input InsnClass // given the input InsnClass
// //
bool State::hasTransition(unsigned InsnClass) { bool State::hasTransition(unsigned InsnClass) const {
return Transitions.count(InsnClass) > 0; return Transitions.count(InsnClass) > 0;
} }
@ -188,7 +185,7 @@ bool State::hasTransition(unsigned InsnClass) {
// which are possible from this state (PossibleStates). // which are possible from this state (PossibleStates).
// //
void State::AddInsnClass(unsigned InsnClass, void State::AddInsnClass(unsigned InsnClass,
std::set<unsigned> &PossibleStates) { std::set<unsigned> &PossibleStates) const {
// //
// Iterate over all resource states in currentState. // Iterate over all resource states in currentState.
// //
@ -247,9 +244,10 @@ bool State::canAddInsnClass(unsigned InsnClass) const {
} }
void DFA::addState(State *S) { const State &DFA::newState() {
assert(!states.count(S) && "State already exists"); auto IterPair = states.emplace();
states.insert(S); assert(IterPair.second && "State already exists");
return *IterPair.first;
} }
@ -285,16 +283,16 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) {
// to construct the StateEntry table. // to construct the StateEntry table.
int ValidTransitions = 0; int ValidTransitions = 0;
for (unsigned i = 0; i < states.size(); ++i, ++SI) { for (unsigned i = 0; i < states.size(); ++i, ++SI) {
assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); assert ((SI->stateNum == (int) i) && "Mismatch in state numbers");
StateEntry[i] = ValidTransitions; StateEntry[i] = ValidTransitions;
for (State::TransitionMap::iterator for (State::TransitionMap::iterator
II = (*SI)->Transitions.begin(), IE = (*SI)->Transitions.end(); II = SI->Transitions.begin(), IE = SI->Transitions.end();
II != IE; ++II) { II != IE; ++II) {
OS << "{" << II->first << ", " OS << "{" << II->first << ", "
<< II->second->stateNum << II->second->stateNum
<< "}, "; << "}, ";
} }
ValidTransitions += (*SI)->Transitions.size(); ValidTransitions += SI->Transitions.size();
// If there are no valid transitions from this stage, we need a sentinel // If there are no valid transitions from this stage, we need a sentinel
// transition. // transition.
@ -440,12 +438,11 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
// Run a worklist algorithm to generate the DFA. // Run a worklist algorithm to generate the DFA.
// //
DFA D; DFA D;
State *Initial = new State; const State *Initial = &D.newState();
Initial->isInitial = true; Initial->isInitial = true;
Initial->stateInfo.insert(0x0); Initial->stateInfo.insert(0x0);
D.addState(Initial); SmallVector<const State*, 32> WorkList;
SmallVector<State*, 32> WorkList; std::map<std::set<unsigned>, const State*> Visited;
std::map<std::set<unsigned>, State*> Visited;
WorkList.push_back(Initial); WorkList.push_back(Initial);
@ -467,7 +464,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
// Add S' to Visited // Add S' to Visited
// //
while (!WorkList.empty()) { while (!WorkList.empty()) {
State *current = WorkList.pop_back_val(); const State *current = WorkList.pop_back_val();
for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(), for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(),
CE = allInsnClasses.end(); CI != CE; ++CI) { CE = allInsnClasses.end(); CI != CE; ++CI) {
unsigned InsnClass = *CI; unsigned InsnClass = *CI;
@ -479,7 +476,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
// //
if (!current->hasTransition(InsnClass) && if (!current->hasTransition(InsnClass) &&
current->canAddInsnClass(InsnClass)) { current->canAddInsnClass(InsnClass)) {
State *NewState = nullptr; const State *NewState;
current->AddInsnClass(InsnClass, NewStateResources); current->AddInsnClass(InsnClass, NewStateResources);
assert(NewStateResources.size() && "New states must be generated"); assert(NewStateResources.size() && "New states must be generated");
@ -487,13 +484,12 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
// If we have seen this state before, then do not create a new state. // If we have seen this state before, then do not create a new state.
// //
// //
std::map<std::set<unsigned>, State*>::iterator VI; auto VI = Visited.find(NewStateResources);
if ((VI = Visited.find(NewStateResources)) != Visited.end()) if (VI != Visited.end())
NewState = VI->second; NewState = VI->second;
else { else {
NewState = new State; NewState = &D.newState();
NewState->stateInfo = NewStateResources; NewState->stateInfo = NewStateResources;
D.addState(NewState);
Visited[NewStateResources] = NewState; Visited[NewStateResources] = NewState;
WorkList.push_back(NewState); WorkList.push_back(NewState);
} }