1 //===- HexagonShuffler.h - Instruction bundle shuffling ---------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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/STLExtras.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"
34 class MCSubtargetInfo
;
37 class HexagonResource
{
38 // Mask of the slots or units that may execute the insn and
39 // the weight or priority that the insn requires to be assigned a slot.
40 unsigned Slots
, Weight
;
43 HexagonResource(unsigned s
) { setUnits(s
); }
45 void setUnits(unsigned s
) {
46 Slots
= s
& ((1u << HEXAGON_PACKET_SIZE
) - 1);
51 setUnits(((1u << HEXAGON_PACKET_SIZE
) - 1));
53 unsigned setWeight(unsigned s
);
55 unsigned getUnits() const { return (Slots
); }
56 unsigned getWeight() const { return (Weight
); }
58 // Check if the resources are in ascending slot order.
59 static bool lessUnits(const HexagonResource
&A
, const HexagonResource
&B
) {
60 return (llvm::popcount(A
.getUnits()) < llvm::popcount(B
.getUnits()));
63 // Check if the resources are in ascending weight order.
64 static bool lessWeight(const HexagonResource
&A
, const HexagonResource
&B
) {
65 return (A
.getWeight() < B
.getWeight());
69 // HVX insn resources.
70 class HexagonCVIResource
: public HexagonResource
{
72 using UnitsAndLanes
= std::pair
<unsigned, unsigned>;
75 // Count of adjacent slots that the insn requires to be executed.
77 // Flag whether the insn is a load or a store.
79 // Flag whether the HVX resources are valid.
82 void setLanes(unsigned l
) { Lanes
= l
; }
83 void setLoad(bool f
= true) { Load
= f
; }
84 void setStore(bool f
= true) { Store
= f
; }
87 HexagonCVIResource(MCInstrInfo
const &MCII
,
88 MCSubtargetInfo
const &STI
,
89 unsigned s
, MCInst
const *id
);
91 bool isValid() const { return Valid
; }
92 unsigned getLanes() const { return Lanes
; }
93 bool mayLoad() const { return Load
; }
94 bool mayStore() const { return Store
; }
97 // Handle to an insn used by the shuffling algorithm.
99 friend class HexagonShuffler
;
102 MCInst
const *Extender
;
103 HexagonResource Core
;
104 HexagonCVIResource CVI
;
107 HexagonInstr(MCInstrInfo
const &MCII
,
108 MCSubtargetInfo
const &STI
, MCInst
const *id
,
109 MCInst
const *Extender
, unsigned s
)
110 : ID(id
), Extender(Extender
), Core(s
), CVI(MCII
, STI
, s
, id
){};
112 MCInst
const &getDesc() const { return *ID
; }
113 MCInst
const *getExtender() const { return Extender
; }
115 // Check if the handles are in ascending order for shuffling purposes.
116 bool operator<(const HexagonInstr
&B
) const {
117 return (HexagonResource::lessWeight(B
.Core
, Core
));
120 // Check if the handles are in ascending order by core slots.
121 static bool lessCore(const HexagonInstr
&A
, const HexagonInstr
&B
) {
122 return (HexagonResource::lessUnits(A
.Core
, B
.Core
));
125 // Check if the handles are in ascending order by HVX slots.
126 static bool lessCVI(const HexagonInstr
&A
, const HexagonInstr
&B
) {
127 return (HexagonResource::lessUnits(A
.CVI
, B
.CVI
));
132 class HexagonShuffler
{
133 using HexagonPacket
=
134 SmallVector
<HexagonInstr
, HEXAGON_PRESHUFFLE_PACKET_SIZE
>;
136 struct HexagonPacketSummary
{
137 // Number of memory operations, loads, solo loads, stores, solo stores,
145 unsigned NonZCVIloads
;
146 unsigned AllCVIloads
;
148 // Number of duplex insns
151 std::optional
<HexagonInstr
*> PrefSlot3Inst
;
153 unsigned ReservedSlotMask
;
154 SmallVector
<HexagonInstr
*, HEXAGON_PRESHUFFLE_PACKET_SIZE
> branchInsts
;
155 std::optional
<SMLoc
> Slot1AOKLoc
;
156 std::optional
<SMLoc
> NoSlot1StoreLoc
;
158 // Insn handles in a bundle.
159 HexagonPacket Packet
;
164 MCInstrInfo
const &MCII
;
165 MCSubtargetInfo
const &STI
;
169 std::vector
<std::pair
<SMLoc
, std::string
>> AppliedRestrictions
;
171 bool applySlotRestrictions(HexagonPacketSummary
const &Summary
,
172 const bool DoShuffle
);
173 void restrictSlot1AOK(HexagonPacketSummary
const &Summary
);
174 void restrictNoSlot1Store(HexagonPacketSummary
const &Summary
);
175 void restrictNoSlot1();
176 bool restrictStoreLoadOrder(HexagonPacketSummary
const &Summary
);
177 void restrictBranchOrder(HexagonPacketSummary
const &Summary
);
178 void restrictPreferSlot3(HexagonPacketSummary
const &Summary
,
179 const bool DoShuffle
);
180 void permitNonSlot();
182 std::optional
<HexagonPacket
> tryAuction(HexagonPacketSummary
const &Summary
);
184 HexagonPacketSummary
GetPacketSummary();
185 bool ValidPacketMemoryOps(HexagonPacketSummary
const &Summary
) const;
186 bool ValidResourceUsage(HexagonPacketSummary
const &Summary
);
189 using iterator
= HexagonPacket::iterator
;
190 using const_iterator
= HexagonPacket::const_iterator
;
191 using packet_range
= iterator_range
<HexagonPacket::iterator
>;
192 using const_packet_range
= iterator_range
<HexagonPacket::const_iterator
>;
194 HexagonShuffler(MCContext
&Context
, bool ReportErrors
,
195 MCInstrInfo
const &MCII
, MCSubtargetInfo
const &STI
);
197 // Reset to initial state.
199 // Check if the bundle may be validly shuffled.
200 bool check(const bool RequireShuffle
= true);
201 // Reorder the insn handles in the bundle.
204 unsigned size() const { return (Packet
.size()); }
206 bool isMemReorderDisabled() const {
207 return (BundleFlags
& HexagonMCInstrInfo::memReorderDisabledMask
) != 0;
210 iterator
begin() { return (Packet
.begin()); }
211 iterator
end() { return (Packet
.end()); }
212 const_iterator
cbegin() const { return (Packet
.begin()); }
213 const_iterator
cend() const { return (Packet
.end()); }
214 packet_range
insts(HexagonPacket
&P
) {
215 return make_range(P
.begin(), P
.end());
217 const_packet_range
insts(HexagonPacket
const &P
) const {
218 return make_range(P
.begin(), P
.end());
220 packet_range
insts() { return make_range(begin(), end()); }
221 const_packet_range
insts() const { return make_range(cbegin(), cend()); }
223 using InstPredicate
= bool (*)(MCInstrInfo
const &, MCInst
const &);
225 bool HasInstWith(InstPredicate Pred
) const {
226 return llvm::any_of(insts(), [&](HexagonInstr
const &I
) {
227 MCInst
const &Inst
= I
.getDesc();
228 return (*Pred
)(MCII
, Inst
);
232 // Add insn handle to the bundle .
233 void append(MCInst
const &ID
, MCInst
const *Extender
, unsigned S
);
235 // Return the error code for the last check or shuffling of the bundle.
236 void reportError(Twine
const &Msg
);
237 void reportResourceError(HexagonPacketSummary
const &Summary
, StringRef Err
);
238 void reportResourceUsage(HexagonPacketSummary
const &Summary
);
241 } // end namespace llvm
243 #endif // LLVM_LIB_TARGET_HEXAGON_MCTARGETDESC_HEXAGONSHUFFLER_H