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