diff options
author | Derek Schuff <dschuff@chromium.org> | 2012-09-19 16:10:54 -0700 |
---|---|---|
committer | Derek Schuff <dschuff@chromium.org> | 2012-09-19 16:10:54 -0700 |
commit | 0e15ffd8cb1ec642eddb96380660914ff2b007e1 (patch) | |
tree | bc5ccf8c89bfe799bb276625e8e0bd6d84e3a75c /utils/TableGen | |
parent | 5e79ec1d7ada2e14283e2b69b6f4375eb4dd1890 (diff) | |
parent | 020aba0c3b6092e353e133446cb6453f95f0d61b (diff) |
Merge commit '020aba0c3b6092e353e133446cb6453f95f0d61b'
Diffstat (limited to 'utils/TableGen')
-rw-r--r-- | utils/TableGen/CodeGenRegisters.cpp | 58 | ||||
-rw-r--r-- | utils/TableGen/CodeGenRegisters.h | 10 | ||||
-rw-r--r-- | utils/TableGen/DFAPacketizerEmitter.cpp | 168 | ||||
-rw-r--r-- | utils/TableGen/RegisterInfoEmitter.cpp | 24 | ||||
-rw-r--r-- | utils/TableGen/X86DisassemblerTables.cpp | 4 |
5 files changed, 123 insertions, 141 deletions
diff --git a/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp index b2e9e38bc1..931807ae44 100644 --- a/utils/TableGen/CodeGenRegisters.cpp +++ b/utils/TableGen/CodeGenRegisters.cpp @@ -28,7 +28,7 @@ using namespace llvm; //===----------------------------------------------------------------------===// CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) - : TheDef(R), EnumValue(Enum) { + : TheDef(R), EnumValue(Enum), LaneMask(0) { Name = R->getName(); if (R->getValue("Namespace")) Namespace = R->getValueAsString("Namespace"); @@ -36,7 +36,7 @@ CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum) CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum) - : TheDef(0), Name(N), Namespace(Nspace), EnumValue(Enum) { + : TheDef(0), Name(N), Namespace(Nspace), EnumValue(Enum), LaneMask(0) { } std::string CodeGenSubRegIndex::getQualifiedName() const { @@ -75,14 +75,21 @@ void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) { } } -void CodeGenSubRegIndex::cleanComposites() { - // Clean out redundant mappings of the form this+X -> X. - for (CompMap::iterator i = Composed.begin(), e = Composed.end(); i != e;) { - CompMap::iterator j = i; - ++i; - if (j->first == j->second) - Composed.erase(j); - } +unsigned CodeGenSubRegIndex::computeLaneMask() { + // Already computed? + if (LaneMask) + return LaneMask; + + // Recursion guard, shouldn't be required. + LaneMask = ~0u; + + // The lane mask is simply the union of all sub-indices. + unsigned M = 0; + for (CompMap::iterator I = Composed.begin(), E = Composed.end(); I != E; ++I) + M |= I->second->computeLaneMask(); + assert(M && "Missing lane mask, sub-register cycle?"); + LaneMask = M; + return LaneMask; } //===----------------------------------------------------------------------===// @@ -1164,11 +1171,35 @@ void CodeGenRegBank::computeComposites() { } } } +} + +// Compute lane masks. This is similar to register units, but at the +// sub-register index level. Each bit in the lane mask is like a register unit +// class, and two lane masks will have a bit in common if two sub-register +// indices overlap in some register. +// +// Conservatively share a lane mask bit if two sub-register indices overlap in +// some registers, but not in others. That shouldn't happen a lot. +void CodeGenRegBank::computeSubRegIndexLaneMasks() { + // First assign individual bits to all the leaf indices. + unsigned Bit = 0; + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + CodeGenSubRegIndex *Idx = SubRegIndices[i]; + if (Idx->getComposites().empty()) { + Idx->LaneMask = 1u << Bit; + // Share bit 31 in the unlikely case there are more than 32 leafs. + if (Bit < 31) ++Bit; + } else { + Idx->LaneMask = 0; + } + } + + // FIXME: What if ad-hoc aliasing introduces overlaps that aren't represented + // by the sub-register graph? This doesn't occur in any known targets. - // We don't care about the difference between (Idx1, Idx2) -> Idx2 and invalid - // compositions, so remove any mappings of that form. + // Inherit lanes from composites. for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) - SubRegIndices[i]->cleanComposites(); + SubRegIndices[i]->computeLaneMask(); } namespace { @@ -1554,6 +1585,7 @@ void CodeGenRegBank::computeRegUnitSets() { void CodeGenRegBank::computeDerivedInfo() { computeComposites(); + computeSubRegIndexLaneMasks(); // Compute a weight for each register unit created during getSubRegs. // This may create adopted register units (with unit # >= NumNativeRegUnits). diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h index 827063e470..bd748ca62e 100644 --- a/utils/TableGen/CodeGenRegisters.h +++ b/utils/TableGen/CodeGenRegisters.h @@ -40,6 +40,7 @@ namespace llvm { public: const unsigned EnumValue; + unsigned LaneMask; CodeGenSubRegIndex(Record *R, unsigned Enum); CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum); @@ -80,12 +81,12 @@ namespace llvm { // Update the composite maps of components specified in 'ComposedOf'. void updateComponents(CodeGenRegBank&); - // Clean out redundant composite mappings. - void cleanComposites(); - // Return the map of composites. const CompMap &getComposites() const { return Composed; } + // Compute LaneMask from Composed. Return LaneMask. + unsigned computeLaneMask(); + private: CompMap Composed; }; @@ -489,6 +490,9 @@ namespace llvm { // Populate the Composite map from sub-register relationships. void computeComposites(); + // Compute a lane mask for each sub-register index. + void computeSubRegIndexLaneMasks(); + public: CodeGenRegBank(RecordKeeper&); diff --git a/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp index 8bfecead6d..0ad25a5428 100644 --- a/utils/TableGen/DFAPacketizerEmitter.cpp +++ b/utils/TableGen/DFAPacketizerEmitter.cpp @@ -17,6 +17,7 @@ #include "CodeGenTarget.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" #include <list> @@ -74,6 +75,8 @@ public: // Another way of thinking about this transition is we are mapping a NDFA with // two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10]. // +// A State instance also contains a collection of transitions from that state: +// a map from inputs to new states. // namespace { class State { @@ -82,10 +85,16 @@ class State { int stateNum; bool isInitial; std::set<unsigned> stateInfo; + typedef std::map<unsigned, State *> TransitionMap; + TransitionMap Transitions; State(); State(const State &S); + bool operator<(const State &s) const { + return stateNum < s.stateNum; + } + // // canAddInsnClass - Returns true if an instruction of type InsnClass is a // valid transition from this state, i.e., can an instruction of type InsnClass @@ -100,38 +109,18 @@ class State { // which are possible from this state (PossibleStates). // void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates); + // + // addTransition - Add a transition from this state given the input InsnClass + // + void addTransition(unsigned InsnClass, State *To); + // + // hasTransition - Returns true if there is a transition from this state + // given the input InsnClass + // + bool hasTransition(unsigned InsnClass); }; } // End anonymous namespace. - -namespace { -struct Transition { - public: - static int currentTransitionNum; - int transitionNum; - State *from; - unsigned input; - State *to; - - Transition(State *from_, unsigned input_, State *to_); -}; -} // End anonymous namespace. - - -// -// Comparators to keep set of states sorted. -// -namespace { -struct ltState { - bool operator()(const State *s1, const State *s2) const; -}; - -struct ltTransition { - bool operator()(const Transition *s1, const Transition *s2) const; -}; -} // End anonymous namespace. - - // // class DFA: deterministic finite automaton for processor resource tracking. // @@ -139,36 +128,19 @@ namespace { class DFA { public: DFA(); + ~DFA(); // Set of states. Need to keep this sorted to emit the transition table. - std::set<State*, ltState> states; + typedef std::set<State *, less_ptr<State> > StateSet; + StateSet states; - // Map from a state to the list of transitions with that state as source. - std::map<State*, std::set<Transition*, ltTransition>, ltState> - stateTransitions; State *currentState; - // Highest valued Input seen. - unsigned LargestInput; - // // Modify the DFA. // void initialize(); void addState(State *); - void addTransition(Transition *); - - // - // getTransition - Return the state when a transition is made from - // State From with Input I. If a transition is not found, return NULL. - // - State *getTransition(State *, unsigned); - - // - // isValidTransition: Predicate that checks if there is a valid transition - // from state From on input InsnClass. - // - bool isValidTransition(State *From, unsigned InsnClass); // // writeTable: Print out a table representing the DFA. @@ -179,7 +151,7 @@ public: // -// Constructors for State, Transition, and DFA +// Constructors and destructors for State and DFA // State::State() : stateNum(currentStateNum++), isInitial(false) {} @@ -189,22 +161,27 @@ State::State(const State &S) : stateNum(currentStateNum++), isInitial(S.isInitial), stateInfo(S.stateInfo) {} +DFA::DFA(): currentState(NULL) {} -Transition::Transition(State *from_, unsigned input_, State *to_) : - transitionNum(currentTransitionNum++), from(from_), input(input_), - to(to_) {} - - -DFA::DFA() : - LargestInput(0) {} - +DFA::~DFA() { + DeleteContainerPointers(states); +} -bool ltState::operator()(const State *s1, const State *s2) const { - return (s1->stateNum < s2->stateNum); +// +// addTransition - Add a transition from this state given the input InsnClass +// +void State::addTransition(unsigned InsnClass, State *To) { + assert(!Transitions.count(InsnClass) && + "Cannot have multiple transitions for the same input"); + Transitions[InsnClass] = To; } -bool ltTransition::operator()(const Transition *s1, const Transition *s2) const { - return (s1->input < s2->input); +// +// hasTransition - Returns true if there is a transition from this state +// given the input InsnClass +// +bool State::hasTransition(unsigned InsnClass) { + return Transitions.count(InsnClass) > 0; } // @@ -272,6 +249,7 @@ bool State::canAddInsnClass(unsigned InsnClass) const { void DFA::initialize() { + assert(currentState && "Missing current state"); currentState->isInitial = true; } @@ -282,47 +260,7 @@ void DFA::addState(State *S) { } -void DFA::addTransition(Transition *T) { - // Update LargestInput. - if (T->input > LargestInput) - LargestInput = T->input; - - // Add the new transition. - bool Added = stateTransitions[T->from].insert(T).second; - assert(Added && "Cannot have multiple states for the same input"); - (void)Added; -} - - -// -// getTransition - Return the state when a transition is made from -// State From with Input I. If a transition is not found, return NULL. -// -State *DFA::getTransition(State *From, unsigned I) { - // Do we have a transition from state From? - if (!stateTransitions.count(From)) - return NULL; - - // Do we have a transition from state From with Input I? - Transition TVal(NULL, I, NULL); - // Do not count this temporal instance - Transition::currentTransitionNum--; - std::set<Transition*, ltTransition>::iterator T = - stateTransitions[From].find(&TVal); - if (T != stateTransitions[From].end()) - return (*T)->to; - - return NULL; -} - - -bool DFA::isValidTransition(State *From, unsigned InsnClass) { - return (getTransition(From, InsnClass) != NULL); -} - - int State::currentStateNum = 0; -int Transition::currentTransitionNum = 0; DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): TargetName(CodeGenTarget(R).getName()), @@ -341,7 +279,7 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R): // // void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { - std::set<State*, ltState>::iterator SI = states.begin(); + DFA::StateSet::iterator SI = states.begin(); // This table provides a map to the beginning of the transitions for State s // in DFAStateInputTable. std::vector<int> StateEntry(states.size()); @@ -353,18 +291,16 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) { // to construct the StateEntry table. int ValidTransitions = 0; for (unsigned i = 0; i < states.size(); ++i, ++SI) { + assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); StateEntry[i] = ValidTransitions; - for (unsigned j = 0; j <= LargestInput; ++j) { - assert (((*SI)->stateNum == (int) i) && "Mismatch in state numbers"); - State *To = getTransition(*SI, j); - if (To == NULL) - continue; - - OS << "{" << j << ", " - << To->stateNum + for (State::TransitionMap::iterator + II = (*SI)->Transitions.begin(), IE = (*SI)->Transitions.end(); + II != IE; ++II) { + OS << "{" << II->first << ", " + << II->second->stateNum << "}, "; - ++ValidTransitions; } + ValidTransitions += (*SI)->Transitions.size(); // If there are no valid transitions from this stage, we need a sentinel // transition. @@ -539,7 +475,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { // If we haven't already created a transition for this input // and the state can accommodate this InsnClass, create a transition. // - if (!D.getTransition(current, InsnClass) && + if (!current->hasTransition(InsnClass) && current->canAddInsnClass(InsnClass)) { State *NewState = NULL; current->AddInsnClass(InsnClass, NewStateResources); @@ -559,10 +495,8 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) { Visited[NewStateResources] = NewState; WorkList.push_back(NewState); } - - Transition *NewTransition = new Transition(current, InsnClass, - NewState); - D.addTransition(NewTransition); + + current->addTransition(InsnClass, NewState); } } } diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp index 02546dfca7..42b213c04a 100644 --- a/utils/TableGen/RegisterInfoEmitter.cpp +++ b/utils/TableGen/RegisterInfoEmitter.cpp @@ -770,7 +770,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target, << TargetName << "RegDiffLists, " << TargetName << "RegStrings, " << TargetName << "SubRegIdxLists, " - << SubRegIndices.size() << ",\n" + << (SubRegIndices.size() + 1) << ",\n" << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, false); @@ -876,15 +876,23 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, VTSeqs.emit(OS, printSimpleValueType, "MVT::Other"); OS << "};\n"; - // Emit SubRegIndex names, skipping 0 - OS << "\nstatic const char *const SubRegIndexTable[] = { \""; + // Emit SubRegIndex names, skipping 0. + OS << "\nstatic const char *const SubRegIndexNameTable[] = { \""; for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { OS << SubRegIndices[i]->getName(); - if (i+1 != e) + if (i + 1 != e) OS << "\", \""; } OS << "\" };\n\n"; + // Emit SubRegIndex lane masks, including 0. + OS << "\nstatic const unsigned SubRegIndexLaneMaskTable[] = {\n ~0u,\n"; + for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { + OS << format(" 0x%08x, // ", SubRegIndices[i]->LaneMask) + << SubRegIndices[i]->getName() << '\n'; + } + OS << " };\n\n"; + OS << "\n"; // Now that all of the structs have been emitted, emit the instances. @@ -1055,8 +1063,8 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, for (unsigned i = 0, e = SubRegIndices.size(); i != e; ++i) { bool Open = false; for (unsigned j = 0; j != e; ++j) { - if (CodeGenSubRegIndex *Comp = - SubRegIndices[i]->compose(SubRegIndices[j])) { + CodeGenSubRegIndex *Comp = SubRegIndices[i]->compose(SubRegIndices[j]); + if (Comp && Comp != SubRegIndices[j]) { if (!Open) { OS << " case " << SubRegIndices[i]->getQualifiedName() << ": switch(IdxB) {\n default: return IdxB;\n"; @@ -1122,7 +1130,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour)\n" << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc" << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n" - << " SubRegIndexTable) {\n" + << " SubRegIndexNameTable, SubRegIndexLaneMaskTable) {\n" << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size()+1 << ", RA,\n " << TargetName << "MCRegisterClasses, " << RegisterClasses.size() << ",\n" @@ -1131,7 +1139,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target, << " " << TargetName << "RegDiffLists,\n" << " " << TargetName << "RegStrings,\n" << " " << TargetName << "SubRegIdxLists,\n" - << " " << SubRegIndices.size() << ",\n" + << " " << SubRegIndices.size() + 1 << ",\n" << " " << TargetName << "RegEncodingTable);\n\n"; EmitRegMapping(OS, Regs, true); diff --git a/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp index f3bd373708..8526621599 100644 --- a/utils/TableGen/X86DisassemblerTables.cpp +++ b/utils/TableGen/X86DisassemblerTables.cpp @@ -366,6 +366,10 @@ void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2, break; } + // We assume that the index can fit into uint16_t. + assert(sEntryNumber < 65536U && + "Index into ModRMDecision is too large for uint16_t!"); + ++sTableNumber; } |