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