1 //===- HexagonShuffler.h - Instruction bundle shuffling ---------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This implements the shuffling of insns inside a bundle according to the 10 // packet formation rules of the Hexagon ISA. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H 15 #define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H 16 17 #include "MCTargetDesc/HexagonMCInstrInfo.h" 18 #include "MCTargetDesc/HexagonMCTargetDesc.h" 19 #include "llvm/ADT/DenseMap.h" 20 #include "llvm/ADT/SmallVector.h" 21 #include "llvm/ADT/StringRef.h" 22 #include "llvm/Support/MathExtras.h" 23 #include "llvm/Support/SMLoc.h" 24 #include <cstdint> 25 #include <utility> 26 27 namespace llvm { 28 29 class MCContext; 30 class MCInst; 31 class MCInstrInfo; 32 class MCSubtargetInfo; 33 34 // Insn resources. 35 class HexagonResource { 36 // Mask of the slots or units that may execute the insn and 37 // the weight or priority that the insn requires to be assigned a slot. 38 unsigned Slots, Weight; 39 40 public: 41 HexagonResource(unsigned s) { setUnits(s); } 42 43 void setUnits(unsigned s) { 44 Slots = s & ((1u << HEXAGON_PACKET_SIZE) - 1); 45 setWeight(s); 46 } 47 48 unsigned setWeight(unsigned s); 49 50 unsigned getUnits() const { return (Slots); } 51 unsigned getWeight() const { return (Weight); } 52 53 // Check if the resources are in ascending slot order. 54 static bool lessUnits(const HexagonResource &A, const HexagonResource &B) { 55 return (countPopulation(A.getUnits()) < countPopulation(B.getUnits())); 56 } 57 58 // Check if the resources are in ascending weight order. 59 static bool lessWeight(const HexagonResource &A, const HexagonResource &B) { 60 return (A.getWeight() < B.getWeight()); 61 } 62 }; 63 64 // HVX insn resources. 65 class HexagonCVIResource : public HexagonResource { 66 public: 67 using UnitsAndLanes = std::pair<unsigned, unsigned>; 68 using TypeUnitsAndLanes = DenseMap<unsigned, UnitsAndLanes>; 69 70 private: 71 // Available HVX slots. 72 enum { 73 CVI_NONE = 0, 74 CVI_XLANE = 1 << 0, 75 CVI_SHIFT = 1 << 1, 76 CVI_MPY0 = 1 << 2, 77 CVI_MPY1 = 1 << 3, 78 CVI_ZW = 1 << 4 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 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 98 bool isValid() const { return Valid; } 99 unsigned getLanes() const { return Lanes; } 100 bool mayLoad() const { return Load; } 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: 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 119 MCInst const &getDesc() const { return *ID; } 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. 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. 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 174 unsigned size() const { return (Packet.size()); } 175 176 bool isMemReorderDisabled() const { 177 return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0; 178 } 179 180 iterator begin() { return (Packet.begin()); } 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