1//===----- HexagonShuffler.h - 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#ifndef HEXAGONSHUFFLER_H
16#define HEXAGONSHUFFLER_H
17
18#include "Hexagon.h"
19#include "MCTargetDesc/HexagonMCInstrInfo.h"
20
21#include "llvm/ADT/SmallVector.h"
22#include "llvm/MC/MCInstrInfo.h"
23
24using namespace llvm;
25
26namespace llvm {
27// Insn resources.
28class HexagonResource {
29  // Mask of the slots or units that may execute the insn and
30  // the weight or priority that the insn requires to be assigned a slot.
31  unsigned Slots, Weight;
32
33public:
34  HexagonResource(unsigned s) { setUnits(s); };
35
36  void setUnits(unsigned s) {
37    Slots = s & ~(~0U << HEXAGON_PACKET_SIZE);
38  };
39  unsigned setWeight(unsigned s);
40
41  unsigned getUnits() const { return (Slots); };
42  unsigned getWeight() const { return (Weight); };
43
44  // Check if the resources are in ascending slot order.
45  static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
46    return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
47  };
48  // Check if the resources are in ascending weight order.
49  static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
50    return (A.getWeight() < B.getWeight());
51  };
52};
53
54// HVX insn resources.
55class HexagonCVIResource : public HexagonResource {
56  typedef std::pair<unsigned, unsigned> UnitsAndLanes;
57  typedef llvm::DenseMap<unsigned, UnitsAndLanes> TypeUnitsAndLanes;
58
59  // Available HVX slots.
60  enum {
61    CVI_NONE = 0,
62    CVI_XLANE = 1 << 0,
63    CVI_SHIFT = 1 << 1,
64    CVI_MPY0 = 1 << 2,
65    CVI_MPY1 = 1 << 3
66  };
67
68  static bool SetUp;
69  static bool setup();
70  static TypeUnitsAndLanes *TUL;
71
72  // Count of adjacent slots that the insn requires to be executed.
73  unsigned Lanes;
74  // Flag whether the insn is a load or a store.
75  bool Load, Store;
76  // Flag whether the HVX resources are valid.
77  bool Valid;
78
79  void setLanes(unsigned l) { Lanes = l; };
80  void setLoad(bool f = true) { Load = f; };
81  void setStore(bool f = true) { Store = f; };
82
83public:
84  HexagonCVIResource(MCInstrInfo const &MCII, unsigned s, MCInst const *id);
85
86  bool isValid() const { return (Valid); };
87  unsigned getLanes() const { return (Lanes); };
88  bool mayLoad() const { return (Load); };
89  bool mayStore() const { return (Store); };
90};
91
92// Handle to an insn used by the shuffling algorithm.
93class HexagonInstr {
94  friend class HexagonShuffler;
95
96  MCInst const *ID;
97  MCInst const *Extender;
98  HexagonResource Core;
99  HexagonCVIResource CVI;
100  bool SoloException;
101
102public:
103  HexagonInstr(MCInstrInfo const &MCII, MCInst const *id,
104               MCInst const *Extender, unsigned s, bool x = false)
105      : ID(id), Extender(Extender), Core(s), CVI(MCII, s, id),
106        SoloException(x){};
107
108  MCInst const *getDesc() const { return (ID); };
109
110  MCInst const *getExtender() const { return Extender; }
111
112  unsigned isSoloException() const { return (SoloException); };
113
114  // Check if the handles are in ascending order for shuffling purposes.
115  bool operator<(const HexagonInstr &B) const {
116    return (HexagonResource::lessWeight(B.Core, Core));
117  };
118  // Check if the handles are in ascending order by core slots.
119  static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
120    return (HexagonResource::lessUnits(A.Core, B.Core));
121  };
122  // Check if the handles are in ascending order by HVX slots.
123  static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
124    return (HexagonResource::lessUnits(A.CVI, B.CVI));
125  };
126};
127
128// Bundle shuffler.
129class HexagonShuffler {
130  typedef SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>
131      HexagonPacket;
132
133  // Insn handles in a bundle.
134  HexagonPacket Packet;
135
136  // Shuffling error code.
137  unsigned Error;
138
139protected:
140  int64_t BundleFlags;
141  MCInstrInfo const &MCII;
142  MCSubtargetInfo const &STI;
143
144public:
145  typedef HexagonPacket::iterator iterator;
146
147  enum {
148    SHUFFLE_SUCCESS = 0,    ///< Successful operation.
149    SHUFFLE_ERROR_INVALID,  ///< Invalid bundle.
150    SHUFFLE_ERROR_STORES,   ///< No free slots for store insns.
151    SHUFFLE_ERROR_LOADS,    ///< No free slots for load insns.
152    SHUFFLE_ERROR_BRANCHES, ///< No free slots for branch insns.
153    SHUFFLE_ERROR_NOSLOTS,  ///< No free slots for other insns.
154    SHUFFLE_ERROR_SLOTS,    ///< Over-subscribed slots.
155    SHUFFLE_ERROR_ERRATA2, ///< Errata violation (v60).
156    SHUFFLE_ERROR_STORE_LOAD_CONFLICT, ///< store/load conflict
157    SHUFFLE_ERROR_UNKNOWN   ///< Unknown error.
158  };
159
160  explicit HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
161
162  // Reset to initial state.
163  void reset();
164  // Check if the bundle may be validly shuffled.
165  bool check();
166  // Reorder the insn handles in the bundle.
167  bool shuffle();
168
169  unsigned size() const { return (Packet.size()); };
170
171  iterator begin() { return (Packet.begin()); };
172  iterator end() { return (Packet.end()); };
173
174  // Add insn handle to the bundle .
175  void append(MCInst const *ID, MCInst const *Extender, unsigned S,
176              bool X = false);
177
178  // Return the error code for the last check or shuffling of the bundle.
179  void setError(unsigned Err) { Error = Err; };
180  unsigned getError() const { return (Error); };
181};
182}
183
184#endif // HEXAGONSHUFFLER_H
185