1 //===----- HexagonMCShuffler.cpp - MC bundle shuffling --------------------===//
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 #define DEBUG_TYPE "hexagon-shuffle"
15
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"
25 #include <cassert>
26
27 using namespace llvm;
28
29 static cl::opt<bool>
30 DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),
31 cl::desc("Disable Hexagon instruction shuffling"));
32
init(MCInst & MCB)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())
40 << '\n');
41 assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo());
42
43 if (!HexagonMCInstrInfo::isImmext(MI)) {
44 append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));
45 Extender = nullptr;
46 } else
47 Extender = &MI;
48 }
49 }
50
51 Loc = MCB.getLoc();
52 BundleFlags = MCB.getOperand(0).getImm();
53 }
54
init(MCInst & MCB,MCInst const & AddMI,bool bInsertAtFront)55 void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI,
56 bool bInsertAtFront) {
57 if (HexagonMCInstrInfo::isBundle(MCB)) {
58 if (bInsertAtFront)
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));
67 Extender = nullptr;
68 } else
69 Extender = &MI;
70 }
71 if (!bInsertAtFront)
72 append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
73 }
74
75 Loc = MCB.getLoc();
76 BundleFlags = MCB.getOperand(0).getImm();
77 }
78
copyTo(MCInst & MCB)79 void HexagonMCShuffler::copyTo(MCInst &MCB) {
80 MCB.clear();
81 MCB.addOperand(MCOperand::createImm(BundleFlags));
82 MCB.setLoc(Loc);
83 // Copy the results into the bundle.
84 for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {
85
86 MCInst const &MI = I->getDesc();
87 MCInst const *Extender = I->getExtender();
88 if (Extender)
89 MCB.addOperand(MCOperand::createInst(Extender));
90 MCB.addOperand(MCOperand::createInst(&MI));
91 }
92 }
93
reshuffleTo(MCInst & MCB)94 bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
95 if (shuffle()) {
96 // Copy the results into the bundle.
97 copyTo(MCB);
98 return true;
99 }
100 LLVM_DEBUG(MCB.dump());
101 return false;
102 }
103
HexagonMCShuffle(MCContext & Context,bool Fatal,MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB)104 bool llvm::HexagonMCShuffle(MCContext &Context, bool Fatal,
105 MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
106 MCInst &MCB) {
107 HexagonMCShuffler MCS(Context, Fatal, MCII, STI, MCB);
108
109 if (DisableShuffle)
110 // Ignore if user chose so.
111 return false;
112
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
120 // became empty.
121 LLVM_DEBUG(dbgs() << "Skipping empty bundle");
122 return false;
123 } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
124 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");
125 return false;
126 }
127
128 return MCS.reshuffleTo(MCB);
129 }
130
131 bool
HexagonMCShuffle(MCContext & Context,MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB,SmallVector<DuplexCandidate,8> possibleDuplexes)132 llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
133 MCSubtargetInfo const &STI, MCInst &MCB,
134 SmallVector<DuplexCandidate, 8> possibleDuplexes) {
135 if (DisableShuffle)
136 return false;
137
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
145 // became empty.
146 LLVM_DEBUG(dbgs() << "Skipping empty bundle");
147 return false;
148 } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
149 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");
150 return false;
151 }
152
153 bool doneShuffling = false;
154 while (possibleDuplexes.size() > 0 && (!doneShuffling)) {
155 // case of Duplex Found
156 DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();
157 MCInst Attempt(MCB);
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
162 MCS.copyTo(MCB);
163 return false;
164 }
165 // try shuffle with this duplex
166 doneShuffling = MCS.reshuffleTo(MCB);
167
168 if (doneShuffling)
169 break;
170 }
171
172 if (!doneShuffling) {
173 HexagonMCShuffler MCS(Context, false, MCII, STI, MCB);
174 doneShuffling = MCS.reshuffleTo(MCB); // shuffle
175 }
176 if (!doneShuffling)
177 return true;
178
179 return false;
180 }
181
HexagonMCShuffle(MCContext & Context,MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB,MCInst const & AddMI,int fixupCount)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))
186 return false;
187
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)
192 return false;
193 bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, MCB);
194 if (fixupCount >= 2) {
195 if (bhasDuplex) {
196 if (bundleSize >= HEXAGON_PACKET_SIZE - 1) {
197 return false;
198 }
199 } else {
200 return false;
201 }
202 } else {
203 if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
204 return false;
205 }
206
207 if (DisableShuffle)
208 return false;
209
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)
217 return false;
218
219 HexagonMCShuffler MCS(Context, false, MCII, STI, MCB, AddMI, false);
220 return MCS.reshuffleTo(MCB);
221 }
222