<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>