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