LLVM  4.0.0
HexagonShuffler.cpp
Go to the documentation of this file.
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"
23 #include "HexagonShuffler.h"
24 #include "llvm/Support/Debug.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()))
95  return (Weight);
96 }
97 
99  (*TUL)[HexagonII::TypeCVI_VA] =
100  UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
101  (*TUL)[HexagonII::TypeCVI_VA_DV] = UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2);
102  (*TUL)[HexagonII::TypeCVI_VX] = UnitsAndLanes(CVI_MPY0 | CVI_MPY1, 1);
103  (*TUL)[HexagonII::TypeCVI_VX_DV] = UnitsAndLanes(CVI_MPY0, 2);
104  (*TUL)[HexagonII::TypeCVI_VP] = UnitsAndLanes(CVI_XLANE, 1);
105  (*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2);
106  (*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1);
107  (*TUL)[HexagonII::TypeCVI_VINLANESAT] = UnitsAndLanes(CVI_SHIFT, 1);
108  (*TUL)[HexagonII::TypeCVI_VM_LD] =
109  UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
110  (*TUL)[HexagonII::TypeCVI_VM_TMP_LD] = UnitsAndLanes(CVI_NONE, 0);
112  UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
113  (*TUL)[HexagonII::TypeCVI_VM_VP_LDU] = UnitsAndLanes(CVI_XLANE, 1);
114  (*TUL)[HexagonII::TypeCVI_VM_ST] =
115  UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1);
116  (*TUL)[HexagonII::TypeCVI_VM_NEW_ST] = UnitsAndLanes(CVI_NONE, 0);
117  (*TUL)[HexagonII::TypeCVI_VM_STU] = UnitsAndLanes(CVI_XLANE, 1);
118  (*TUL)[HexagonII::TypeCVI_HIST] = UnitsAndLanes(CVI_XLANE, 4);
119 }
120 
122  MCInstrInfo const &MCII, unsigned s,
123  MCInst const *id)
124  : HexagonResource(s), TUL(TUL) {
125  unsigned T = HexagonMCInstrInfo::getType(MCII, *id);
126 
127  if (TUL->count(T)) {
128  // For an HVX insn.
129  Valid = true;
130  setUnits((*TUL)[T].first);
131  setLanes((*TUL)[T].second);
132  setLoad(HexagonMCInstrInfo::getDesc(MCII, *id).mayLoad());
133  setStore(HexagonMCInstrInfo::getDesc(MCII, *id).mayStore());
134  } else {
135  // For core insns.
136  Valid = false;
137  setUnits(0);
138  setLanes(0);
139  setLoad(false);
140  setStore(false);
141  }
142 }
143 
145  MCSubtargetInfo const &STI)
146  : MCII(MCII), STI(STI) {
147  reset();
149 }
150 
152  Packet.clear();
153  BundleFlags = 0;
155 }
156 
157 void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender,
158  unsigned S, bool X) {
159  HexagonInstr PI(&TUL, MCII, ID, Extender, S, X);
160 
161  Packet.push_back(PI);
162 }
163 
164 /// Check that the packet is legal and enforce relative insn order.
166  // Descriptive slot masks.
167  const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2,
168  slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4,
169  slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1;
170  // Highest slots for branches and stores used to keep their original order.
171  unsigned slotJump = slotFirstJump;
172  unsigned slotLoadStore = slotFirstLoadStore;
173  // Number of branches, solo branches, indirect branches.
174  unsigned jumps = 0, jump1 = 0;
175  // Number of memory operations, loads, solo loads, stores, solo stores, single
176  // stores.
177  unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0;
178  // Number of HVX loads, HVX stores.
179  unsigned CVIloads = 0, CVIstores = 0;
180  // Number of duplex insns, solo insns.
181  unsigned duplex = 0, solo = 0;
182  // Number of insns restricting other insns in the packet to A and X types,
183  // which is neither A or X types.
184  unsigned onlyAX = 0, neitherAnorX = 0;
185  // Number of insns restricting other insns in slot #1 to A type.
186  unsigned onlyAin1 = 0;
187  // Number of insns restricting any insn in slot #1, except A2_nop.
188  unsigned onlyNo1 = 0;
189  unsigned xtypeFloat = 0;
190  unsigned pSlot3Cnt = 0;
191  iterator slot3ISJ = end();
192 
193  // Collect information from the insns in the packet.
194  for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
195  MCInst const *ID = ISJ->getDesc();
196 
198  solo += !ISJ->isSoloException();
199  else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID))
200  onlyAX += !ISJ->isSoloException();
201  else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID))
202  onlyAin1 += !ISJ->isSoloException();
205  ++neitherAnorX;
207  ++pSlot3Cnt;
208  slot3ISJ = ISJ;
209  }
211  ++jump1;
212 
213  switch (HexagonMCInstrInfo::getType(MCII, *ID)) {
216  ++xtypeFloat;
217  break;
218  case HexagonII::TypeJR:
219  case HexagonII::TypeJ:
220  ++jumps;
221  break;
223  ++onlyNo1;
227  ++CVIloads;
228  case HexagonII::TypeLD:
229  ++loads;
230  ++memory;
231  if (ISJ->Core.getUnits() == slotSingleLoad)
232  ++load0;
234  ++jumps, ++jump1; // DEALLOC_RETURN is of type LD.
235  break;
237  ++onlyNo1;
240  ++CVIstores;
241  case HexagonII::TypeST:
242  ++stores;
243  ++memory;
244  if (ISJ->Core.getUnits() == slotSingleStore)
245  ++store0;
246  break;
248  ++loads;
249  ++stores;
250  ++store1;
251  ++memory;
252  break;
253  case HexagonII::TypeNV:
254  ++memory; // NV insns are memory-like.
256  ++jumps, ++jump1;
257  break;
258  case HexagonII::TypeCR:
259  // Legacy conditional branch predicated on a register.
262  ++loads;
263  break;
264  }
265  }
266 
267  // Check if the packet is legal.
268  if ((load0 > 1 || store0 > 1 || CVIloads > 1 || CVIstores > 1) ||
269  (duplex > 1 || (duplex && memory)) || (solo && size() > 1) ||
270  (onlyAX && neitherAnorX > 1) || (onlyAX && xtypeFloat)) {
272  return false;
273  }
274 
275  if (jump1 && jumps > 1) {
276  // Error if single branch with another branch.
278  return false;
279  }
280 
281  // Modify packet accordingly.
282  // TODO: need to reserve slots #0 and #1 for duplex insns.
283  bool bOnlySlot3 = false;
284  for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
285  MCInst const *ID = ISJ->getDesc();
286 
287  if (!ISJ->Core.getUnits()) {
288  // Error if insn may not be executed in any slot.
290  return false;
291  }
292 
293  // Exclude from slot #1 any insn but A2_nop.
294  if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::A2_nop)
295  if (onlyNo1)
296  ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
297 
298  // Exclude from slot #1 any insn but A-type.
300  if (onlyAin1)
301  ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne);
302 
303  // Branches must keep the original order.
306  if (jumps > 1) {
307  if (slotJump < slotLastJump) {
308  // Error if indirect branch with another branch or
309  // no more slots available for branches.
311  return false;
312  }
313  // Pin the branch to the highest slot available to it.
314  ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump);
315  // Update next highest slot available to branches.
316  slotJump >>= 1;
317  }
318 
319  // A single load must use slot #0.
321  if (loads == 1 && loads == memory)
322  // Pin the load to slot #0.
323  ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad);
324  }
325 
326  // A single store must use slot #0.
328  if (!store0) {
329  if (stores == 1)
330  ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore);
331  else if (stores > 1) {
332  if (slotLoadStore < slotLastLoadStore) {
333  // Error if no more slots available for stores.
335  return false;
336  }
337  // Pin the store to the highest slot available to it.
338  ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore);
339  // Update the next highest slot available to stores.
340  slotLoadStore >>= 1;
341  }
342  }
343  if (store1 && stores > 1) {
344  // Error if a single store with another store.
346  return false;
347  }
348  }
349 
350  // flag if an instruction can only be executed in slot 3
351  if (ISJ->Core.getUnits() == slotThree)
352  bOnlySlot3 = true;
353 
354  if (!ISJ->Core.getUnits()) {
355  // Error if insn may not be executed in any slot.
357  return false;
358  }
359  }
360 
361  bool validateSlots = true;
362  if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) {
363  // save off slot mask of instruction marked with A_PREFER_SLOT3
364  // and then pin it to slot #3
365  unsigned saveUnits = slot3ISJ->Core.getUnits();
366  slot3ISJ->Core.setUnits(saveUnits & slotThree);
367 
368  HexagonUnitAuction AuctionCore;
369  std::sort(begin(), end(), HexagonInstr::lessCore);
370 
371  // see if things ok with that instruction being pinned to slot #3
372  bool bFail = false;
373  for (iterator I = begin(); I != end() && bFail != true; ++I)
374  if (!AuctionCore.bid(I->Core.getUnits()))
375  bFail = true;
376 
377  // if yes, great, if not then restore original slot mask
378  if (!bFail)
379  validateSlots = false; // all good, no need to re-do auction
380  else
381  for (iterator ISJ = begin(); ISJ != end(); ++ISJ) {
382  MCInst const *ID = ISJ->getDesc();
384  ISJ->Core.setUnits(saveUnits);
385  }
386  }
387 
388  // Check if any slot, core, is over-subscribed.
389  // Verify the core slot subscriptions.
390  if (validateSlots) {
391  HexagonUnitAuction AuctionCore;
392 
393  std::sort(begin(), end(), HexagonInstr::lessCore);
394 
395  for (iterator I = begin(); I != end(); ++I)
396  if (!AuctionCore.bid(I->Core.getUnits())) {
398  return false;
399  }
400  }
401  // Verify the CVI slot subscriptions.
402  {
403  HexagonUnitAuction AuctionCVI;
404 
405  std::sort(begin(), end(), HexagonInstr::lessCVI);
406 
407  for (iterator I = begin(); I != end(); ++I)
408  for (unsigned i = 0; i < I->CVI.getLanes(); ++i) // TODO: I->CVI.isValid?
409  if (!AuctionCVI.bid(I->CVI.getUnits() << i)) {
411  return false;
412  }
413  }
414 
416  return true;
417 }
418 
420  if (size() > HEXAGON_PACKET_SIZE) {
421  // Ignore a packet with with more than what a packet can hold
422  // or with compound or duplex insns for now.
424  return false;
425  }
426 
427  // Check and prepare packet.
428  if (size() > 1 && check())
429  // Reorder the handles for each slot.
430  for (unsigned nSlot = 0, emptySlots = 0; nSlot < HEXAGON_PACKET_SIZE;
431  ++nSlot) {
432  iterator ISJ, ISK;
433  unsigned slotSkip, slotWeight;
434 
435  // Prioritize the handles considering their restrictions.
436  for (ISJ = ISK = Packet.begin(), slotSkip = slotWeight = 0;
437  ISK != Packet.end(); ++ISK, ++slotSkip)
438  if (slotSkip < nSlot - emptySlots)
439  // Note which handle to begin at.
440  ++ISJ;
441  else
442  // Calculate the weight of the slot.
443  slotWeight += ISK->Core.setWeight(HEXAGON_PACKET_SIZE - nSlot - 1);
444 
445  if (slotWeight)
446  // Sort the packet, favoring source order,
447  // beginning after the previous slot.
448  std::sort(ISJ, Packet.end());
449  else
450  // Skip unused slot.
451  ++emptySlots;
452  }
453 
454  for (iterator ISJ = begin(); ISJ != end(); ++ISJ)
455  DEBUG(dbgs().write_hex(ISJ->Core.getUnits());
456  dbgs() << ':'
457  << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc())
458  .getOpcode();
459  dbgs() << '\n');
460  DEBUG(dbgs() << '\n');
461 
462  return (!getError());
463 }
bool isSoloAin1(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether the insn can be packaged only with an A-type insn in slot #1.
std::string & operator+=(std::string &buffer, StringRef string)
Definition: StringRef.h:888
void push_back(const T &Elt)
Definition: SmallVector.h:211
static bool lessCore(const HexagonInstr &A, const HexagonInstr &B)
void setUnits(unsigned s)
size_t i
unsigned getError() const
bool isReturn() const
Return true if the instruction is a return.
Definition: MCInstrDesc.h:236
bool mayStore() const
Return true if this instruction could possibly modify memory.
Definition: MCInstrDesc.h:384
bool isSolo(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned setWeight(unsigned s)
No free slots for store insns.
#define HEXAGON_PACKET_SIZE
Definition: Hexagon.h:33
bool isBranch() const
Returns true if this is a conditional, unconditional, or indirect branch.
Definition: MCInstrDesc.h:261
bool isCall() const
Return true if the instruction is a call.
Definition: MCInstrDesc.h:242
bool isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI)
StringRef getCPU() const
getCPU - Return the CPU string.
HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI)
unsigned getUnits() const
No free slots for branch insns.
raw_ostream & write_hex(unsigned long long N)
Output N in hexadecimal, without any prefix or padding.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:150
HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII, unsigned s, MCInst const *id)
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB=ZB_Width)
Count number of 0's from the least significant bit to the most stopping at the first 1...
Definition: MathExtras.h:111
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:115
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:24
unsigned size() const
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned getOpcode() const
Return the opcode number for this descriptor.
Definition: MCInstrDesc.h:203
void append(MCInst const *ID, MCInst const *Extender, unsigned S, bool X=false)
unsigned countPopulation(T Value)
Count the number of set bits in a value.
Definition: MathExtras.h:494
MCInstrInfo const & MCII
bool mayLoad() const
Return true if this instruction could possibly read memory.
Definition: MCInstrDesc.h:378
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
size_type count(const KeyT &Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:122
bool isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether the insn can be packaged only with A and X-type insns.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:119
#define I(x, y, z)
Definition: MD5.cpp:54
MCSubtargetInfo - Generic base class for all target subtargets.
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isFloat(MCInstrInfo const &MCII, MCInst const &MCI)
Return whether it is a floating-point insn.
Lightweight error class with error context and mandatory checking.
std::pair< unsigned, unsigned > UnitsAndLanes
#define DEBUG(X)
Definition: Debug.h:100
static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI)
static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU)
hexagon widen stores
bool check()
Check that the packet is legal and enforce relative insn order.