1 //===----- HexagonMCShuffler.cpp - MC bundle shuffling --------------------===//
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 #define DEBUG_TYPE "hexagon-shuffle"
16 #include "MCTargetDesc/HexagonMCShuffler.h"
17 #include "MCTargetDesc/HexagonMCInstrInfo.h"
18 #include "MCTargetDesc/HexagonShuffler.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrDesc.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/Debug.h"
24 #include "llvm/Support/raw_ostream.h"
30 DisableShuffle("disable-hexagon-shuffle", cl::Hidden
, cl::init(false),
31 cl::desc("Disable Hexagon instruction shuffling"));
33 void HexagonMCShuffler::init(MCInst
&MCB
) {
34 if (HexagonMCInstrInfo::isBundle(MCB
)) {
35 MCInst
const *Extender
= nullptr;
36 // Copy the bundle for the shuffling.
37 for (const auto &I
: HexagonMCInstrInfo::bundleInstructions(MCB
)) {
38 MCInst
&MI
= *const_cast<MCInst
*>(I
.getInst());
39 LLVM_DEBUG(dbgs() << "Shuffling: " << MCII
.getName(MI
.getOpcode())
41 assert(!HexagonMCInstrInfo::getDesc(MCII
, MI
).isPseudo());
43 if (!HexagonMCInstrInfo::isImmext(MI
)) {
44 append(MI
, Extender
, HexagonMCInstrInfo::getUnits(MCII
, STI
, MI
));
52 BundleFlags
= MCB
.getOperand(0).getImm();
55 void HexagonMCShuffler::init(MCInst
&MCB
, MCInst
const &AddMI
,
56 bool bInsertAtFront
) {
57 if (HexagonMCInstrInfo::isBundle(MCB
)) {
59 append(AddMI
, nullptr, HexagonMCInstrInfo::getUnits(MCII
, STI
, AddMI
));
60 MCInst
const *Extender
= nullptr;
61 // Copy the bundle for the shuffling.
62 for (auto const &I
: HexagonMCInstrInfo::bundleInstructions(MCB
)) {
63 assert(!HexagonMCInstrInfo::getDesc(MCII
, *I
.getInst()).isPseudo());
64 MCInst
&MI
= *const_cast<MCInst
*>(I
.getInst());
65 if (!HexagonMCInstrInfo::isImmext(MI
)) {
66 append(MI
, Extender
, HexagonMCInstrInfo::getUnits(MCII
, STI
, MI
));
72 append(AddMI
, nullptr, HexagonMCInstrInfo::getUnits(MCII
, STI
, AddMI
));
76 BundleFlags
= MCB
.getOperand(0).getImm();
79 void HexagonMCShuffler::copyTo(MCInst
&MCB
) {
81 MCB
.addOperand(MCOperand::createImm(BundleFlags
));
83 // Copy the results into the bundle.
84 for (HexagonShuffler::iterator I
= begin(); I
!= end(); ++I
) {
86 MCInst
const &MI
= I
->getDesc();
87 MCInst
const *Extender
= I
->getExtender();
89 MCB
.addOperand(MCOperand::createInst(Extender
));
90 MCB
.addOperand(MCOperand::createInst(&MI
));
94 bool HexagonMCShuffler::reshuffleTo(MCInst
&MCB
) {
96 // Copy the results into the bundle.
100 LLVM_DEBUG(MCB
.dump());
104 bool llvm::HexagonMCShuffle(MCContext
&Context
, bool Fatal
,
105 MCInstrInfo
const &MCII
, MCSubtargetInfo
const &STI
,
107 HexagonMCShuffler
MCS(Context
, Fatal
, MCII
, STI
, MCB
);
110 // Ignore if user chose so.
113 if (!HexagonMCInstrInfo::bundleSize(MCB
)) {
114 // There once was a bundle:
115 // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
116 // implicit-def %d7, ...
117 // * %d2 = IMPLICIT_DEF; flags:
118 // * %d7 = IMPLICIT_DEF; flags:
119 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
121 LLVM_DEBUG(dbgs() << "Skipping empty bundle");
123 } else if (!HexagonMCInstrInfo::isBundle(MCB
)) {
124 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");
128 return MCS
.reshuffleTo(MCB
);
132 llvm::HexagonMCShuffle(MCContext
&Context
, MCInstrInfo
const &MCII
,
133 MCSubtargetInfo
const &STI
, MCInst
&MCB
,
134 SmallVector
<DuplexCandidate
, 8> possibleDuplexes
) {
138 if (!HexagonMCInstrInfo::bundleSize(MCB
)) {
139 // There once was a bundle:
140 // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
141 // implicit-def %d7, ...
142 // * %d2 = IMPLICIT_DEF; flags:
143 // * %d7 = IMPLICIT_DEF; flags:
144 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
146 LLVM_DEBUG(dbgs() << "Skipping empty bundle");
148 } else if (!HexagonMCInstrInfo::isBundle(MCB
)) {
149 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");
153 bool doneShuffling
= false;
154 while (possibleDuplexes
.size() > 0 && (!doneShuffling
)) {
155 // case of Duplex Found
156 DuplexCandidate duplexToTry
= possibleDuplexes
.pop_back_val();
158 HexagonMCInstrInfo::replaceDuplex(Context
, Attempt
, duplexToTry
);
159 HexagonMCShuffler
MCS(Context
, false, MCII
, STI
, Attempt
); // copy packet to the shuffler
160 if (MCS
.size() == 1) { // case of one duplex
161 // copy the created duplex in the shuffler to the bundle
165 // try shuffle with this duplex
166 doneShuffling
= MCS
.reshuffleTo(MCB
);
172 if (!doneShuffling
) {
173 HexagonMCShuffler
MCS(Context
, false, MCII
, STI
, MCB
);
174 doneShuffling
= MCS
.reshuffleTo(MCB
); // shuffle
182 bool llvm::HexagonMCShuffle(MCContext
&Context
, MCInstrInfo
const &MCII
,
183 MCSubtargetInfo
const &STI
, MCInst
&MCB
,
184 MCInst
const &AddMI
, int fixupCount
) {
185 if (!HexagonMCInstrInfo::isBundle(MCB
))
188 // if fixups present, make sure we don't insert too many nops that would
189 // later prevent an extender from being inserted.
190 unsigned int bundleSize
= HexagonMCInstrInfo::bundleSize(MCB
);
191 if (bundleSize
>= HEXAGON_PACKET_SIZE
)
193 bool bhasDuplex
= HexagonMCInstrInfo::hasDuplex(MCII
, MCB
);
194 if (fixupCount
>= 2) {
196 if (bundleSize
>= HEXAGON_PACKET_SIZE
- 1) {
203 if (bundleSize
== HEXAGON_PACKET_SIZE
- 1 && fixupCount
)
210 // mgl: temporary code (shuffler doesn't take into account the fact that
211 // a duplex takes up two slots. for example, 3 nops can be put into a packet
212 // containing a duplex oversubscribing slots by 1).
213 unsigned maxBundleSize
= (HexagonMCInstrInfo::hasImmExt(MCB
))
214 ? HEXAGON_PACKET_SIZE
215 : HEXAGON_PACKET_SIZE
- 1;
216 if (bhasDuplex
&& bundleSize
>= maxBundleSize
)
219 HexagonMCShuffler
MCS(Context
, false, MCII
, STI
, MCB
, AddMI
, false);
220 return MCS
.reshuffleTo(MCB
);