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