blob: 41112ac0b46ee9f4e90cb6da9b881c38eaa67f19 [file] [log] [blame]
Colin LeMahieub23c47b2015-05-31 21:57:09 +00001//===----- HexagonShuffler.cpp - Instruction bundle shuffling -------------===//
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#define DEBUG_TYPE "hexagon-shuffle"
16
17#include <algorithm>
18#include <utility>
19#include "Hexagon.h"
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"
27
28using namespace llvm;
29
30// Insn shuffling priority.
31class HexagonBid {
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.
36 unsigned Bid;
37
38public:
39 HexagonBid() : Bid(0){};
40 HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; };
41
42 // Check if the insn priority is overflowed.
43 bool isSold() const { return (Bid >= MAX); };
44
45 HexagonBid &operator+=(const HexagonBid &B) {
46 Bid += B.Bid;
47 return *this;
48 };
49};
50
51// Slot shuffling allocation.
52class HexagonUnitAuction {
53 HexagonBid Scores[HEXAGON_PACKET_SIZE];
54 // Mask indicating which slot is unavailable.
55 unsigned isSold : HEXAGON_PACKET_SIZE;
56
57public:
58 HexagonUnitAuction() : isSold(0){};
59
60 // Allocate slots.
61 bool bid(unsigned B) {
62 // Exclude already auctioned slots from the bid.
63 unsigned b = B & ~isSold;
64 if (b) {
65 for (unsigned i = 0; i < HEXAGON_PACKET_SIZE; ++i)
66 if (b & (1 << i)) {
67 // Request candidate slots.
68 Scores[i] += HexagonBid(b);
69 isSold |= Scores[i].isSold() << i;
70 }
71 return true;
72 ;
73 } else
74 // Error if the desired slots are already full.
75 return false;
76 };
77};
78
79unsigned HexagonResource::setWeight(unsigned s) {
80 const unsigned SlotWeight = 8;
81 const unsigned MaskWeight = SlotWeight - 1;
82 bool Key = (1 << s) & getUnits();
83
Justin Bogneraa315fb2015-06-24 07:03:07 +000084 // TODO: Improve this API so that we can prevent misuse statically.
85 assert(SlotWeight * s < 32 && "Argument to setWeight too large.");
86
Colin LeMahieub23c47b2015-05-31 21:57:09 +000087 // Calculate relative weight of the insn for the given slot, weighing it the
88 // heavier the more restrictive the insn is and the lowest the slots that the
89 // insn may be executed in.
90 Weight =
91 (Key << (SlotWeight * s)) * ((MaskWeight - countPopulation(getUnits()))
92 << countTrailingZeros(getUnits()));
93 return (Weight);
94}
95
96HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII,
97 MCSubtargetInfo const &STI)
98 : MCII(MCII), STI(STI) {
99 reset();
100}
101
102void HexagonShuffler::reset() {
103 Packet.clear();
104 BundleFlags = 0;
105 Error = SHUFFLE_SUCCESS;
106}
107
108void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,
109 unsigned S, bool X) {
110 HexagonInstr PI(ID, Extender, S, X);
111
112 Packet.push_back(PI);
113}
114
115/// Check that the packet is legal and enforce relative insn order.
116bool HexagonShuffler::check() {
117 // Descriptive slot masks.
118 const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
119 slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4,
120 slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
121 // Highest slots for branches and stores used to keep their original order.
122 unsigned slotJump = slotFirstJump;
123 unsigned slotLoadStore = slotFirstLoadStore;
124 // Number of branches, solo branches, indirect branches.
125 unsigned jumps = 0, jump1 = 0, jumpr = 0;
126 // Number of memory operations, loads, solo loads, stores, solo stores, single
127 // stores.
128 unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
129 // Number of duplex insns, solo insns.
130 unsigned duplex = 0, solo = 0;
131 // Number of insns restricting other insns in the packet to A and X types,
132 // which is neither A or X types.
133 unsigned onlyAX = 0, neitherAnorX = 0;
134 // Number of insns restricting other insns in slot #1 to A type.
135 unsigned onlyAin1 = 0;
136 // Number of insns restricting any insn in slot #1, except A2_nop.
137 unsigned onlyNo1 = 0;
138 unsigned xtypeFloat = 0;
139 unsigned pSlot3Cnt = 0;
140 iterator slot3ISJ = end();
141
142 // Collect information from the insns in the packet.
143 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
144 MCInst const *ID = ISJ->getDesc();
145
146 if (HexagonMCInstrInfo::isSolo(MCII, *ID))
147 solo += !ISJ->isSoloException();
148 else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))
149 onlyAX += !ISJ->isSoloException();
150 else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))
151 onlyAin1 += !ISJ->isSoloException();
152 if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 &&
153 HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE)
154 ++neitherAnorX;
155 if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) {
156 ++pSlot3Cnt;
157 slot3ISJ = ISJ;
158 }
159
160 switch (HexagonMCInstrInfo::getType(MCII, *ID)) {
161 case HexagonII::TypeXTYPE:
162 if (HexagonMCInstrInfo::isFloat(MCII, *ID))
163 ++xtypeFloat;
164 break;
165 case HexagonII::TypeJR:
166 ++jumpr;
167 // Fall-through.
168 case HexagonII::TypeJ:
169 ++jumps;
170 break;
171 case HexagonII::TypeLD:
172 ++loads;
173 ++memory;
174 if (ISJ->Core.getUnits() == slotSingleLoad)
175 ++load0;
176 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn())
177 ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
178 break;
179 case HexagonII::TypeST:
180 ++stores;
181 ++memory;
182 if (ISJ->Core.getUnits() == slotSingleStore)
183 ++store0;
184 break;
185 case HexagonII::TypeMEMOP:
186 ++loads;
187 ++stores;
188 ++store1;
189 ++memory;
190 break;
191 case HexagonII::TypeNV:
192 ++memory; // NV insns are memory-like.
193 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch())
194 ++jumps, ++jump1;
195 break;
196 case HexagonII::TypeCR:
197 // Legacy conditional branch predicated on a register.
198 case HexagonII::TypeSYSTEM:
199 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad())
200 ++loads;
201 break;
202 }
203 }
204
205 // Check if the packet is legal.
206 if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory)) ||
207 (solo && size() > 1) || (onlyAX && neitherAnorX > 1) ||
208 (onlyAX && xtypeFloat)) {
209 Error = SHUFFLE_ERROR_INVALID;
210 return false;
211 }
212
213 if (jump1 && jumps > 1) {
214 // Error if single branch with another branch.
215 Error = SHUFFLE_ERROR_BRANCHES;
216 return false;
217 }
218
219 // Modify packet accordingly.
220 // TODO: need to reserve slots #0 and #1 for duplex insns.
221 bool bOnlySlot3 = false;
222 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
223 MCInst const *ID = ISJ->getDesc();
224
225 if (!ISJ->Core.getUnits()) {
226 // Error if insn may not be executed in any slot.
227 Error = SHUFFLE_ERROR_UNKNOWN;
228 return false;
229 }
230
231 // Exclude from slot #1 any insn but A2_nop.
232 if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop)
233 if (onlyNo1)
234 ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
235
236 // Exclude from slot #1 any insn but A-type.
237 if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32)
238 if (onlyAin1)
239 ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
240
241 // Branches must keep the original order.
242 if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() ||
243 HexagonMCInstrInfo::getDesc(MCII, *ID).isCall())
244 if (jumps > 1) {
245 if (jumpr || slotJump < slotLastJump) {
246 // Error if indirect branch with another branch or
247 // no more slots available for branches.
248 Error = SHUFFLE_ERROR_BRANCHES;
249 return false;
250 }
251 // Pin the branch to the highest slot available to it.
252 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);
253 // Update next highest slot available to branches.
254 slotJump >>= 1;
255 }
256
257 // A single load must use slot #0.
258 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) {
259 if (loads == 1 && loads == memory)
260 // Pin the load to slot #0.
261 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
262 }
263
264 // A single store must use slot #0.
265 if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) {
266 if (!store0) {
267 if (stores == 1)
268 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
269 else if (stores > 1) {
270 if (slotLoadStore < slotLastLoadStore) {
271 // Error if no more slots available for stores.
272 Error = SHUFFLE_ERROR_STORES;
273 return false;
274 }
275 // Pin the store to the highest slot available to it.
276 ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
277 // Update the next highest slot available to stores.
278 slotLoadStore >>= 1;
279 }
280 }
281 if (store1 && stores > 1) {
282 // Error if a single store with another store.
283 Error = SHUFFLE_ERROR_STORES;
284 return false;
285 }
286 }
287
288 // flag if an instruction can only be executed in slot 3
289 if (ISJ->Core.getUnits() == slotThree)
290 bOnlySlot3 = true;
291
292 if (!ISJ->Core.getUnits()) {
293 // Error if insn may not be executed in any slot.
294 Error = SHUFFLE_ERROR_NOSLOTS;
295 return false;
296 }
297 }
298
299 bool validateSlots = true;
300 if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
301 // save off slot mask of instruction marked with A_PREFER_SLOT3
302 // and then pin it to slot #3
303 unsigned saveUnits = slot3ISJ->Core.getUnits();
304 slot3ISJ->Core.setUnits(saveUnits & slotThree);
305
306 HexagonUnitAuction AuctionCore;
307 std::sort(begin(), end(), HexagonInstr::lessCore);
308
309 // see if things ok with that instruction being pinned to slot #3
310 bool bFail = false;
311 for (iterator I = begin(); I != end() && bFail != true; ++I)
312 if (!AuctionCore.bid(I->Core.getUnits()))
313 bFail = true;
314
315 // if yes, great, if not then restore original slot mask
316 if (!bFail)
317 validateSlots = false; // all good, no need to re-do auction
318 else
319 for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
320 MCInst const *ID = ISJ->getDesc();
321 if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID))
322 ISJ->Core.setUnits(saveUnits);
323 }
324 }
325
326 // Check if any slot, core, is over-subscribed.
327 // Verify the core slot subscriptions.
328 if (validateSlots) {
329 HexagonUnitAuction AuctionCore;
330
331 std::sort(begin(), end(), HexagonInstr::lessCore);
332
333 for (iterator I = begin(); I != end(); ++I)
334 if (!AuctionCore.bid(I->Core.getUnits())) {
335 Error = SHUFFLE_ERROR_SLOTS;
336 return false;
337 }
338 }
339
340 Error = SHUFFLE_SUCCESS;
341 return true;
342}
343
344bool HexagonShuffler::shuffle() {
345 if (size() > HEXAGON_PACKET_SIZE) {
346 // Ignore a packet with with more than what a packet can hold
347 // or with compound or duplex insns for now.
348 Error = SHUFFLE_ERROR_INVALID;
349 return false;
350 }
351
352 // Check and prepare packet.
353 if (size() > 1 && check())
354 // Reorder the handles for each slot.
355 for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;
356 ++nSlot) {
357 iterator ISJ, ISK;
358 unsigned slotSkip, slotWeight;
359
360 // Prioritize the handles considering their restrictions.
361 for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
362 ISK != Packet.end(); ++ISK, ++slotSkip)
363 if (slotSkip < nSlot - emptySlots)
364 // Note which handle to begin at.
365 ++ISJ;
366 else
367 // Calculate the weight of the slot.
368 slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);
369
370 if (slotWeight)
371 // Sort the packet, favoring source order,
372 // beginning after the previous slot.
373 std::sort(ISJ, Packet.end());
374 else
375 // Skip unused slot.
376 ++emptySlots;
377 }
378
379 for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
380 DEBUG(dbgs().write_hex(ISJ->Core.getUnits());
381 dbgs() << ':'
382 << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())
383 .getOpcode();
384 dbgs() << '\n');
385 DEBUG(dbgs() << '\n');
386
387 return (!getError());
388}