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 27namespace llvm { 28 29class MCContext; 30class MCInst; 31class MCInstrInfo; 32class MCSubtargetInfo; 33 34// Insn resources. 35class 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 40public: 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. 65class HexagonCVIResource : public HexagonResource { 66public: 67 using UnitsAndLanes = std::pair<unsigned, unsigned>; 68 using TypeUnitsAndLanes = DenseMap<unsigned, UnitsAndLanes>; 69 70private: 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 92public: 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. 105class HexagonInstr { 106 friend class HexagonShuffler; 107 108 MCInst const *ID; 109 MCInst const *Extender; 110 HexagonResource Core; 111 HexagonCVIResource CVI; 112 113public: 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. 139class 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 149protected: 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 161public: 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