1 //===----- HexagonShuffler.cpp - Instruction bundle shuffling -------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This implements the shuffling of insns inside a bundle according to the
11 // packet formation rules of the Hexagon ISA.
13 //===----------------------------------------------------------------------===//
15 #define DEBUG_TYPE "hexagon-shuffle"
20 #include "MCTargetDesc/HexagonBaseInfo.h"
21 #include "MCTargetDesc/HexagonMCTargetDesc.h"
22 #include "MCTargetDesc/HexagonMCInstrInfo.h"
23 #include "HexagonShuffler.h"
24 #include "llvm/Support/Debug.h"
25 #include "llvm/Support/MathExtras.h"
26 #include "llvm/Support/raw_ostream.h"
31 // Insn shuffling priority.
33 // The priority is directly proportional to how restricted the insn is based
34 // on its flexibility to run on the available slots. So, the fewer slots it
35 // may run on, the higher its priority.
36 enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15.
40 HexagonBid() : Bid(0){};
41 HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; };
43 // Check if the insn priority is overflowed.
44 bool isSold() const { return (Bid >= MAX); };
46 HexagonBid &operator+=(const HexagonBid &B) {
52 // Slot shuffling allocation.
53 class HexagonUnitAuction {
54 HexagonBid Scores[HEXAGON_PACKET_SIZE];
55 // Mask indicating which slot is unavailable.
56 unsigned isSold : HEXAGON_PACKET_SIZE;
59 HexagonUnitAuction() : isSold(0){};
62 bool bid(unsigned B) {
63 // Exclude already auctioned slots from the bid.
64 unsigned b = B & ~isSold;
66 for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i)
68 // Request candidate slots.
69 Scores[i] += HexagonBid(b);
70 isSold |= Scores[i].isSold() << i;
75 // Error if the desired slots are already full.
79 } // end anonymous namespace
81 unsigned HexagonResource::setWeight(unsigned s) {
82 const unsigned SlotWeight = 8;
83 const unsigned MaskWeight = SlotWeight - 1;
84 bool Key = (1 << s) & getUnits();
86 // TODO: Improve this API so that we can prevent misuse statically.
87 assert(SlotWeight * s < 32 && "Argument to setWeight too large.");
89 // Calculate relative weight of the insn for the given slot, weighing it the
90 // heavier the more restrictive the insn is and the lowest the slots that the
91 // insn may be executed in.
93 (Key << (SlotWeight * s)) * ((MaskWeight - countPopulation(getUnits()))
94 << countTrailingZeros(getUnits()));
98 HexagonCVIResource::TypeUnitsAndLanes *HexagonCVIResource::TUL;
100 bool HexagonCVIResource::SetUp = HexagonCVIResource::setup();
102 bool HexagonCVIResource::setup() {
104 TUL = new (TypeUnitsAndLanes);
106 (*TUL)[HexagonII::TypeCVI_VA] =
107 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
108 (*TUL)[HexagonII::TypeCVI_VA_DV] = UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2);
109 (*TUL)[HexagonII::TypeCVI_VX] = UnitsAndLanes(CVI_MPY0 | CVI_MPY1, 1);
110 (*TUL)[HexagonII::TypeCVI_VX_DV] = UnitsAndLanes(CVI_MPY0, 2);
111 (*TUL)[HexagonII::TypeCVI_VP] = UnitsAndLanes(CVI_XLANE, 1);
112 (*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2);
113 (*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1);
114 (*TUL)[HexagonII::TypeCVI_VINLANESAT] = UnitsAndLanes(CVI_SHIFT, 1);
115 (*TUL)[HexagonII::TypeCVI_VM_LD] =
116 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
117 (*TUL)[HexagonII::TypeCVI_VM_TMP_LD] = UnitsAndLanes(CVI_NONE, 0);
118 (*TUL)[HexagonII::TypeCVI_VM_CUR_LD] =
119 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
120 (*TUL)[HexagonII::TypeCVI_VM_VP_LDU] = UnitsAndLanes(CVI_XLANE, 1);
121 (*TUL)[HexagonII::TypeCVI_VM_ST] =
122 UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
123 (*TUL)[HexagonII::TypeCVI_VM_NEW_ST] = UnitsAndLanes(CVI_NONE, 0);
124 (*TUL)[HexagonII::TypeCVI_VM_STU] = UnitsAndLanes(CVI_XLANE, 1);
125 (*TUL)[HexagonII::TypeCVI_HIST] = UnitsAndLanes(CVI_XLANE, 4);
130 HexagonCVIResource::HexagonCVIResource(MCInstrInfo const &MCII, unsigned s,
132 : HexagonResource(s) {
133 unsigned T = HexagonMCInstrInfo::getType(MCII, *id);
138 setUnits((*TUL)[T].first);
139 setLanes((*TUL)[T].second);
140 setLoad(HexagonMCInstrInfo::getDesc(MCII, *id).mayLoad());
141 setStore(HexagonMCInstrInfo::getDesc(MCII, *id).mayStore());
152 HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
153 MCSubtargetInfo const &STI)
154 : MCII(MCII), STI(STI) {
158 void HexagonShuffler::reset() {
161 Error = SHUFFLE_SUCCESS;
164 void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,
165 unsigned S, bool X) {
166 HexagonInstr PI(MCII, ID, Extender, S, X);
168 Packet.push_back(PI);
171 /// Check that the packet is legal and enforce relative insn order.
172 bool HexagonShuffler::check() {
173 // Descriptive slot masks.
174 const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
175 slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4,
176 slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
177 // Highest slots for branches and stores used to keep their original order.
178 unsigned slotJump = slotFirstJump;
179 unsigned slotLoadStore = slotFirstLoadStore;
180 // Number of branches, solo branches, indirect branches.
181 unsigned jumps = 0, jump1 = 0, jumpr = 0;
182 // Number of memory operations, loads, solo loads, stores, solo stores, single
184 unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
185 // Number of HVX loads, HVX stores.
186 unsigned CVIloads = 0, CVIstores = 0;
187 // Number of duplex insns, solo insns.
188 unsigned duplex = 0, solo = 0;
189 // Number of insns restricting other insns in the packet to A and X types,
190 // which is neither A or X types.
191 unsigned onlyAX = 0, neitherAnorX = 0;
192 // Number of insns restricting other insns in slot #1 to A type.
193 unsigned onlyAin1 = 0;
194 // Number of insns restricting any insn in slot #1, except A2_nop.
195 unsigned onlyNo1 = 0;
196 unsigned xtypeFloat = 0;
197 unsigned pSlot3Cnt = 0;
198 iterator slot3ISJ = end();
200 // Collect information from the insns in the packet.
201 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
202 MCInst const *ID = ISJ->getDesc();
204 if (HexagonMCInstrInfo::isSolo(MCII, *ID))
205 solo += !ISJ->isSoloException();
206 else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))
207 onlyAX += !ISJ->isSoloException();
208 else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))
209 onlyAin1 += !ISJ->isSoloException();
210 if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 &&
211 HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE)
213 if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) {
218 switch (HexagonMCInstrInfo::getType(MCII, *ID)) {
219 case HexagonII::TypeXTYPE:
220 if (HexagonMCInstrInfo::isFloat(MCII, *ID))
223 case HexagonII::TypeJR:
226 case HexagonII::TypeJ:
229 case HexagonII::TypeCVI_VM_VP_LDU:
231 case HexagonII::TypeCVI_VM_LD:
232 case HexagonII::TypeCVI_VM_TMP_LD:
233 case HexagonII::TypeCVI_VM_CUR_LD:
235 case HexagonII::TypeLD:
238 if (ISJ->Core.getUnits() == slotSingleLoad)
240 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn())
241 ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
243 case HexagonII::TypeCVI_VM_STU:
245 case HexagonII::TypeCVI_VM_ST:
246 case HexagonII::TypeCVI_VM_NEW_ST:
248 case HexagonII::TypeST:
251 if (ISJ->Core.getUnits() == slotSingleStore)
254 case HexagonII::TypeMEMOP:
260 case HexagonII::TypeNV:
261 ++memory; // NV insns are memory-like.
262 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch())
265 case HexagonII::TypeCR:
266 // Legacy conditional branch predicated on a register.
267 case HexagonII::TypeSYSTEM:
268 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad())
274 // Check if the packet is legal.
275 if ((load0 > 1 || store0 > 1 || CVIloads > 1 || CVIstores > 1) ||
276 (duplex > 1 || (duplex && memory)) || (solo && size() > 1) ||
277 (onlyAX && neitherAnorX > 1) || (onlyAX && xtypeFloat)) {
278 Error = SHUFFLE_ERROR_INVALID;
282 if (jump1 && jumps > 1) {
283 // Error if single branch with another branch.
284 Error = SHUFFLE_ERROR_BRANCHES;
288 // Modify packet accordingly.
289 // TODO: need to reserve slots #0 and #1 for duplex insns.
290 bool bOnlySlot3 = false;
291 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
292 MCInst const *ID = ISJ->getDesc();
294 if (!ISJ->Core.getUnits()) {
295 // Error if insn may not be executed in any slot.
296 Error = SHUFFLE_ERROR_UNKNOWN;
300 // Exclude from slot #1 any insn but A2_nop.
301 if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop)
303 ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
305 // Exclude from slot #1 any insn but A-type.
306 if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32)
308 ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
310 // Branches must keep the original order.
311 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() ||
312 HexagonMCInstrInfo::getDesc(MCII, *ID).isCall())
314 if (jumpr || slotJump < slotLastJump) {
315 // Error if indirect branch with another branch or
316 // no more slots available for branches.
317 Error = SHUFFLE_ERROR_BRANCHES;
320 // Pin the branch to the highest slot available to it.
321 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);
322 // Update next highest slot available to branches.
326 // A single load must use slot #0.
327 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) {
328 if (loads == 1 && loads == memory)
329 // Pin the load to slot #0.
330 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
333 // A single store must use slot #0.
334 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) {
337 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
338 else if (stores > 1) {
339 if (slotLoadStore < slotLastLoadStore) {
340 // Error if no more slots available for stores.
341 Error = SHUFFLE_ERROR_STORES;
344 // Pin the store to the highest slot available to it.
345 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
346 // Update the next highest slot available to stores.
350 if (store1 && stores > 1) {
351 // Error if a single store with another store.
352 Error = SHUFFLE_ERROR_STORES;
357 // flag if an instruction can only be executed in slot 3
358 if (ISJ->Core.getUnits() == slotThree)
361 if (!ISJ->Core.getUnits()) {
362 // Error if insn may not be executed in any slot.
363 Error = SHUFFLE_ERROR_NOSLOTS;
368 bool validateSlots = true;
369 if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
370 // save off slot mask of instruction marked with A_PREFER_SLOT3
371 // and then pin it to slot #3
372 unsigned saveUnits = slot3ISJ->Core.getUnits();
373 slot3ISJ->Core.setUnits(saveUnits & slotThree);
375 HexagonUnitAuction AuctionCore;
376 std::sort(begin(), end(), HexagonInstr::lessCore);
378 // see if things ok with that instruction being pinned to slot #3
380 for (iterator I = begin(); I != end() && bFail != true; ++I)
381 if (!AuctionCore.bid(I->Core.getUnits()))
384 // if yes, great, if not then restore original slot mask
386 validateSlots = false; // all good, no need to re-do auction
388 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
389 MCInst const *ID = ISJ->getDesc();
390 if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID))
391 ISJ->Core.setUnits(saveUnits);
395 // Check if any slot, core, is over-subscribed.
396 // Verify the core slot subscriptions.
398 HexagonUnitAuction AuctionCore;
400 std::sort(begin(), end(), HexagonInstr::lessCore);
402 for (iterator I = begin(); I != end(); ++I)
403 if (!AuctionCore.bid(I->Core.getUnits())) {
404 Error = SHUFFLE_ERROR_SLOTS;
408 // Verify the CVI slot subscriptions.
410 HexagonUnitAuction AuctionCVI;
412 std::sort(begin(), end(), HexagonInstr::lessCVI);
414 for (iterator I = begin(); I != end(); ++I)
415 for (unsigned i = 0; i < I->CVI.getLanes(); ++i) // TODO: I->CVI.isValid?
416 if (!AuctionCVI.bid(I->CVI.getUnits() << i)) {
417 Error = SHUFFLE_ERROR_SLOTS;
422 Error = SHUFFLE_SUCCESS;
426 bool HexagonShuffler::shuffle() {
427 if (size() > HEXAGON_PACKET_SIZE) {
428 // Ignore a packet with with more than what a packet can hold
429 // or with compound or duplex insns for now.
430 Error = SHUFFLE_ERROR_INVALID;
434 // Check and prepare packet.
435 if (size() > 1 && check())
436 // Reorder the handles for each slot.
437 for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;
440 unsigned slotSkip, slotWeight;
442 // Prioritize the handles considering their restrictions.
443 for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
444 ISK != Packet.end(); ++ISK, ++slotSkip)
445 if (slotSkip < nSlot - emptySlots)
446 // Note which handle to begin at.
449 // Calculate the weight of the slot.
450 slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);
453 // Sort the packet, favoring source order,
454 // beginning after the previous slot.
455 std::sort(ISJ, Packet.end());
461 for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
462 DEBUG(dbgs().write_hex(ISJ->Core.getUnits());
464 << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())
467 DEBUG(dbgs() << '\n');
469 return (!getError());