<p dir="ltr"><br>
2015/11/22 5:03 "Krzysztof Parzyszek via llvm-commits" <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>>:<br>
><br>
> Author: kparzysz<br>
> Date: Sat Nov 21 14:00:45 2015<br>
> New Revision: 253793<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=253793&view=rev">http://llvm.org/viewvc/llvm-project?rev=253793&view=rev</a><br>
> Log:<br>
> Hexagon V60/HVX DFA scheduler support<br>
><br>
> Extended DFA tablegen to:<br>
> - added "-debug-only dfa-emitter" support to llvm-tblgen<br>
><br>
> - defined CVI_PIPE* resources for the V60 vector coprocessor<br>
><br>
> - allow specification of multiple required resources<br>
> - supports ANDs of ORs<br>
> - e.g. [SLOT2, SLOT3], [CVI_MPY0, CVI_MPY1] means:<br>
> (SLOT2 OR SLOT3) AND (CVI_MPY0 OR CVI_MPY1)<br>
><br>
> - added support for combo resources<br>
> - allows specifying ORs of ANDs<br>
> - e.g. [CVI_XLSHF, CVI_MPY01] means:<br>
> (CVI_XLANE AND CVI_SHIFT) OR (CVI_MPY0 AND CVI_MPY1)<br>
><br>
> - increased DFA input size from 32-bit to 64-bit<br>
> - allows for a maximum of 4 AND'ed terms of 16 resources<br>
><br>
> - supported expressions now include:<br>
><br>
> expression => term [AND term] [AND term] [AND term]<br>
> term => resource [OR resource]*<br>
> resource => one_resource | combo_resource<br>
> combo_resource => (one_resource [AND one_resource]*)<br>
><br>
> Author: Dan Palermo <<a href="mailto:dpalermo@codeaurora.org">dpalermo@codeaurora.org</a>><br>
><br>
> kparzysz: Verified AMDGPU codegen to be unchanged on all llc<br>
> tests, except those dealing with instruction encodings.<br>
><br>
> Reapply the previous patch, this time without circular dependencies.<br>
><br>
><br>
> Added:<br>
> llvm/trunk/include/llvm/CodeGen/DFAPacketizerDefs.h<br>
> Modified:<br>
> llvm/trunk/include/llvm/CodeGen/DFAPacketizer.h<br>
> llvm/trunk/include/llvm/Target/TargetItinerary.td<br>
> llvm/trunk/lib/CodeGen/DFAPacketizer.cpp<br>
> llvm/trunk/lib/Target/Hexagon/HexagonScheduleV60.td<br>
> llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp<br>
><br>
> Modified: llvm/trunk/include/llvm/CodeGen/DFAPacketizer.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DFAPacketizer.h?rev=253793&r1=253792&r2=253793&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DFAPacketizer.h?rev=253793&r1=253792&r2=253793&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/CodeGen/DFAPacketizer.h (original)<br>
> +++ llvm/trunk/include/llvm/CodeGen/DFAPacketizer.h Sat Nov 21 14:00:45 2015<br>
> @@ -27,6 +27,7 @@<br>
> #define LLVM_CODEGEN_DFAPACKETIZER_H<br>
><br>
> #include "llvm/ADT/DenseMap.h"<br>
> +#include "llvm/CodeGen/DFAPacketizerDefs.h"<br>
> #include "llvm/CodeGen/MachineBasicBlock.h"<br>
> #include <map><br>
><br>
> @@ -42,20 +43,21 @@ class SUnit;<br>
><br>
> class DFAPacketizer {<br>
> private:<br>
> - typedef std::pair<unsigned, unsigned> UnsignPair;<br>
> + typedef std::pair<unsigned, DFAInput> UnsignPair;<br>
> +<br>
> const InstrItineraryData *InstrItins;<br>
> int CurrentState;<br>
> - const int (*DFAStateInputTable)[2];<br>
> + const DFAStateInput (*DFAStateInputTable)[2];<br>
> const unsigned *DFAStateEntryTable;<br>
><br>
> // CachedTable is a map from <FromState, Input> to ToState.<br>
> DenseMap<UnsignPair, unsigned> CachedTable;<br>
><br>
> // ReadTable - Read the DFA transition table and update CachedTable.<br>
> - void ReadTable(unsigned int state);<br>
> + void ReadTable(unsigned state);<br>
><br>
> public:<br>
> - DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2],<br>
> + DFAPacketizer(const InstrItineraryData *I, const DFAStateInput (*SIT)[2],<br>
> const unsigned *SET);<br>
><br>
> // Reset the current state to make all resources available.<br>
> @@ -63,6 +65,14 @@ public:<br>
> CurrentState = 0;<br>
> }<br>
><br>
> + // getInsnInput - Return the DFAInput for an instruction class.<br>
> + DFAInput getInsnInput(unsigned InsnClass);<br>
> +<br>
> + // getInsnInput - Return the DFAInput for an instruction class input vector.<br>
> + static DFAInput getInsnInput(const std::vector<unsigned> &InsnClass) {<br>
> + return getDFAInsnInput(InsnClass);<br>
> + }<br>
> +<br>
> // canReserveResources - Check if the resources occupied by a MCInstrDesc<br>
> // are available in the current state.<br>
> bool canReserveResources(const llvm::MCInstrDesc *MID);<br>
><br>
> Added: llvm/trunk/include/llvm/CodeGen/DFAPacketizerDefs.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DFAPacketizerDefs.h?rev=253793&view=auto">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/DFAPacketizerDefs.h?rev=253793&view=auto</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/CodeGen/DFAPacketizerDefs.h (added)<br>
> +++ llvm/trunk/include/llvm/CodeGen/DFAPacketizerDefs.h Sat Nov 21 14:00:45 2015<br>
> @@ -0,0 +1,63 @@<br>
> +//=- llvm/CodeGen/DFAPacketizerDefs.h - DFA Packetizer for VLIW ---*- C++ -*-=//<br>
> +//<br>
> +// The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +// Common definitions used by TableGen and the DFAPacketizer in CodeGen.<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_CODEGEN_DFAPACKETIZERDEFS_H<br>
> +#define LLVM_CODEGEN_DFAPACKETIZERDEFS_H<br>
> +<br>
> +#include <vector><br>
> +<br>
> +namespace llvm {<br>
> +<br>
> +// DFA_MAX_RESTERMS * DFA_MAX_RESOURCES must fit within sizeof DFAInput.<br>
> +// This is verified in DFAPacketizer.cpp:DFAPacketizer::DFAPacketizer.<br>
> +//<br>
> +// e.g. terms x resource bit combinations that fit in uint32_t:<br>
> +// 4 terms x 8 bits = 32 bits<br>
> +// 3 terms x 10 bits = 30 bits<br>
> +// 2 terms x 16 bits = 32 bits<br>
> +//<br>
> +// e.g. terms x resource bit combinations that fit in uint64_t:<br>
> +// 8 terms x 8 bits = 64 bits<br>
> +// 7 terms x 9 bits = 63 bits<br>
> +// 6 terms x 10 bits = 60 bits<br>
> +// 5 terms x 12 bits = 60 bits<br>
> +// 4 terms x 16 bits = 64 bits <--- current<br>
> +// 3 terms x 21 bits = 63 bits<br>
> +// 2 terms x 32 bits = 64 bits<br>
> +//<br>
> +#define DFA_MAX_RESTERMS 4 // The max # of AND'ed resource terms.<br>
> +#define DFA_MAX_RESOURCES 16 // The max # of resource bits in one term.<br>
> +<br>
> +typedef uint64_t DFAInput;<br>
> +typedef int64_t DFAStateInput;<br>
> +#define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable.<br>
> +<br>
> +namespace {<br>
> + DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {<br>
> + return (Inp << DFA_MAX_RESOURCES) | FuncUnits;<br>
> + }<br>
> +<br>
> + /// Return the DFAInput for an instruction class input vector.<br>
> + /// This function is used in both DFAPacketizer.cpp and in<br>
> + /// DFAPacketizerEmitter.cpp.<br>
> + DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {<br>
> + DFAInput InsnInput = 0;<br>
> + assert ((InsnClass.size() <= DFA_MAX_RESTERMS) &&<br>
> + "Exceeded maximum number of DFA terms");<br>
> + for (auto U : InsnClass)<br>
> + InsnInput = addDFAFuncUnits(InsnInput, U);<br>
> + return InsnInput;<br>
> + }<br>
> +}<br>
> +<br>
> +}<br>
> +<br>
> +#endif<br>
><br>
> Modified: llvm/trunk/include/llvm/Target/TargetItinerary.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetItinerary.td?rev=253793&r1=253792&r2=253793&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetItinerary.td?rev=253793&r1=253792&r2=253793&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/include/llvm/Target/TargetItinerary.td (original)<br>
> +++ llvm/trunk/include/llvm/Target/TargetItinerary.td Sat Nov 21 14:00:45 2015<br>
> @@ -134,3 +134,19 @@ class ProcessorItineraries<list<FuncUnit<br>
> // info. Subtargets using NoItineraries can bypass the scheduler's<br>
> // expensive HazardRecognizer because no reservation table is needed.<br>
> def NoItineraries : ProcessorItineraries<[], [], []>;<br>
> +<br>
> +//===----------------------------------------------------------------------===//<br>
> +// Combo Function Unit data - This is a map of combo function unit names to<br>
> +// the list of functional units that are included in the combination.<br>
> +//<br>
> +class ComboFuncData<FuncUnit ComboFunc, list<FuncUnit> funclist> {<br>
> + FuncUnit TheComboFunc = ComboFunc;<br>
> + list<FuncUnit> FuncList = funclist;<br>
> +}<br>
> +<br>
> +//===----------------------------------------------------------------------===//<br>
> +// Combo Function Units - This is a list of all combo function unit data.<br>
> +class ComboFuncUnits<list<ComboFuncData> cfd> {<br>
> + list<ComboFuncData> CFD = cfd;<br>
> +}<br>
> +<br>
><br>
> Modified: llvm/trunk/lib/CodeGen/DFAPacketizer.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/DFAPacketizer.cpp?rev=253793&r1=253792&r2=253793&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/DFAPacketizer.cpp?rev=253793&r1=253792&r2=253793&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/CodeGen/DFAPacketizer.cpp (original)<br>
> +++ llvm/trunk/lib/CodeGen/DFAPacketizer.cpp Sat Nov 21 14:00:45 2015<br>
> @@ -31,10 +31,17 @@<br>
> #include "llvm/Target/TargetInstrInfo.h"<br>
> using namespace llvm;<br>
><br>
> -DFAPacketizer::DFAPacketizer(const InstrItineraryData *I, const int (*SIT)[2],<br>
> +DFAPacketizer::DFAPacketizer(const InstrItineraryData *I,<br>
> + const DFAStateInput (*SIT)[2],<br>
> const unsigned *SET):<br>
> InstrItins(I), CurrentState(0), DFAStateInputTable(SIT),<br>
> - DFAStateEntryTable(SET) {}<br>
> + DFAStateEntryTable(SET) {<br>
> + // Make sure DFA types are large enough for the number of terms & resources.<br>
> + assert((DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) <= (8 * sizeof(DFAInput))<br>
> + && "(DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) too big for DFAInput");<br>
> + assert((DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) <= (8 * sizeof(DFAStateInput))<br>
> + && "(DFA_MAX_RESTERMS * DFA_MAX_RESOURCES) too big for DFAStateInput");<br>
> +}<br>
><br>
><br>
> //<br>
> @@ -60,26 +67,37 @@ void DFAPacketizer::ReadTable(unsigned i<br>
> DFAStateInputTable[i][1];<br>
> }<br>
><br>
> +//<br>
> +// getInsnInput - Return the DFAInput for an instruction class.<br>
> +//<br>
> +DFAInput DFAPacketizer::getInsnInput(unsigned InsnClass) {<br>
> + // Note: this logic must match that in DFAPacketizerDefs.h for input vectors.<br>
> + DFAInput InsnInput = 0;<br>
> + unsigned i = 0;<br>
> + for (const InstrStage *IS = InstrItins->beginStage(InsnClass),<br>
> + *IE = InstrItins->endStage(InsnClass); IS != IE; ++IS, ++i) {<br>
> + InsnInput = addDFAFuncUnits(InsnInput, IS->getUnits());<br>
> + assert ((i < DFA_MAX_RESTERMS) && "Exceeded maximum number of DFA inputs");<br>
> + }<br>
> + return InsnInput;<br>
> +}<br>
><br>
> // canReserveResources - Check if the resources occupied by a MCInstrDesc<br>
> // are available in the current state.<br>
> bool DFAPacketizer::canReserveResources(const llvm::MCInstrDesc *MID) {<br>
> unsigned InsnClass = MID->getSchedClass();<br>
> - const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);<br>
> - unsigned FuncUnits = IS->getUnits();<br>
> - UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits);<br>
> + DFAInput InsnInput = getInsnInput(InsnClass);<br>
> + UnsignPair StateTrans = UnsignPair(CurrentState, InsnInput);<br>
> ReadTable(CurrentState);<br>
> return (CachedTable.count(StateTrans) != 0);<br>
> }<br>
><br>
> -<br>
> // reserveResources - Reserve the resources occupied by a MCInstrDesc and<br>
> // change the current state to reflect that change.<br>
> void DFAPacketizer::reserveResources(const llvm::MCInstrDesc *MID) {<br>
> unsigned InsnClass = MID->getSchedClass();<br>
> - const llvm::InstrStage *IS = InstrItins->beginStage(InsnClass);<br>
> - unsigned FuncUnits = IS->getUnits();<br>
> - UnsignPair StateTrans = UnsignPair(CurrentState, FuncUnits);<br>
> + DFAInput InsnInput = getInsnInput(InsnClass);<br>
> + UnsignPair StateTrans = UnsignPair(CurrentState, InsnInput);<br>
> ReadTable(CurrentState);<br>
> assert(CachedTable.count(StateTrans) != 0);<br>
> CurrentState = CachedTable[StateTrans];<br>
><br>
> Modified: llvm/trunk/lib/Target/Hexagon/HexagonScheduleV60.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonScheduleV60.td?rev=253793&r1=253792&r2=253793&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonScheduleV60.td?rev=253793&r1=253792&r2=253793&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/lib/Target/Hexagon/HexagonScheduleV60.td (original)<br>
> +++ llvm/trunk/lib/Target/Hexagon/HexagonScheduleV60.td Sat Nov 21 14:00:45 2015<br>
> @@ -20,6 +20,15 @@ def CVI_XLSHF : FuncUnit;<br>
> def CVI_MPY01 : FuncUnit;<br>
> def CVI_ALL : FuncUnit;<br>
><br>
> +// Combined functional unit data.<br>
> +def HexagonComboFuncsV60 :<br>
> + ComboFuncUnits<[<br>
> + ComboFuncData<CVI_XLSHF , [CVI_XLANE, CVI_SHIFT]>,<br>
> + ComboFuncData<CVI_MPY01 , [CVI_MPY0, CVI_MPY1]>,<br>
> + ComboFuncData<CVI_ALL , [CVI_ST, CVI_XLANE, CVI_SHIFT,<br>
> + CVI_MPY0, CVI_MPY1, CVI_LD]><br>
> + ]>;<br>
> +<br>
> // Note: When adding additional vector scheduling classes, add the<br>
> // corresponding methods to the class HexagonInstrInfo.<br>
> def CVI_VA : InstrItinClass;<br>
><br>
> Modified: llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp?rev=253793&r1=253792&r2=253793&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp?rev=253793&r1=253792&r2=253793&view=diff</a><br>
> ==============================================================================<br>
> --- llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp (original)<br>
> +++ llvm/trunk/utils/TableGen/DFAPacketizerEmitter.cpp Sat Nov 21 14:00:45 2015<br>
> @@ -15,16 +15,36 @@<br>
> //<br>
> //===----------------------------------------------------------------------===//<br>
><br>
> +#define DEBUG_TYPE "dfa-emitter"<br>
> +<br>
> #include "CodeGenTarget.h"<br>
> #include "llvm/ADT/DenseSet.h"<br>
> #include "llvm/ADT/STLExtras.h"<br>
> +#include "llvm/ADT/StringExtras.h"<br>
> +#include "llvm/CodeGen/DFAPacketizerDefs.h"</p>
<p dir="ltr">It violates layering.</p>
<p dir="ltr">> #include "llvm/TableGen/Record.h"<br>
> #include "llvm/TableGen/TableGenBackend.h"<br>
> +#include "llvm/Support/Debug.h"<br>
> #include <list><br>
> #include <map><br>
> #include <string><br>
> +#include <queue><br>
> using namespace llvm;<br>
><br>
> +// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".<br>
> +//<br>
> +// dbgsInsnClass - When debugging, print instruction class stages.<br>
> +//<br>
> +void dbgsInsnClass(const std::vector<unsigned> &InsnClass);<br>
> +//<br>
> +// dbgsStateInfo - When debugging, print the set of state info.<br>
> +//<br>
> +void dbgsStateInfo(const std::set<unsigned> &stateInfo);<br>
> +//<br>
> +// dbgsIndent - When debugging, indent by the specified amount.<br>
> +//<br>
> +void dbgsIndent(unsigned indent);<br>
> +<br>
> //<br>
> // class DFAPacketizerEmitter: class that generates and prints out the DFA<br>
> // for resource tracking.<br>
> @@ -37,20 +57,48 @@ private:<br>
> // allInsnClasses is the set of all possible resources consumed by an<br>
> // InstrStage.<br>
> //<br>
> - DenseSet<unsigned> allInsnClasses;<br>
> + std::vector<std::vector<unsigned>> allInsnClasses;<br>
> RecordKeeper &Records;<br>
><br>
> public:<br>
> DFAPacketizerEmitter(RecordKeeper &R);<br>
><br>
> //<br>
> - // collectAllInsnClasses: Populate allInsnClasses which is a set of units<br>
> + // collectAllFuncUnits - Construct a map of function unit names to bits.<br>
> + //<br>
> + int collectAllFuncUnits(std::vector<Record*> &ProcItinList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + int &maxResources,<br>
> + raw_ostream &OS);<br>
> +<br>
> + //<br>
> + // collectAllComboFuncs - Construct a map from a combo function unit bit to<br>
> + // the bits of all included functional units.<br>
> + //<br>
> + int collectAllComboFuncs(std::vector<Record*> &ComboFuncList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap,<br>
> + raw_ostream &OS);<br>
> +<br>
> + //<br>
> + // collectOneInsnClass - Populate allInsnClasses with one instruction class.<br>
> + //<br>
> + int collectOneInsnClass(const std::string &ProcName,<br>
> + std::vector<Record*> &ProcItinList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + Record *ItinData,<br>
> + raw_ostream &OS);<br>
> +<br>
> + //<br>
> + // collectAllInsnClasses - Populate allInsnClasses which is a set of units<br>
> // used in each stage.<br>
> //<br>
> - void collectAllInsnClasses(const std::string &Name,<br>
> - Record *ItinData,<br>
> - unsigned &NStages,<br>
> - raw_ostream &OS);<br>
> + int collectAllInsnClasses(const std::string &ProcName,<br>
> + std::vector<Record*> &ProcItinList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + std::vector<Record*> &ItinDataList,<br>
> + int &maxStages,<br>
> + raw_ostream &OS);<br>
><br>
> void run(raw_ostream &OS);<br>
> };<br>
> @@ -87,7 +135,7 @@ class State {<br>
> const int stateNum;<br>
> mutable bool isInitial;<br>
> mutable std::set<unsigned> stateInfo;<br>
> - typedef std::map<unsigned, const State *> TransitionMap;<br>
> + typedef std::map<std::vector<unsigned>, const State *> TransitionMap;<br>
> mutable TransitionMap Transitions;<br>
><br>
> State();<br>
> @@ -97,28 +145,47 @@ class State {<br>
> }<br>
><br>
> //<br>
> - // canAddInsnClass - Returns true if an instruction of type InsnClass is a<br>
> - // valid transition from this state, i.e., can an instruction of type InsnClass<br>
> - // be added to the packet represented by this state.<br>
> + // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass<br>
> + // may be a valid transition from this state i.e., can an instruction of type<br>
> + // InsnClass be added to the packet represented by this state.<br>
> + //<br>
> + // Note that for multiple stages, this quick check does not take into account<br>
> + // any possible resource competition between the stages themselves. That is<br>
> + // enforced in AddInsnClassStages which checks the cross product of all<br>
> + // stages for resource availability (which is a more involved check).<br>
> + //<br>
> + bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap) const;<br>
> + //<br>
> + // AddInsnClass - Return all combinations of resource reservation<br>
> + // which are possible from this state (PossibleStates).<br>
> //<br>
> // PossibleStates is the set of valid resource states that ensue from valid<br>
> // transitions.<br>
> //<br>
> - bool canAddInsnClass(unsigned InsnClass) const;<br>
> + void AddInsnClass(std::vector<unsigned> &InsnClass,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap,<br>
> + std::set<unsigned> &PossibleStates) const;<br>
> //<br>
> - // AddInsnClass - Return all combinations of resource reservation<br>
> + // AddInsnClassStages - Return all combinations of resource reservation<br>
> + // resulting from the cross product of all stages for this InsnClass<br>
> // which are possible from this state (PossibleStates).<br>
> //<br>
> - void AddInsnClass(unsigned InsnClass, std::set<unsigned> &PossibleStates) const;<br>
> - //<br>
> + void AddInsnClassStages(std::vector<unsigned> &InsnClass,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap,<br>
> + unsigned chkstage, unsigned numstages,<br>
> + unsigned prevState, unsigned origState,<br>
> + DenseSet<unsigned> &VisitedResourceStates,<br>
> + std::set<unsigned> &PossibleStates) const;<br>
> + //<br>
> // addTransition - Add a transition from this state given the input InsnClass<br>
> //<br>
> - void addTransition(unsigned InsnClass, const State *To) const;<br>
> + void addTransition(std::vector<unsigned> InsnClass, const State *To) const;<br>
> //<br>
> // hasTransition - Returns true if there is a transition from this state<br>
> // given the input InsnClass<br>
> //<br>
> - bool hasTransition(unsigned InsnClass) const;<br>
> + bool hasTransition(std::vector<unsigned> InsnClass) const;<br>
> };<br>
> } // End anonymous namespace.<br>
><br>
> @@ -144,10 +211,52 @@ public:<br>
> //<br>
> // writeTable: Print out a table representing the DFA.<br>
> //<br>
> - void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName);<br>
> + void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName,<br>
> + int numInsnClasses = 0,<br>
> + int maxResources = 0, int numCombos = 0, int maxStages = 0);<br>
> };<br>
> } // End anonymous namespace.<br>
><br>
> +// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".<br>
> +//<br>
> +// dbgsInsnClass - When debugging, print instruction class stages.<br>
> +//<br>
> +void dbgsInsnClass(const std::vector<unsigned> &InsnClass) {<br>
> + DEBUG(dbgs() << "InsnClass: ");<br>
> + for (unsigned i = 0; i < InsnClass.size(); ++i) {<br>
> + if (i > 0) {<br>
> + DEBUG(dbgs() << ", ");<br>
> + }<br>
> + DEBUG(dbgs() << "0x" << utohexstr(InsnClass[i]));<br>
> + }<br>
> + DFAInput InsnInput = getDFAInsnInput(InsnClass);<br>
> + DEBUG(dbgs() << " (input: 0x" << utohexstr(InsnInput) << ")");<br>
> +}<br>
> +<br>
> +//<br>
> +// dbgsStateInfo - When debugging, print the set of state info.<br>
> +//<br>
> +void dbgsStateInfo(const std::set<unsigned> &stateInfo) {<br>
> + DEBUG(dbgs() << "StateInfo: ");<br>
> + unsigned i = 0;<br>
> + for (std::set<unsigned>::iterator SI = stateInfo.begin();<br>
> + SI != stateInfo.end(); ++SI, ++i) {<br>
> + unsigned thisState = *SI;<br>
> + if (i > 0) {<br>
> + DEBUG(dbgs() << ", ");<br>
> + }<br>
> + DEBUG(dbgs() << "0x" << utohexstr(thisState));<br>
> + }<br>
> +}<br>
> +<br>
> +//<br>
> +// dbgsIndent - When debugging, indent by the specified amount.<br>
> +//<br>
> +void dbgsIndent(unsigned indent) {<br>
> + for (unsigned i = 0; i < indent; ++i) {<br>
> + DEBUG(dbgs() << " ");<br>
> + }<br>
> +}<br>
><br>
> //<br>
> // Constructors and destructors for State and DFA<br>
> @@ -157,10 +266,11 @@ State::State() :<br>
><br>
> DFA::DFA(): currentState(nullptr) {}<br>
><br>
> -//<br>
> +//<br>
> // addTransition - Add a transition from this state given the input InsnClass<br>
> //<br>
> -void State::addTransition(unsigned InsnClass, const State *To) const {<br>
> +void State::addTransition(std::vector<unsigned> InsnClass, const State *To)<br>
> + const {<br>
> assert(!Transitions.count(InsnClass) &&<br>
> "Cannot have multiple transitions for the same input");<br>
> Transitions[InsnClass] = To;<br>
> @@ -170,7 +280,7 @@ void State::addTransition(unsigned InsnC<br>
> // hasTransition - Returns true if there is a transition from this state<br>
> // given the input InsnClass<br>
> //<br>
> -bool State::hasTransition(unsigned InsnClass) const {<br>
> +bool State::hasTransition(std::vector<unsigned> InsnClass) const {<br>
> return Transitions.count(InsnClass) > 0;<br>
> }<br>
><br>
> @@ -178,61 +288,167 @@ bool State::hasTransition(unsigned InsnC<br>
> // AddInsnClass - Return all combinations of resource reservation<br>
> // which are possible from this state (PossibleStates).<br>
> //<br>
> -void State::AddInsnClass(unsigned InsnClass,<br>
> - std::set<unsigned> &PossibleStates) const {<br>
> +// PossibleStates is the set of valid resource states that ensue from valid<br>
> +// transitions.<br>
> +//<br>
> +void State::AddInsnClass(std::vector<unsigned> &InsnClass,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap,<br>
> + std::set<unsigned> &PossibleStates) const {<br>
> //<br>
> // Iterate over all resource states in currentState.<br>
> //<br>
> + unsigned numstages = InsnClass.size();<br>
> + assert((numstages > 0) && "InsnClass has no stages");<br>
><br>
> for (std::set<unsigned>::iterator SI = stateInfo.begin();<br>
> SI != stateInfo.end(); ++SI) {<br>
> unsigned thisState = *SI;<br>
><br>
> - //<br>
> - // Iterate over all possible resources used in InsnClass.<br>
> - // For ex: for InsnClass = 0x11, all resources = {0x01, 0x10}.<br>
> - //<br>
> -<br>
> DenseSet<unsigned> VisitedResourceStates;<br>
> - for (unsigned int j = 0; j < sizeof(InsnClass) * 8; ++j) {<br>
> - if ((0x1 << j) & InsnClass) {<br>
> - //<br>
> - // For each possible resource used in InsnClass, generate the<br>
> - // resource state if that resource was used.<br>
> - //<br>
> - unsigned ResultingResourceState = thisState | (0x1 << j);<br>
> +<br>
> + DEBUG(dbgs() << " thisState: 0x" << utohexstr(thisState) << "\n");<br>
> + AddInsnClassStages(InsnClass, ComboBitToBitsMap,<br>
> + numstages - 1, numstages,<br>
> + thisState, thisState,<br>
> + VisitedResourceStates, PossibleStates);<br>
> + }<br>
> +}<br>
> +<br>
> +void State::AddInsnClassStages(std::vector<unsigned> &InsnClass,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap,<br>
> + unsigned chkstage, unsigned numstages,<br>
> + unsigned prevState, unsigned origState,<br>
> + DenseSet<unsigned> &VisitedResourceStates,<br>
> + std::set<unsigned> &PossibleStates) const {<br>
> +<br>
> + assert((chkstage < numstages) && "AddInsnClassStages: stage out of range");<br>
> + unsigned thisStage = InsnClass[chkstage];<br>
> +<br>
> + dbgsIndent((1 + numstages - chkstage) << 1);<br>
> + DEBUG(dbgs() << "AddInsnClassStages " << chkstage<br>
> + << " (0x" << utohexstr(thisStage) << ") from ");<br>
> + dbgsInsnClass(InsnClass);<br>
> + DEBUG(dbgs() << "\n");<br>
> +<br>
> + //<br>
> + // Iterate over all possible resources used in thisStage.<br>
> + // For ex: for thisStage = 0x11, all resources = {0x01, 0x10}.<br>
> + //<br>
> + for (unsigned int j = 0; j < DFA_MAX_RESOURCES; ++j) {<br>
> + unsigned resourceMask = (0x1 << j);<br>
> + if (resourceMask & thisStage) {<br>
> + unsigned combo = ComboBitToBitsMap[resourceMask];<br>
> + if (combo && ((~prevState & combo) != combo)) {<br>
> + DEBUG(dbgs() << "\tSkipped Add 0x" << utohexstr(prevState)<br>
> + << " - combo op 0x" << utohexstr(resourceMask)<br>
> + << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");<br>
> + continue;<br>
> + }<br>
> + //<br>
> + // For each possible resource used in thisStage, generate the<br>
> + // resource state if that resource was used.<br>
> + //<br>
> + unsigned ResultingResourceState = prevState | resourceMask | combo;<br>
> + dbgsIndent((2 + numstages - chkstage) << 1);<br>
> + DEBUG(dbgs() << "0x" << utohexstr(prevState)<br>
> + << " | 0x" << utohexstr(resourceMask));<br>
> + if (combo) {<br>
> + DEBUG(dbgs() << " | 0x" << utohexstr(combo));<br>
> + }<br>
> + DEBUG(dbgs() << " = 0x" << utohexstr(ResultingResourceState) << " ");<br>
> +<br>
> + //<br>
> + // If this is the final stage for this class<br>
> + //<br>
> + if (chkstage == 0) {<br>
> //<br>
> // Check if the resulting resource state can be accommodated in this<br>
> // packet.<br>
> - // We compute ResultingResourceState OR thisState.<br>
> - // If the result of the OR is different than thisState, it implies<br>
> + // We compute resource OR prevState (originally started as origState).<br>
> + // If the result of the OR is different than origState, it implies<br>
> // that there is at least one resource that can be used to schedule<br>
> - // InsnClass in the current packet.<br>
> + // thisStage in the current packet.<br>
> // Insert ResultingResourceState into PossibleStates only if we haven't<br>
> // processed ResultingResourceState before.<br>
> //<br>
> - if ((ResultingResourceState != thisState) &&<br>
> - (VisitedResourceStates.count(ResultingResourceState) == 0)) {<br>
> - VisitedResourceStates.insert(ResultingResourceState);<br>
> - PossibleStates.insert(ResultingResourceState);<br>
> + if (ResultingResourceState != prevState) {<br>
> + if (VisitedResourceStates.count(ResultingResourceState) == 0) {<br>
> + VisitedResourceStates.insert(ResultingResourceState);<br>
> + PossibleStates.insert(ResultingResourceState);<br>
> + DEBUG(dbgs() << "\tResultingResourceState: 0x"<br>
> + << utohexstr(ResultingResourceState) << "\n");<br>
> + } else {<br>
> + DEBUG(dbgs() << "\tSkipped Add - state already seen\n");<br>
> + }<br>
> + } else {<br>
> + DEBUG(dbgs() << "\tSkipped Add - no final resources available\n");<br>
> + }<br>
> + } else {<br>
> + //<br>
> + // If the current resource can be accommodated, check the next<br>
> + // stage in InsnClass for available resources.<br>
> + //<br>
> + if (ResultingResourceState != prevState) {<br>
> + DEBUG(dbgs() << "\n");<br>
> + AddInsnClassStages(InsnClass, ComboBitToBitsMap,<br>
> + chkstage - 1, numstages,<br>
> + ResultingResourceState, origState,<br>
> + VisitedResourceStates, PossibleStates);<br>
> + } else {<br>
> + DEBUG(dbgs() << "\tSkipped Add - no resources available\n");<br>
> }<br>
> }<br>
> }<br>
> }<br>
> -<br>
> }<br>
><br>
><br>
> //<br>
> -// canAddInsnClass - Quickly verifies if an instruction of type InsnClass is a<br>
> -// valid transition from this state i.e., can an instruction of type InsnClass<br>
> -// be added to the packet represented by this state.<br>
> +// canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass<br>
> +// may be a valid transition from this state i.e., can an instruction of type<br>
> +// InsnClass be added to the packet represented by this state.<br>
> +//<br>
> +// Note that this routine is performing conservative checks that can be<br>
> +// quickly executed acting as a filter before calling AddInsnClassStages.<br>
> +// Any cases allowed through here will be caught later in AddInsnClassStages<br>
> +// which performs the more expensive exact check.<br>
> //<br>
> -bool State::canAddInsnClass(unsigned InsnClass) const {<br>
> +bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap) const {<br>
> for (std::set<unsigned>::const_iterator SI = stateInfo.begin();<br>
> SI != stateInfo.end(); ++SI) {<br>
> - if (~*SI & InsnClass)<br>
> +<br>
> + // Check to see if all required resources are available.<br>
> + bool available = true;<br>
> +<br>
> + // Inspect each stage independently.<br>
> + // note: This is a conservative check as we aren't checking for<br>
> + // possible resource competition between the stages themselves<br>
> + // The full cross product is examined later in AddInsnClass.<br>
> + for (unsigned i = 0; i < InsnClass.size(); ++i) {<br>
> + unsigned resources = *SI;<br>
> + if ((~resources & InsnClass[i]) == 0) {<br>
> + available = false;<br>
> + break;<br>
> + }<br>
> + // Make sure _all_ resources for a combo function are available.<br>
> + // note: This is a quick conservative check as it won't catch an<br>
> + // unscheduleable combo if this stage is an OR expression<br>
> + // containing a combo.<br>
> + // These cases are caught later in AddInsnClass.<br>
> + unsigned combo = ComboBitToBitsMap[InsnClass[i]];<br>
> + if (combo && ((~resources & combo) != combo)) {<br>
> + DEBUG(dbgs() << "\tSkipped canMaybeAdd 0x" << utohexstr(resources)<br>
> + << " - combo op 0x" << utohexstr(InsnClass[i])<br>
> + << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");<br>
> + available = false;<br>
> + break;<br>
> + }<br>
> + }<br>
> +<br>
> + if (available) {<br>
> return true;<br>
> + }<br>
> }<br>
> return false;<br>
> }<br>
> @@ -244,7 +460,6 @@ const State &DFA::newState() {<br>
> return *IterPair.first;<br>
> }<br>
><br>
> -<br>
> int State::currentStateNum = 0;<br>
><br>
> DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):<br>
> @@ -263,57 +478,100 @@ DFAPacketizerEmitter::DFAPacketizerEmitt<br>
> // the ith state.<br>
> //<br>
> //<br>
> -void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName) {<br>
> - static const std::string SentinelEntry = "{-1, -1}";<br>
> - DFA::StateSet::iterator SI = states.begin();<br>
> +void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,<br>
> + int numInsnClasses,<br>
> + int maxResources, int numCombos, int maxStages) {<br>
> +<br>
> + unsigned numStates = states.size();<br>
> +<br>
> + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");<br>
> + DEBUG(dbgs() << "writeTableAndAPI\n");<br>
> + DEBUG(dbgs() << "Total states: " << numStates << "\n");<br>
> +<br>
> + OS << "namespace llvm {\n";<br>
> +<br>
> + OS << "\n// Input format:\n";<br>
> + OS << "#define DFA_MAX_RESTERMS " << DFA_MAX_RESTERMS<br>
> + << "\t// maximum AND'ed resource terms\n";<br>
> + OS << "#define DFA_MAX_RESOURCES " << DFA_MAX_RESOURCES<br>
> + << "\t// maximum resource bits in one term\n";<br>
> +<br>
> + OS << "\n// " << TargetName << "DFAStateInputTable[][2] = "<br>
> + << "pairs of <Input, NextState> for all valid\n";<br>
> + OS << "// transitions.\n";<br>
> + OS << "// " << numStates << "\tstates\n";<br>
> + OS << "// " << numInsnClasses << "\tinstruction classes\n";<br>
> + OS << "// " << maxResources << "\tresources max\n";<br>
> + OS << "// " << numCombos << "\tcombo resources\n";<br>
> + OS << "// " << maxStages << "\tstages max\n";<br>
> + OS << "const " << DFA_TBLTYPE << " "<br>
> + << TargetName << "DFAStateInputTable[][2] = {\n";<br>
> +<br>
> // This table provides a map to the beginning of the transitions for State s<br>
> // in DFAStateInputTable.<br>
> - std::vector<int> StateEntry(states.size());<br>
> -<br>
> - OS << "namespace llvm {\n\n";<br>
> - OS << "const int " << TargetName << "DFAStateInputTable[][2] = {\n";<br>
> + std::vector<int> StateEntry(numStates+1);<br>
> + static const std::string SentinelEntry = "{-1, -1}";<br>
><br>
> // Tracks the total valid transitions encountered so far. It is used<br>
> // to construct the StateEntry table.<br>
> int ValidTransitions = 0;<br>
> - for (unsigned i = 0; i < states.size(); ++i, ++SI) {<br>
> + DFA::StateSet::iterator SI = states.begin();<br>
> + for (unsigned i = 0; i < numStates; ++i, ++SI) {<br>
> assert ((SI->stateNum == (int) i) && "Mismatch in state numbers");<br>
> StateEntry[i] = ValidTransitions;<br>
> for (State::TransitionMap::iterator<br>
> II = SI->Transitions.begin(), IE = SI->Transitions.end();<br>
> II != IE; ++II) {<br>
> - OS << "{" << II->first << ", "<br>
> + OS << "{0x" << utohexstr(getDFAInsnInput(II->first)) << ", "<br>
> << II->second->stateNum<br>
> - << "}, ";<br>
> + << "},\t";<br>
> }<br>
> ValidTransitions += SI->Transitions.size();<br>
><br>
> // If there are no valid transitions from this stage, we need a sentinel<br>
> // transition.<br>
> if (ValidTransitions == StateEntry[i]) {<br>
> - OS << SentinelEntry << ",";<br>
> + OS << SentinelEntry << ",\t";<br>
> ++ValidTransitions;<br>
> }<br>
><br>
> + OS << " // state " << i << ": " << StateEntry[i];<br>
> + if (StateEntry[i] != (ValidTransitions-1)) { // More than one transition.<br>
> + OS << "-" << (ValidTransitions-1);<br>
> + }<br>
> OS << "\n";<br>
> }<br>
><br>
> // Print out a sentinel entry at the end of the StateInputTable. This is<br>
> // needed to iterate over StateInputTable in DFAPacketizer::ReadTable()<br>
> - OS << SentinelEntry << "\n";<br>
> -<br>
> + OS << SentinelEntry << "\t";<br>
> + OS << " // state " << numStates << ": " << ValidTransitions;<br>
> + OS << "\n";<br>
> +<br>
> OS << "};\n\n";<br>
> + OS << "// " << TargetName << "DFAStateEntryTable[i] = "<br>
> + << "Index of the first entry in DFAStateInputTable for\n";<br>
> + OS << "// "<br>
> + << "the ith state.\n";<br>
> + OS << "// " << numStates << " states\n";<br>
> OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n";<br>
><br>
> // Multiply i by 2 since each entry in DFAStateInputTable is a set of<br>
> // two numbers.<br>
> - for (unsigned i = 0; i < states.size(); ++i)<br>
> + unsigned lastState = 0;<br>
> + for (unsigned i = 0; i < numStates; ++i) {<br>
> + if (i && ((i % 10) == 0)) {<br>
> + lastState = i-1;<br>
> + OS << " // states " << (i-10) << ":" << lastState << "\n";<br>
> + }<br>
> OS << StateEntry[i] << ", ";<br>
> + }<br>
><br>
> // Print out the index to the sentinel entry in StateInputTable<br>
> OS << ValidTransitions << ", ";<br>
> + OS << " // states " << (lastState+1) << ":" << numStates << "\n";<br>
><br>
> - OS << "\n};\n";<br>
> + OS << "};\n";<br>
> OS << "} // namespace\n";<br>
><br>
><br>
> @@ -332,40 +590,123 @@ void DFA::writeTableAndAPI(raw_ostream &<br>
><br>
><br>
> //<br>
> -// collectAllInsnClasses - Populate allInsnClasses which is a set of units<br>
> -// used in each stage.<br>
> +// collectAllFuncUnits - Construct a map of function unit names to bits.<br>
> //<br>
> -void DFAPacketizerEmitter::collectAllInsnClasses(const std::string &Name,<br>
> - Record *ItinData,<br>
> - unsigned &NStages,<br>
> - raw_ostream &OS) {<br>
> - // Collect processor itineraries.<br>
> - std::vector<Record*> ProcItinList =<br>
> - Records.getAllDerivedDefinitions("ProcessorItineraries");<br>
> -<br>
> - // If just no itinerary then don't bother.<br>
> - if (ProcItinList.size() < 2)<br>
> - return;<br>
> - std::map<std::string, unsigned> NameToBitsMap;<br>
> +int DFAPacketizerEmitter::collectAllFuncUnits(<br>
> + std::vector<Record*> &ProcItinList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + int &maxFUs,<br>
> + raw_ostream &OS) {<br>
> + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");<br>
> + DEBUG(dbgs() << "collectAllFuncUnits");<br>
> + DEBUG(dbgs() << " (" << ProcItinList.size() << " itineraries)\n");<br>
><br>
> + int totalFUs = 0;<br>
> // Parse functional units for all the itineraries.<br>
> for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {<br>
> Record *Proc = ProcItinList[i];<br>
> + const std::string &ProcName = Proc->getName();<br>
> std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");<br>
><br>
> + DEBUG(dbgs() << " FU:" << i<br>
> + << " (" << FUs.size() << " FUs) "<br>
> + << ProcName);<br>
> +<br>
> +<br>
> // Convert macros to bits for each stage.<br>
> - for (unsigned i = 0, N = FUs.size(); i < N; ++i)<br>
> - NameToBitsMap[FUs[i]->getName()] = (unsigned) (1U << i);<br>
> + unsigned numFUs = FUs.size();<br>
> + for (unsigned j = 0; j < numFUs; ++j) {<br>
> + assert ((j < DFA_MAX_RESOURCES) &&<br>
> + "Exceeded maximum number of representable resources");<br>
> + unsigned FuncResources = (unsigned) (1U << j);<br>
> + FUNameToBitsMap[FUs[j]->getName()] = FuncResources;<br>
> + DEBUG(dbgs() << " " << FUs[j]->getName()<br>
> + << ":0x" << utohexstr(FuncResources));<br>
> + }<br>
> + if (((int) numFUs) > maxFUs) {<br>
> + maxFUs = numFUs;<br>
> + }<br>
> + totalFUs += numFUs;<br>
> + DEBUG(dbgs() << "\n");<br>
> }<br>
> + return totalFUs;<br>
> +}<br>
> +<br>
> +//<br>
> +// collectAllComboFuncs - Construct a map from a combo function unit bit to<br>
> +// the bits of all included functional units.<br>
> +//<br>
> +int DFAPacketizerEmitter::collectAllComboFuncs(<br>
> + std::vector<Record*> &ComboFuncList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + std::map<unsigned, unsigned> &ComboBitToBitsMap,<br>
> + raw_ostream &OS) {<br>
> + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");<br>
> + DEBUG(dbgs() << "collectAllComboFuncs");<br>
> + DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n");<br>
> +<br>
> + int numCombos = 0;<br>
> + for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) {<br>
> + Record *Func = ComboFuncList[i];<br>
> + const std::string &ProcName = Func->getName();<br>
> + std::vector<Record*> FUs = Func->getValueAsListOfDefs("CFD");<br>
> +<br>
> + DEBUG(dbgs() << " CFD:" << i<br>
> + << " (" << FUs.size() << " combo FUs) "<br>
> + << ProcName << "\n");<br>
> +<br>
> + // Convert macros to bits for each stage.<br>
> + for (unsigned j = 0, N = FUs.size(); j < N; ++j) {<br>
> + assert ((j < DFA_MAX_RESOURCES) &&<br>
> + "Exceeded maximum number of DFA resources");<br>
> + Record *FuncData = FUs[j];<br>
> + Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");<br>
> + const std::vector<Record*> &FuncList =<br>
> + FuncData->getValueAsListOfDefs("FuncList");<br>
> + std::string ComboFuncName = ComboFunc->getName();<br>
> + unsigned ComboBit = FUNameToBitsMap[ComboFuncName];<br>
> + unsigned ComboResources = ComboBit;<br>
> + DEBUG(dbgs() << " combo: " << ComboFuncName<br>
> + << ":0x" << utohexstr(ComboResources) << "\n");<br>
> + for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {<br>
> + std::string FuncName = FuncList[k]->getName();<br>
> + unsigned FuncResources = FUNameToBitsMap[FuncName];<br>
> + DEBUG(dbgs() << " " << FuncName<br>
> + << ":0x" << utohexstr(FuncResources) << "\n");<br>
> + ComboResources |= FuncResources;<br>
> + }<br>
> + ComboBitToBitsMap[ComboBit] = ComboResources;<br>
> + numCombos++;<br>
> + DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x"<br>
> + << utohexstr(ComboBit) << " = 0x"<br>
> + << utohexstr(ComboResources) << "\n");<br>
> + }<br>
> + }<br>
> + return numCombos;<br>
> +}<br>
> +<br>
> +<br>
> +//<br>
> +// collectOneInsnClass - Populate allInsnClasses with one instruction class<br>
> +//<br>
> +int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName,<br>
> + std::vector<Record*> &ProcItinList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + Record *ItinData,<br>
> + raw_ostream &OS) {<br>
> + // Collect instruction classes.<br>
> + Record *ItinDef = ItinData->getValueAsDef("TheClass");<br>
><br>
> const std::vector<Record*> &StageList =<br>
> ItinData->getValueAsListOfDefs("Stages");<br>
><br>
> // The number of stages.<br>
> - NStages = StageList.size();<br>
> + unsigned NStages = StageList.size();<br>
><br>
> - // For each unit.<br>
> - unsigned UnitBitValue = 0;<br>
> + DEBUG(dbgs() << " " << ItinDef->getName()<br>
> + << "\n");<br>
> +<br>
> + std::vector<unsigned> UnitBits;<br>
><br>
> // Compute the bitwise or of each unit used in this stage.<br>
> for (unsigned i = 0; i < NStages; ++i) {<br>
> @@ -375,18 +716,72 @@ void DFAPacketizerEmitter::collectAllIns<br>
> const std::vector<Record*> &UnitList =<br>
> Stage->getValueAsListOfDefs("Units");<br>
><br>
> + DEBUG(dbgs() << " stage:" << i<br>
> + << " [" << UnitList.size() << " units]:");<br>
> + unsigned dbglen = 26; // cursor after stage dbgs<br>
> +<br>
> + // Compute the bitwise or of each unit used in this stage.<br>
> + unsigned UnitBitValue = 0;<br>
> for (unsigned j = 0, M = UnitList.size(); j < M; ++j) {<br>
> // Conduct bitwise or.<br>
> std::string UnitName = UnitList[j]->getName();<br>
> - assert(NameToBitsMap.count(UnitName));<br>
> - UnitBitValue |= NameToBitsMap[UnitName];<br>
> + DEBUG(dbgs() << " " << j << ":" << UnitName);<br>
> + dbglen += 3 + UnitName.length();<br>
> + assert(FUNameToBitsMap.count(UnitName));<br>
> + UnitBitValue |= FUNameToBitsMap[UnitName];<br>
> }<br>
><br>
> if (UnitBitValue != 0)<br>
> - allInsnClasses.insert(UnitBitValue);<br>
> + UnitBits.push_back(UnitBitValue);<br>
> +<br>
> + while (dbglen <= 64) { // line up bits dbgs<br>
> + dbglen += 8;<br>
> + DEBUG(dbgs() << "\t");<br>
> + }<br>
> + DEBUG(dbgs() << " (bits: 0x" << utohexstr(UnitBitValue) << ")\n");<br>
> }<br>
> +<br>
> + if (UnitBits.size() > 0)<br>
> + allInsnClasses.push_back(UnitBits);<br>
> +<br>
> + DEBUG(dbgs() << " ");<br>
> + dbgsInsnClass(UnitBits);<br>
> + DEBUG(dbgs() << "\n");<br>
> +<br>
> + return NStages;<br>
> }<br>
><br>
> +//<br>
> +// collectAllInsnClasses - Populate allInsnClasses which is a set of units<br>
> +// used in each stage.<br>
> +//<br>
> +int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,<br>
> + std::vector<Record*> &ProcItinList,<br>
> + std::map<std::string, unsigned> &FUNameToBitsMap,<br>
> + std::vector<Record*> &ItinDataList,<br>
> + int &maxStages,<br>
> + raw_ostream &OS) {<br>
> + // Collect all instruction classes.<br>
> + unsigned M = ItinDataList.size();<br>
> +<br>
> + int numInsnClasses = 0;<br>
> + DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"<br>
> + << "collectAllInsnClasses "<br>
> + << ProcName<br>
> + << " (" << M << " classes)\n");<br>
> +<br>
> + // Collect stages for each instruction class for all itinerary data<br>
> + for (unsigned j = 0; j < M; j++) {<br>
> + Record *ItinData = ItinDataList[j];<br>
> + int NStages = collectOneInsnClass(ProcName, ProcItinList,<br>
> + FUNameToBitsMap, ItinData, OS);<br>
> + if (NStages > maxStages) {<br>
> + maxStages = NStages;<br>
> + }<br>
> + numInsnClasses++;<br>
> + }<br>
> + return numInsnClasses;<br>
> +}<br>
><br>
> //<br>
> // Run the worklist algorithm to generate the DFA.<br>
> @@ -398,16 +793,35 @@ void DFAPacketizerEmitter::run(raw_ostre<br>
> Records.getAllDerivedDefinitions("ProcessorItineraries");<br>
><br>
> //<br>
> - // Collect the instruction classes.<br>
> + // Collect the Functional units.<br>
> + //<br>
> + std::map<std::string, unsigned> FUNameToBitsMap;<br>
> + int maxResources = 0;<br>
> + collectAllFuncUnits(ProcItinList,<br>
> + FUNameToBitsMap, maxResources, OS);<br>
> +<br>
> + //<br>
> + // Collect the Combo Functional units.<br>
> + //<br>
> + std::map<unsigned, unsigned> ComboBitToBitsMap;<br>
> + std::vector<Record*> ComboFuncList =<br>
> + Records.getAllDerivedDefinitions("ComboFuncUnits");<br>
> + int numCombos = collectAllComboFuncs(ComboFuncList,<br>
> + FUNameToBitsMap, ComboBitToBitsMap, OS);<br>
> +<br>
> + //<br>
> + // Collect the itineraries.<br>
> //<br>
> + int maxStages = 0;<br>
> + int numInsnClasses = 0;<br>
> for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {<br>
> Record *Proc = ProcItinList[i];<br>
><br>
> // Get processor itinerary name.<br>
> - const std::string &Name = Proc->getName();<br>
> + const std::string &ProcName = Proc->getName();<br>
><br>
> // Skip default.<br>
> - if (Name == "NoItineraries")<br>
> + if (ProcName == "NoItineraries")<br>
> continue;<br>
><br>
> // Sanity check for at least one instruction itinerary class.<br>
> @@ -419,15 +833,11 @@ void DFAPacketizerEmitter::run(raw_ostre<br>
> // Get itinerary data list.<br>
> std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");<br>
><br>
> - // Collect instruction classes for all itinerary data.<br>
> - for (unsigned j = 0, M = ItinDataList.size(); j < M; j++) {<br>
> - Record *ItinData = ItinDataList[j];<br>
> - unsigned NStages;<br>
> - collectAllInsnClasses(Name, ItinData, NStages, OS);<br>
> - }<br>
> + // Collect all instruction classes<br>
> + numInsnClasses += collectAllInsnClasses(ProcName, ProcItinList,<br>
> + FUNameToBitsMap, ItinDataList, maxStages, OS);<br>
> }<br>
><br>
> -<br>
> //<br>
> // Run a worklist algorithm to generate the DFA.<br>
> //<br>
> @@ -436,6 +846,7 @@ void DFAPacketizerEmitter::run(raw_ostre<br>
> Initial->isInitial = true;<br>
> Initial->stateInfo.insert(0x0);<br>
> SmallVector<const State*, 32> WorkList;<br>
> +// std::queue<State*> WorkList;<br>
> std::map<std::set<unsigned>, const State*> Visited;<br>
><br>
> WorkList.push_back(Initial);<br>
> @@ -459,9 +870,15 @@ void DFAPacketizerEmitter::run(raw_ostre<br>
> //<br>
> while (!WorkList.empty()) {<br>
> const State *current = WorkList.pop_back_val();<br>
> - for (DenseSet<unsigned>::iterator CI = allInsnClasses.begin(),<br>
> - CE = allInsnClasses.end(); CI != CE; ++CI) {<br>
> - unsigned InsnClass = *CI;<br>
> + DEBUG(dbgs() << "---------------------\n");<br>
> + DEBUG(dbgs() << "Processing state: " << current->stateNum << " - ");<br>
> + dbgsStateInfo(current->stateInfo);<br>
> + DEBUG(dbgs() << "\n");<br>
> + for (unsigned i = 0; i < allInsnClasses.size(); i++) {<br>
> + std::vector<unsigned> InsnClass = allInsnClasses[i];<br>
> + DEBUG(dbgs() << i << " ");<br>
> + dbgsInsnClass(InsnClass);<br>
> + DEBUG(dbgs() << "\n");<br>
><br>
> std::set<unsigned> NewStateResources;<br>
> //<br>
> @@ -469,32 +886,47 @@ void DFAPacketizerEmitter::run(raw_ostre<br>
> // and the state can accommodate this InsnClass, create a transition.<br>
> //<br>
> if (!current->hasTransition(InsnClass) &&<br>
> - current->canAddInsnClass(InsnClass)) {<br>
> - const State *NewState;<br>
> - current->AddInsnClass(InsnClass, NewStateResources);<br>
> - assert(!NewStateResources.empty() && "New states must be generated");<br>
> + current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {<br>
> + const State *NewState = NULL;<br>
> + current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);<br>
> + if (NewStateResources.size() == 0) {<br>
> + DEBUG(dbgs() << " Skipped - no new states generated\n");<br>
> + continue;<br>
> + }<br>
> +<br>
> + DEBUG(dbgs() << "\t");<br>
> + dbgsStateInfo(NewStateResources);<br>
> + DEBUG(dbgs() << "\n");<br>
><br>
> //<br>
> // If we have seen this state before, then do not create a new state.<br>
> //<br>
> - //<br>
> auto VI = Visited.find(NewStateResources);<br>
> - if (VI != Visited.end())<br>
> + if (VI != Visited.end()) {<br>
> NewState = VI->second;<br>
> - else {<br>
> + DEBUG(dbgs() << "\tFound existing state: "<br>
> + << NewState->stateNum << " - ");<br>
> + dbgsStateInfo(NewState->stateInfo);<br>
> + DEBUG(dbgs() << "\n");<br>
> + } else {<br>
> NewState = &D.newState();<br>
> NewState->stateInfo = NewStateResources;<br>
> Visited[NewStateResources] = NewState;<br>
> WorkList.push_back(NewState);<br>
> + DEBUG(dbgs() << "\tAccepted new state: "<br>
> + << NewState->stateNum << " - ");<br>
> + dbgsStateInfo(NewState->stateInfo);<br>
> + DEBUG(dbgs() << "\n");<br>
> }<br>
> -<br>
> +<br>
> current->addTransition(InsnClass, NewState);<br>
> }<br>
> }<br>
> }<br>
><br>
> // Print out the table.<br>
> - D.writeTableAndAPI(OS, TargetName);<br>
> + D.writeTableAndAPI(OS, TargetName,<br>
> + numInsnClasses, maxResources, numCombos, maxStages);<br>
> }<br>
><br>
> namespace llvm {<br>
><br>
><br>
> _______________________________________________<br>
> llvm-commits mailing list<br>
> <a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</p>