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 CVI_ZW = 1 << 4 80 }; 81 82 // Count of adjacent slots that the insn requires to be executed. 83 unsigned Lanes; 84 // Flag whether the insn is a load or a store. 85 bool Load, Store; 86 // Flag whether the HVX resources are valid. 87 bool Valid; 88 setLanes(unsigned l)89 void setLanes(unsigned l) { Lanes = l; } 90 void setLoad(bool f = true) { Load = f; } 91 void setStore(bool f = true) { Store = f; } 92 93 public: 94 HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII, 95 unsigned s, MCInst const *id); 96 97 static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU); 98 isValid()99 bool isValid() const { return Valid; } getLanes()100 unsigned getLanes() const { return Lanes; } mayLoad()101 bool mayLoad() const { return Load; } mayStore()102 bool mayStore() const { return Store; } 103 }; 104 105 // Handle to an insn used by the shuffling algorithm. 106 class HexagonInstr { 107 friend class HexagonShuffler; 108 109 MCInst const *ID; 110 MCInst const *Extender; 111 HexagonResource Core; 112 HexagonCVIResource CVI; 113 114 public: HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes * T,MCInstrInfo const & MCII,MCInst const * id,MCInst const * Extender,unsigned s)115 HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T, 116 MCInstrInfo const &MCII, MCInst const *id, 117 MCInst const *Extender, unsigned s) 118 : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {} 119 getDesc()120 MCInst const &getDesc() const { return *ID; } getExtender()121 MCInst const *getExtender() const { return Extender; } 122 123 // Check if the handles are in ascending order for shuffling purposes. 124 bool operator<(const HexagonInstr &B) const { 125 return (HexagonResource::lessWeight(B.Core, Core)); 126 } 127 128 // Check if the handles are in ascending order by core slots. lessCore(const HexagonInstr & A,const HexagonInstr & B)129 static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) { 130 return (HexagonResource::lessUnits(A.Core, B.Core)); 131 } 132 133 // Check if the handles are in ascending order by HVX slots. lessCVI(const HexagonInstr & A,const HexagonInstr & B)134 static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) { 135 return (HexagonResource::lessUnits(A.CVI, B.CVI)); 136 } 137 }; 138 139 // Bundle shuffler. 140 class HexagonShuffler { 141 using HexagonPacket = 142 SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>; 143 144 // Insn handles in a bundle. 145 HexagonPacket Packet; 146 HexagonPacket PacketSave; 147 148 HexagonCVIResource::TypeUnitsAndLanes TUL; 149 150 protected: 151 MCContext &Context; 152 int64_t BundleFlags; 153 MCInstrInfo const &MCII; 154 MCSubtargetInfo const &STI; 155 SMLoc Loc; 156 bool ReportErrors; 157 std::vector<std::pair<SMLoc, std::string>> AppliedRestrictions; 158 void applySlotRestrictions(); 159 void restrictSlot1AOK(); 160 void restrictNoSlot1Store(); 161 162 public: 163 using iterator = HexagonPacket::iterator; 164 165 HexagonShuffler(MCContext &Context, bool ReportErrors, 166 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 size()175 unsigned size() const { return (Packet.size()); } 176 isMemReorderDisabled()177 bool isMemReorderDisabled() const { 178 return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0; 179 } 180 begin()181 iterator begin() { return (Packet.begin()); } end()182 iterator end() { return (Packet.end()); } 183 184 // Add insn handle to the bundle . 185 void append(MCInst const &ID, MCInst const *Extender, unsigned S); 186 187 // Return the error code for the last check or shuffling of the bundle. 188 void reportError(Twine const &Msg); 189 }; 190 191 } // end namespace llvm 192 193 #endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H 194