1 //===- HexagonShuffler.h - Instruction bundle shuffling ---------*- C++ -*-===// 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 LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H 16 #define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H 17 18 #include "Hexagon.h" 19 #include "MCTargetDesc/HexagonMCInstrInfo.h" 20 #include "llvm/ADT/DenseMap.h" 21 #include "llvm/ADT/SmallVector.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/Support/MathExtras.h" 24 #include "llvm/Support/SMLoc.h" 25 #include <cstdint> 26 #include <utility> 27 28 namespace llvm { 29 30 class MCContext; 31 class MCInst; 32 class MCInstrInfo; 33 class MCSubtargetInfo; 34 35 // Insn resources. 36 class HexagonResource { 37 // Mask of the slots or units that may execute the insn and 38 // the weight or priority that the insn requires to be assigned a slot. 39 unsigned Slots, Weight; 40 41 public: HexagonResource(unsigned s)42 HexagonResource(unsigned s) { setUnits(s); } 43 setUnits(unsigned s)44 void setUnits(unsigned s) { 45 Slots = s & ((1u << HEXAGON_PACKET_SIZE) - 1); 46 setWeight(s); 47 } 48 49 unsigned setWeight(unsigned s); 50 getUnits()51 unsigned getUnits() const { return (Slots); } getWeight()52 unsigned getWeight() const { return (Weight); } 53 54 // Check if the resources are in ascending slot order. lessUnits(const HexagonResource & A,const HexagonResource & B)55 static bool lessUnits(const HexagonResource &A, const HexagonResource &B) { 56 return (countPopulation(A.getUnits()) < countPopulation(B.getUnits())); 57 } 58 59 // Check if the resources are in ascending weight order. lessWeight(const HexagonResource & A,const HexagonResource & B)60 static bool lessWeight(const HexagonResource &A, const HexagonResource &B) { 61 return (A.getWeight() < B.getWeight()); 62 } 63 }; 64 65 // HVX insn resources. 66 class HexagonCVIResource : public HexagonResource { 67 public: 68 using UnitsAndLanes = std::pair<unsigned, unsigned>; 69 using TypeUnitsAndLanes = DenseMap<unsigned, UnitsAndLanes>; 70 71 private: 72 // Available HVX slots. 73 enum { 74 CVI_NONE = 0, 75 CVI_XLANE = 1 << 0, 76 CVI_SHIFT = 1 << 1, 77 CVI_MPY0 = 1 << 2, 78 CVI_MPY1 = 1 << 3 79 }; 80 81 // Count of adjacent slots that the insn requires to be executed. 82 unsigned Lanes; 83 // Flag whether the insn is a load or a store. 84 bool Load, Store; 85 // Flag whether the HVX resources are valid. 86 bool Valid; 87 setLanes(unsigned l)88 void setLanes(unsigned l) { Lanes = l; } 89 void setLoad(bool f = true) { Load = f; } 90 void setStore(bool f = true) { Store = f; } 91 92 public: 93 HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII, 94 unsigned s, MCInst const *id); 95 96 static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU); 97 isValid()98 bool isValid() const { return Valid; } getLanes()99 unsigned getLanes() const { return Lanes; } mayLoad()100 bool mayLoad() const { return Load; } mayStore()101 bool mayStore() const { return Store; } 102 }; 103 104 // Handle to an insn used by the shuffling algorithm. 105 class HexagonInstr { 106 friend class HexagonShuffler; 107 108 MCInst const *ID; 109 MCInst const *Extender; 110 HexagonResource Core; 111 HexagonCVIResource CVI; 112 113 public: HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes * T,MCInstrInfo const & MCII,MCInst const * id,MCInst const * Extender,unsigned s)114 HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T, 115 MCInstrInfo const &MCII, MCInst const *id, 116 MCInst const *Extender, unsigned s) 117 : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {} 118 getDesc()119 MCInst const &getDesc() const { return *ID; } getExtender()120 MCInst const *getExtender() const { return Extender; } 121 122 // Check if the handles are in ascending order for shuffling purposes. 123 bool operator<(const HexagonInstr &B) const { 124 return (HexagonResource::lessWeight(B.Core, Core)); 125 } 126 127 // Check if the handles are in ascending order by core slots. lessCore(const HexagonInstr & A,const HexagonInstr & B)128 static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) { 129 return (HexagonResource::lessUnits(A.Core, B.Core)); 130 } 131 132 // Check if the handles are in ascending order by HVX slots. lessCVI(const HexagonInstr & A,const HexagonInstr & B)133 static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) { 134 return (HexagonResource::lessUnits(A.CVI, B.CVI)); 135 } 136 }; 137 138 // Bundle shuffler. 139 class HexagonShuffler { 140 using HexagonPacket = 141 SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>; 142 143 // Insn handles in a bundle. 144 HexagonPacket Packet; 145 HexagonPacket PacketSave; 146 147 HexagonCVIResource::TypeUnitsAndLanes TUL; 148 149 protected: 150 MCContext &Context; 151 int64_t BundleFlags; 152 MCInstrInfo const &MCII; 153 MCSubtargetInfo const &STI; 154 SMLoc Loc; 155 bool ReportErrors; 156 std::vector<std::pair<SMLoc, std::string>> AppliedRestrictions; 157 void applySlotRestrictions(); 158 void restrictSlot1AOK(); 159 void restrictNoSlot1Store(); 160 161 public: 162 using iterator = HexagonPacket::iterator; 163 164 HexagonShuffler(MCContext &Context, bool ReportErrors, 165 MCInstrInfo const &MCII, MCSubtargetInfo const &STI); 166 167 // Reset to initial state. 168 void reset(); 169 // Check if the bundle may be validly shuffled. 170 bool check(); 171 // Reorder the insn handles in the bundle. 172 bool shuffle(); 173 size()174 unsigned size() const { return (Packet.size()); } 175 isMemReorderDisabled()176 bool isMemReorderDisabled() const { 177 return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0; 178 } 179 begin()180 iterator begin() { return (Packet.begin()); } end()181 iterator end() { return (Packet.end()); } 182 183 // Add insn handle to the bundle . 184 void append(MCInst const &ID, MCInst const *Extender, unsigned S); 185 186 // Return the error code for the last check or shuffling of the bundle. 187 void reportError(Twine const &Msg); 188 }; 189 190 } // end namespace llvm 191 192 #endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H 193