Home | History | Annotate | Download | only in MCTargetDesc
      1 //===----- HexagonShuffler.h - Instruction bundle shuffling ---------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This implements the shuffling of insns inside a bundle according to the
     11 // packet formation rules of the Hexagon ISA.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef HEXAGONSHUFFLER_H
     16 #define HEXAGONSHUFFLER_H
     17 
     18 #include "Hexagon.h"
     19 #include "MCTargetDesc/HexagonMCInstrInfo.h"
     20 
     21 #include "llvm/ADT/SmallVector.h"
     22 #include "llvm/MC/MCInstrInfo.h"
     23 #include "llvm/MC/MCSubtargetInfo.h"
     24 
     25 using namespace llvm;
     26 
     27 namespace llvm {
     28 // Insn resources.
     29 class HexagonResource {
     30   // Mask of the slots or units that may execute the insn and
     31   // the weight or priority that the insn requires to be assigned a slot.
     32   unsigned Slots, Weight;
     33 
     34 public:
     35   HexagonResource(unsigned s) { setUnits(s); };
     36 
     37   void setUnits(unsigned s) {
     38     Slots = s & ~(~0U << HEXAGON_PACKET_SIZE);
     39   };
     40   unsigned setWeight(unsigned s);
     41 
     42   unsigned getUnits() const { return (Slots); };
     43   unsigned getWeight() const { return (Weight); };
     44 
     45   // Check if the resources are in ascending slot order.
     46   static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
     47     return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
     48   };
     49   // Check if the resources are in ascending weight order.
     50   static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
     51     return (A.getWeight() < B.getWeight());
     52   };
     53 };
     54 
     55 // HVX insn resources.
     56 class HexagonCVIResource : public HexagonResource {
     57 public:
     58   typedef std::pair<unsigned, unsigned> UnitsAndLanes;
     59   typedef llvm::DenseMap<unsigned, UnitsAndLanes> TypeUnitsAndLanes;
     60 
     61 private:
     62   // Available HVX slots.
     63   enum {
     64     CVI_NONE = 0,
     65     CVI_XLANE = 1 << 0,
     66     CVI_SHIFT = 1 << 1,
     67     CVI_MPY0 = 1 << 2,
     68     CVI_MPY1 = 1 << 3
     69   };
     70 
     71   TypeUnitsAndLanes *TUL;
     72 
     73   // Count of adjacent slots that the insn requires to be executed.
     74   unsigned Lanes;
     75   // Flag whether the insn is a load or a store.
     76   bool Load, Store;
     77   // Flag whether the HVX resources are valid.
     78   bool Valid;
     79 
     80   void setLanes(unsigned l) { Lanes = l; };
     81   void setLoad(bool f = true) { Load = f; };
     82   void setStore(bool f = true) { Store = f; };
     83 
     84 public:
     85   HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII,
     86                      unsigned s, MCInst const *id);
     87   static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU);
     88 
     89   bool isValid() const { return (Valid); };
     90   unsigned getLanes() const { return (Lanes); };
     91   bool mayLoad() const { return (Load); };
     92   bool mayStore() const { return (Store); };
     93 };
     94 
     95 // Handle to an insn used by the shuffling algorithm.
     96 class HexagonInstr {
     97   friend class HexagonShuffler;
     98 
     99   MCInst const *ID;
    100   MCInst const *Extender;
    101   HexagonResource Core;
    102   HexagonCVIResource CVI;
    103   bool SoloException;
    104 
    105 public:
    106   HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
    107                MCInstrInfo const &MCII, MCInst const *id,
    108                MCInst const *Extender, unsigned s, bool x = false)
    109       : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id),
    110         SoloException(x) {};
    111 
    112   MCInst const *getDesc() const { return (ID); };
    113 
    114   MCInst const *getExtender() const { return Extender; }
    115 
    116   unsigned isSoloException() const { return (SoloException); };
    117 
    118   // Check if the handles are in ascending order for shuffling purposes.
    119   bool operator<(const HexagonInstr &B) const {
    120     return (HexagonResource::lessWeight(B.Core, Core));
    121   };
    122   // Check if the handles are in ascending order by core slots.
    123   static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
    124     return (HexagonResource::lessUnits(A.Core, B.Core));
    125   };
    126   // Check if the handles are in ascending order by HVX slots.
    127   static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
    128     return (HexagonResource::lessUnits(A.CVI, B.CVI));
    129   };
    130 };
    131 
    132 // Bundle shuffler.
    133 class HexagonShuffler {
    134   typedef SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>
    135       HexagonPacket;
    136 
    137   // Insn handles in a bundle.
    138   HexagonPacket Packet;
    139 
    140   // Shuffling error code.
    141   unsigned Error;
    142 
    143   HexagonCVIResource::TypeUnitsAndLanes TUL;
    144 
    145 protected:
    146   int64_t BundleFlags;
    147   MCInstrInfo const &MCII;
    148   MCSubtargetInfo const &STI;
    149 
    150 public:
    151   typedef HexagonPacket::iterator iterator;
    152 
    153   enum {
    154     SHUFFLE_SUCCESS = 0,    ///< Successful operation.
    155     SHUFFLE_ERROR_INVALID,  ///< Invalid bundle.
    156     SHUFFLE_ERROR_STORES,   ///< No free slots for store insns.
    157     SHUFFLE_ERROR_LOADS,    ///< No free slots for load insns.
    158     SHUFFLE_ERROR_BRANCHES, ///< No free slots for branch insns.
    159     SHUFFLE_ERROR_NOSLOTS,  ///< No free slots for other insns.
    160     SHUFFLE_ERROR_SLOTS,    ///< Over-subscribed slots.
    161     SHUFFLE_ERROR_ERRATA2, ///< Errata violation (v60).
    162     SHUFFLE_ERROR_STORE_LOAD_CONFLICT, ///< store/load conflict
    163     SHUFFLE_ERROR_UNKNOWN   ///< Unknown error.
    164   };
    165 
    166   explicit HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
    167 
    168   // Reset to initial state.
    169   void reset();
    170   // Check if the bundle may be validly shuffled.
    171   bool check();
    172   // Reorder the insn handles in the bundle.
    173   bool shuffle();
    174 
    175   unsigned size() const { return (Packet.size()); };
    176 
    177   iterator begin() { return (Packet.begin()); };
    178   iterator end() { return (Packet.end()); };
    179 
    180   // Add insn handle to the bundle .
    181   void append(MCInst const *ID, MCInst const *Extender, unsigned S,
    182               bool X = false);
    183 
    184   // Return the error code for the last check or shuffling of the bundle.
    185   void setError(unsigned Err) { Error = Err; };
    186   unsigned getError() const { return (Error); };
    187 };
    188 }
    189 
    190 #endif // HEXAGONSHUFFLER_H
    191