1 //===----- HexagonMCShuffler.cpp - MC bundle shuffling --------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This implements the shuffling of insns inside a bundle according to the
11 // packet formation rules of the Hexagon ISA.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #define DEBUG_TYPE "hexagon-shuffle"
16
17 #include "Hexagon.h"
18 #include "MCTargetDesc/HexagonMCInstrInfo.h"
19 #include "MCTargetDesc/HexagonMCShuffler.h"
20 #include "MCTargetDesc/HexagonMCTargetDesc.h"
21 #include "llvm/Support/CommandLine.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/raw_ostream.h"
24
25 using namespace llvm;
26
27 static cl::opt<bool>
28 DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),
29 cl::desc("Disable Hexagon instruction shuffling"));
30
init(MCInst & MCB)31 void HexagonMCShuffler::init(MCInst &MCB) {
32 if (HexagonMCInstrInfo::isBundle(MCB)) {
33 MCInst const *Extender = nullptr;
34 // Copy the bundle for the shuffling.
35 for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
36 assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
37 MCInst *MI = const_cast<MCInst *>(I.getInst());
38
39 if (!HexagonMCInstrInfo::isImmext(*MI)) {
40 append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
41 false);
42 Extender = nullptr;
43 } else
44 Extender = MI;
45 }
46 }
47
48 BundleFlags = MCB.getOperand(0).getImm();
49 }
50
init(MCInst & MCB,MCInst const * AddMI,bool bInsertAtFront)51 void HexagonMCShuffler::init(MCInst &MCB, MCInst const *AddMI,
52 bool bInsertAtFront) {
53 if (HexagonMCInstrInfo::isBundle(MCB)) {
54 if (bInsertAtFront && AddMI)
55 append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
56 false);
57 MCInst const *Extender = nullptr;
58 // Copy the bundle for the shuffling.
59 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
60 assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
61 MCInst *MI = const_cast<MCInst *>(I.getInst());
62 if (!HexagonMCInstrInfo::isImmext(*MI)) {
63 append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
64 false);
65 Extender = nullptr;
66 } else
67 Extender = MI;
68 }
69 if (!bInsertAtFront && AddMI)
70 append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
71 false);
72 }
73
74 BundleFlags = MCB.getOperand(0).getImm();
75 }
76
copyTo(MCInst & MCB)77 void HexagonMCShuffler::copyTo(MCInst &MCB) {
78 MCB.clear();
79 MCB.addOperand(MCOperand::createImm(BundleFlags));
80 // Copy the results into the bundle.
81 for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {
82
83 MCInst const *MI = I->getDesc();
84 MCInst const *Extender = I->getExtender();
85 if (Extender)
86 MCB.addOperand(MCOperand::createInst(Extender));
87 MCB.addOperand(MCOperand::createInst(MI));
88 }
89 }
90
reshuffleTo(MCInst & MCB)91 bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
92 if (shuffle()) {
93 // Copy the results into the bundle.
94 copyTo(MCB);
95 } else
96 DEBUG(MCB.dump());
97
98 return (!getError());
99 }
100
HexagonMCShuffle(MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB)101 bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
102 MCInst &MCB) {
103 HexagonMCShuffler MCS(MCII, STI, MCB);
104
105 if (DisableShuffle)
106 // Ignore if user chose so.
107 return false;
108
109 if (!HexagonMCInstrInfo::bundleSize(MCB)) {
110 // There once was a bundle:
111 // BUNDLE %D2<imp-def>, %R4<imp-def>, %R5<imp-def>, %D7<imp-def>, ...
112 // * %D2<def> = IMPLICIT_DEF; flags:
113 // * %D7<def> = IMPLICIT_DEF; flags:
114 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
115 // became empty.
116 DEBUG(dbgs() << "Skipping empty bundle");
117 return false;
118 } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
119 DEBUG(dbgs() << "Skipping stand-alone insn");
120 return false;
121 }
122
123 // Reorder the bundle and copy the result.
124 if (!MCS.reshuffleTo(MCB)) {
125 // Unless there is any error, which should not happen at this point.
126 unsigned shuffleError = MCS.getError();
127 switch (shuffleError) {
128 default:
129 llvm_unreachable("unknown error");
130 case HexagonShuffler::SHUFFLE_ERROR_INVALID:
131 llvm_unreachable("invalid packet");
132 case HexagonShuffler::SHUFFLE_ERROR_STORES:
133 llvm_unreachable("too many stores");
134 case HexagonShuffler::SHUFFLE_ERROR_LOADS:
135 llvm_unreachable("too many loads");
136 case HexagonShuffler::SHUFFLE_ERROR_BRANCHES:
137 llvm_unreachable("too many branches");
138 case HexagonShuffler::SHUFFLE_ERROR_NOSLOTS:
139 llvm_unreachable("no suitable slot");
140 case HexagonShuffler::SHUFFLE_ERROR_SLOTS:
141 llvm_unreachable("over-subscribed slots");
142 case HexagonShuffler::SHUFFLE_SUCCESS: // Single instruction case.
143 return true;
144 }
145 }
146
147 return true;
148 }
149
150 unsigned
HexagonMCShuffle(MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCContext & Context,MCInst & MCB,SmallVector<DuplexCandidate,8> possibleDuplexes)151 llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
152 MCContext &Context, MCInst &MCB,
153 SmallVector<DuplexCandidate, 8> possibleDuplexes) {
154
155 if (DisableShuffle)
156 return HexagonShuffler::SHUFFLE_SUCCESS;
157
158 if (!HexagonMCInstrInfo::bundleSize(MCB)) {
159 // There once was a bundle:
160 // BUNDLE %D2<imp-def>, %R4<imp-def>, %R5<imp-def>, %D7<imp-def>, ...
161 // * %D2<def> = IMPLICIT_DEF; flags:
162 // * %D7<def> = IMPLICIT_DEF; flags:
163 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
164 // became empty.
165 DEBUG(dbgs() << "Skipping empty bundle");
166 return HexagonShuffler::SHUFFLE_SUCCESS;
167 } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
168 DEBUG(dbgs() << "Skipping stand-alone insn");
169 return HexagonShuffler::SHUFFLE_SUCCESS;
170 }
171
172 bool doneShuffling = false;
173 unsigned shuffleError;
174 while (possibleDuplexes.size() > 0 && (!doneShuffling)) {
175 // case of Duplex Found
176 DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();
177 MCInst Attempt(MCB);
178 HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry);
179 HexagonMCShuffler MCS(MCII, STI, Attempt); // copy packet to the shuffler
180 if (MCS.size() == 1) { // case of one duplex
181 // copy the created duplex in the shuffler to the bundle
182 MCS.copyTo(MCB);
183 return HexagonShuffler::SHUFFLE_SUCCESS;
184 }
185 // try shuffle with this duplex
186 doneShuffling = MCS.reshuffleTo(MCB);
187 shuffleError = MCS.getError();
188
189 if (doneShuffling)
190 break;
191 }
192
193 if (doneShuffling == false) {
194 HexagonMCShuffler MCS(MCII, STI, MCB);
195 doneShuffling = MCS.reshuffleTo(MCB); // shuffle
196 shuffleError = MCS.getError();
197 }
198 if (!doneShuffling)
199 return shuffleError;
200
201 return HexagonShuffler::SHUFFLE_SUCCESS;
202 }
203
HexagonMCShuffle(MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB,MCInst const * AddMI,int fixupCount)204 bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
205 MCInst &MCB, MCInst const *AddMI, int fixupCount) {
206 if (!HexagonMCInstrInfo::isBundle(MCB) || !AddMI)
207 return false;
208
209 // if fixups present, make sure we don't insert too many nops that would
210 // later prevent an extender from being inserted.
211 unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);
212 if (bundleSize >= HEXAGON_PACKET_SIZE)
213 return false;
214 if (fixupCount >= 2) {
215 return false;
216 } else {
217 if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
218 return false;
219 }
220
221 if (DisableShuffle)
222 return false;
223
224 HexagonMCShuffler MCS(MCII, STI, MCB, AddMI);
225 if (!MCS.reshuffleTo(MCB)) {
226 unsigned shuffleError = MCS.getError();
227 switch (shuffleError) {
228 default:
229 return false;
230 case HexagonShuffler::SHUFFLE_SUCCESS: // single instruction case
231 return true;
232 }
233 }
234
235 return true;
236 }
237