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"
30 // Insn shuffling priority.
32 // The priority is directly proportional to how restricted the insn is based
33 // on its flexibility to run on the available slots. So, the fewer slots it
34 // may run on, the higher its priority.
35 enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15.
39 HexagonBid() : Bid(0){};
40 HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; };
42 // Check if the insn priority is overflowed.
43 bool isSold() const { return (Bid >= MAX); };
45 HexagonBid &operator+=(const HexagonBid &B) {
51 // Slot shuffling allocation.
52 class HexagonUnitAuction {
53 HexagonBid Scores[HEXAGON_PACKET_SIZE];
54 // Mask indicating which slot is unavailable.
55 unsigned isSold : HEXAGON_PACKET_SIZE;
58 HexagonUnitAuction() : isSold(0){};
61 bool bid(unsigned B) {
62 // Exclude already auctioned slots from the bid.
63 unsigned b = B & ~isSold;
65 for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i)
67 // Request candidate slots.
68 Scores[i] += HexagonBid(b);
69 isSold |= Scores[i].isSold() << i;
74 // Error if the desired slots are already full.
79 unsigned HexagonResource::setWeight(unsigned s) {
80 const unsigned SlotWeight = 8;
81 const unsigned MaskWeight = SlotWeight - 1;
82 bool Key = (1 << s) & getUnits();
84 // Calculate relative weight of the insn for the given slot, weighing it the
85 // heavier the more restrictive the insn is and the lowest the slots that the
86 // insn may be executed in.
88 (Key << (SlotWeight * s)) * ((MaskWeight - countPopulation(getUnits()))
89 << countTrailingZeros(getUnits()));
93 HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
94 MCSubtargetInfo const &STI)
95 : MCII(MCII), STI(STI) {
99 void HexagonShuffler::reset() {
102 Error = SHUFFLE_SUCCESS;
105 void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,
106 unsigned S, bool X) {
107 HexagonInstr PI(ID, Extender, S, X);
109 Packet.push_back(PI);
112 /// Check that the packet is legal and enforce relative insn order.
113 bool HexagonShuffler::check() {
114 // Descriptive slot masks.
115 const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
116 slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4,
117 slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
118 // Highest slots for branches and stores used to keep their original order.
119 unsigned slotJump = slotFirstJump;
120 unsigned slotLoadStore = slotFirstLoadStore;
121 // Number of branches, solo branches, indirect branches.
122 unsigned jumps = 0, jump1 = 0, jumpr = 0;
123 // Number of memory operations, loads, solo loads, stores, solo stores, single
125 unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
126 // Number of duplex insns, solo insns.
127 unsigned duplex = 0, solo = 0;
128 // Number of insns restricting other insns in the packet to A and X types,
129 // which is neither A or X types.
130 unsigned onlyAX = 0, neitherAnorX = 0;
131 // Number of insns restricting other insns in slot #1 to A type.
132 unsigned onlyAin1 = 0;
133 // Number of insns restricting any insn in slot #1, except A2_nop.
134 unsigned onlyNo1 = 0;
135 unsigned xtypeFloat = 0;
136 unsigned pSlot3Cnt = 0;
137 iterator slot3ISJ = end();
139 // Collect information from the insns in the packet.
140 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
141 MCInst const *ID = ISJ->getDesc();
143 if (HexagonMCInstrInfo::isSolo(MCII, *ID))
144 solo += !ISJ->isSoloException();
145 else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))
146 onlyAX += !ISJ->isSoloException();
147 else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))
148 onlyAin1 += !ISJ->isSoloException();
149 if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 &&
150 HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE)
152 if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) {
157 switch (HexagonMCInstrInfo::getType(MCII, *ID)) {
158 case HexagonII::TypeXTYPE:
159 if (HexagonMCInstrInfo::isFloat(MCII, *ID))
162 case HexagonII::TypeJR:
165 case HexagonII::TypeJ:
168 case HexagonII::TypeLD:
171 if (ISJ->Core.getUnits() == slotSingleLoad)
173 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn())
174 ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
176 case HexagonII::TypeST:
179 if (ISJ->Core.getUnits() == slotSingleStore)
182 case HexagonII::TypeMEMOP:
188 case HexagonII::TypeNV:
189 ++memory; // NV insns are memory-like.
190 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch())
193 case HexagonII::TypeCR:
194 // Legacy conditional branch predicated on a register.
195 case HexagonII::TypeSYSTEM:
196 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad())
202 // Check if the packet is legal.
203 if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory)) ||
204 (solo && size() > 1) || (onlyAX && neitherAnorX > 1) ||
205 (onlyAX && xtypeFloat)) {
206 Error = SHUFFLE_ERROR_INVALID;
210 if (jump1 && jumps > 1) {
211 // Error if single branch with another branch.
212 Error = SHUFFLE_ERROR_BRANCHES;
216 // Modify packet accordingly.
217 // TODO: need to reserve slots #0 and #1 for duplex insns.
218 bool bOnlySlot3 = false;
219 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
220 MCInst const *ID = ISJ->getDesc();
222 if (!ISJ->Core.getUnits()) {
223 // Error if insn may not be executed in any slot.
224 Error = SHUFFLE_ERROR_UNKNOWN;
228 // Exclude from slot #1 any insn but A2_nop.
229 if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop)
231 ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
233 // Exclude from slot #1 any insn but A-type.
234 if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32)
236 ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
238 // Branches must keep the original order.
239 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() ||
240 HexagonMCInstrInfo::getDesc(MCII, *ID).isCall())
242 if (jumpr || slotJump < slotLastJump) {
243 // Error if indirect branch with another branch or
244 // no more slots available for branches.
245 Error = SHUFFLE_ERROR_BRANCHES;
248 // Pin the branch to the highest slot available to it.
249 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);
250 // Update next highest slot available to branches.
254 // A single load must use slot #0.
255 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) {
256 if (loads == 1 && loads == memory)
257 // Pin the load to slot #0.
258 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
261 // A single store must use slot #0.
262 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) {
265 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
266 else if (stores > 1) {
267 if (slotLoadStore < slotLastLoadStore) {
268 // Error if no more slots available for stores.
269 Error = SHUFFLE_ERROR_STORES;
272 // Pin the store to the highest slot available to it.
273 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
274 // Update the next highest slot available to stores.
278 if (store1 && stores > 1) {
279 // Error if a single store with another store.
280 Error = SHUFFLE_ERROR_STORES;
285 // flag if an instruction can only be executed in slot 3
286 if (ISJ->Core.getUnits() == slotThree)
289 if (!ISJ->Core.getUnits()) {
290 // Error if insn may not be executed in any slot.
291 Error = SHUFFLE_ERROR_NOSLOTS;
296 bool validateSlots = true;
297 if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
298 // save off slot mask of instruction marked with A_PREFER_SLOT3
299 // and then pin it to slot #3
300 unsigned saveUnits = slot3ISJ->Core.getUnits();
301 slot3ISJ->Core.setUnits(saveUnits & slotThree);
303 HexagonUnitAuction AuctionCore;
304 std::sort(begin(), end(), HexagonInstr::lessCore);
306 // see if things ok with that instruction being pinned to slot #3
308 for (iterator I = begin(); I != end() && bFail != true; ++I)
309 if (!AuctionCore.bid(I->Core.getUnits()))
312 // if yes, great, if not then restore original slot mask
314 validateSlots = false; // all good, no need to re-do auction
316 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
317 MCInst const *ID = ISJ->getDesc();
318 if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID))
319 ISJ->Core.setUnits(saveUnits);
323 // Check if any slot, core, is over-subscribed.
324 // Verify the core slot subscriptions.
326 HexagonUnitAuction AuctionCore;
328 std::sort(begin(), end(), HexagonInstr::lessCore);
330 for (iterator I = begin(); I != end(); ++I)
331 if (!AuctionCore.bid(I->Core.getUnits())) {
332 Error = SHUFFLE_ERROR_SLOTS;
337 Error = SHUFFLE_SUCCESS;
341 bool HexagonShuffler::shuffle() {
342 if (size() > HEXAGON_PACKET_SIZE) {
343 // Ignore a packet with with more than what a packet can hold
344 // or with compound or duplex insns for now.
345 Error = SHUFFLE_ERROR_INVALID;
349 // Check and prepare packet.
350 if (size() > 1 && check())
351 // Reorder the handles for each slot.
352 for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;
355 unsigned slotSkip, slotWeight;
357 // Prioritize the handles considering their restrictions.
358 for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
359 ISK != Packet.end(); ++ISK, ++slotSkip)
360 if (slotSkip < nSlot - emptySlots)
361 // Note which handle to begin at.
364 // Calculate the weight of the slot.
365 slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);
368 // Sort the packet, favoring source order,
369 // beginning after the previous slot.
370 std::sort(ISJ, Packet.end());
376 for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
377 DEBUG(dbgs().write_hex(ISJ->Core.getUnits());
379 << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())
382 DEBUG(dbgs() << '\n');
384 return (!getError());