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