[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / lib / Target / Hexagon / MCTargetDesc / HexagonShuffler.h
blobbf3bad36dfe55da8a4843e04ec1bbc44e126a656
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.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
15 #define LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H
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>
27 namespace llvm {
29 class MCContext;
30 class MCInst;
31 class MCInstrInfo;
32 class MCSubtargetInfo;
34 // Insn resources.
35 class 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;
40 public:
41 HexagonResource(unsigned s) { setUnits(s); }
43 void setUnits(unsigned s) {
44 Slots = s & ((1u << HEXAGON_PACKET_SIZE) - 1);
45 setWeight(s);
48 unsigned setWeight(unsigned s);
50 unsigned getUnits() const { return (Slots); }
51 unsigned getWeight() const { return (Weight); }
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()));
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());
64 // HVX insn resources.
65 class HexagonCVIResource : public HexagonResource {
66 public:
67 using UnitsAndLanes = std::pair<unsigned, unsigned>;
68 using TypeUnitsAndLanes = DenseMap<unsigned, UnitsAndLanes>;
70 private:
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
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;
88 void setLanes(unsigned l) { Lanes = l; }
89 void setLoad(bool f = true) { Load = f; }
90 void setStore(bool f = true) { Store = f; }
92 public:
93 HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII,
94 unsigned s, MCInst const *id);
96 static void SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU);
98 bool isValid() const { return Valid; }
99 unsigned getLanes() const { return Lanes; }
100 bool mayLoad() const { return Load; }
101 bool mayStore() const { return Store; }
104 // Handle to an insn used by the shuffling algorithm.
105 class HexagonInstr {
106 friend class HexagonShuffler;
108 MCInst const *ID;
109 MCInst const *Extender;
110 HexagonResource Core;
111 HexagonCVIResource CVI;
113 public:
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) {}
119 MCInst const &getDesc() const { return *ID; }
120 MCInst const *getExtender() const { return Extender; }
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));
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));
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));
138 // Bundle shuffler.
139 class HexagonShuffler {
140 using HexagonPacket =
141 SmallVector<HexagonInstr, HEXAGON_PRESHUFFLE_PACKET_SIZE>;
143 // Insn handles in a bundle.
144 HexagonPacket Packet;
145 HexagonPacket PacketSave;
147 HexagonCVIResource::TypeUnitsAndLanes TUL;
149 protected:
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();
161 public:
162 using iterator = HexagonPacket::iterator;
164 HexagonShuffler(MCContext &Context, bool ReportErrors,
165 MCInstrInfo const &MCII, MCSubtargetInfo const &STI);
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();
174 unsigned size() const { return (Packet.size()); }
176 bool isMemReorderDisabled() const {
177 return (BundleFlags & HexagonMCInstrInfo::memReorderDisabledMask) != 0;
180 iterator begin() { return (Packet.begin()); }
181 iterator end() { return (Packet.end()); }
183 // Add insn handle to the bundle .
184 void append(MCInst const &ID, MCInst const *Extender, unsigned S);
186 // Return the error code for the last check or shuffling of the bundle.
187 void reportError(Twine const &Msg);
190 } // end namespace llvm
192 #endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H