1//===- HexagonShuffler.h - Instruction bundle shuffling ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This implements the shuffling of insns inside a bundle according to the
10// packet formation rules of the Hexagon ISA.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
15#define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
16
17#include "MCTargetDesc/HexagonMCInstrInfo.h"
18#include "MCTargetDesc/HexagonMCTargetDesc.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/SmallVector.h"
21#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/MathExtras.h"
23#include "llvm/Support/SMLoc.h"
24#include <cstdint>
25#include <utility>
26
27namespace llvm {
28
29class MCContext;
30class MCInst;
31class MCInstrInfo;
32class MCSubtargetInfo;
33
34// Insn resources.
35class HexagonResource {
36  // Mask of the slots or units that may execute the insn and
37  // the weight or priority that the insn requires to be assigned a slot.
38  unsigned Slots, Weight;
39
40public:
41  HexagonResource(unsigned s) { setUnits(s); }
42
43  void setUnits(unsigned s) {
44    Slots = s & ((1u << HEXAGON_PACKET_SIZE) - 1);
45    setWeight(s);
46  }
47
48  unsigned setWeight(unsigned s);
49
50  unsigned getUnits() const { return (Slots); }
51  unsigned getWeight() const { return (Weight); }
52
53  // Check if the resources are in ascending slot order.
54  static bool lessUnits(const HexagonResource &A, const HexagonResource &B) {
55    return (countPopulation(A.getUnits()) < countPopulation(B.getUnits()));
56  }
57
58  // Check if the resources are in ascending weight order.
59  static bool lessWeight(const HexagonResource &A, const HexagonResource &B) {
60    return (A.getWeight() < B.getWeight());
61  }
62};
63
64// HVX insn resources.
65class HexagonCVIResource : public HexagonResource {
66public:
67  using UnitsAndLanes = std::pair<unsigned, unsigned>;
68  using TypeUnitsAndLanes = DenseMap<unsigned, UnitsAndLanes>;
69
70private:
71  // Available HVX slots.
72  enum {
73    CVI_NONE = 0,
74    CVI_XLANE = 1 << 0,
75    CVI_SHIFT = 1 << 1,
76    CVI_MPY0 = 1 << 2,
77    CVI_MPY1 = 1 << 3,
78    CVI_ZW = 1 << 4
79  };
80
81  // Count of adjacent slots that the insn requires to be executed.
82  unsigned Lanes;
83  // Flag whether the insn is a load or a store.
84  bool Load, Store;
85  // Flag whether the HVX resources are valid.
86  bool Valid;
87
88  void setLanes(unsigned l) { Lanes = l; }
89  void setLoad(bool f = true) { Load = f; }
90  void setStore(bool f = true) { Store = f; }
91
92public:
93  HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII,
94                     unsigned s, MCInst const *id);
95
96  static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU);
97
98  bool isValid() const { return Valid; }
99  unsigned getLanes() const { return Lanes; }
100  bool mayLoad() const { return Load; }
101  bool mayStore() const { return Store; }
102};
103
104// Handle to an insn used by the shuffling algorithm.
105class HexagonInstr {
106  friend class HexagonShuffler;
107
108  MCInst const *ID;
109  MCInst const *Extender;
110  HexagonResource Core;
111  HexagonCVIResource CVI;
112
113public:
114  HexagonInstr(HexagonCVIResource::TypeUnitsAndLanes *T,
115               MCInstrInfo const &MCII, MCInst const *id,
116               MCInst const *Extender, unsigned s)
117      : ID(id), Extender(Extender), Core(s), CVI(T, MCII, s, id) {}
118
119  MCInst const &getDesc() const { return *ID; }
120  MCInst const *getExtender() const { return Extender; }
121
122  // Check if the handles are in ascending order for shuffling purposes.
123  bool operator<(const HexagonInstr &B) const {
124    return (HexagonResource::lessWeight(B.Core, Core));
125  }
126
127  // Check if the handles are in ascending order by core slots.
128  static bool lessCore(const HexagonInstr &A, const HexagonInstr &B) {
129    return (HexagonResource::lessUnits(A.Core, B.Core));
130  }
131
132  // Check if the handles are in ascending order by HVX slots.
133  static bool lessCVI(const HexagonInstr &A, const HexagonInstr &B) {
134    return (HexagonResource::lessUnits(A.CVI, B.CVI));
135  }
136};
137
138// Bundle shuffler.
139class HexagonShuffler {
140  using HexagonPacket =
141      SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>;
142
143  // Insn handles in a bundle.
144  HexagonPacket Packet;
145  HexagonPacket PacketSave;
146
147  HexagonCVIResource::TypeUnitsAndLanes TUL;
148
149protected:
150  MCContext &Context;
151  int64_t BundleFlags;
152  MCInstrInfo const &MCII;
153  MCSubtargetInfo const &STI;
154  SMLoc Loc;
155  bool ReportErrors;
156  std::vector<std::pair<SMLoc, std::string>> AppliedRestrictions;
157  void applySlotRestrictions();
158  void restrictSlot1AOK();
159  void restrictNoSlot1Store();
160
161public:
162  using iterator = HexagonPacket::iterator;
163
164  HexagonShuffler(MCContext &Context, bool ReportErrors,
165                  MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
166
167  // Reset to initial state.
168  void reset();
169  // Check if the bundle may be validly shuffled.
170  bool check();
171  // Reorder the insn handles in the bundle.
172  bool shuffle();
173
174  unsigned size() const { return (Packet.size()); }
175
176  bool isMemReorderDisabled() const {
177    return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0;
178  }
179
180  iterator begin() { return (Packet.begin()); }
181  iterator end() { return (Packet.end()); }
182
183  // Add insn handle to the bundle .
184  void append(MCInst const &ID, MCInst const *Extender, unsigned S);
185
186  // Return the error code for the last check or shuffling of the bundle.
187  void reportError(Twine const &Msg);
188};
189
190} // end namespace llvm
191
192#endif //  LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
193