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 | #include "MCTargetDesc/HexagonMCShuffler.h" |
15 | #include "MCTargetDesc/HexagonMCInstrInfo.h" |
16 | #include "MCTargetDesc/HexagonShuffler.h" |
17 | #include "llvm/MC/MCInst.h" |
18 | #include "llvm/MC/MCInstrDesc.h" |
19 | #include "llvm/MC/MCInstrInfo.h" |
20 | #include "llvm/Support/CommandLine.h" |
21 | #include "llvm/Support/Debug.h" |
22 | #include "llvm/Support/raw_ostream.h" |
23 | #include <cassert> |
24 | |
25 | #define DEBUG_TYPE "hexagon-shuffle" |
26 | |
27 | using namespace llvm; |
28 | |
29 | static cl::opt<bool> |
30 | DisableShuffle("disable-hexagon-shuffle" , cl::Hidden, cl::init(Val: false), |
31 | cl::desc("Disable Hexagon instruction shuffling" )); |
32 | |
33 | void HexagonMCShuffler::init(MCInst &MCB) { |
34 | if (HexagonMCInstrInfo::isBundle(MCI: MCB)) { |
35 | MCInst const *Extender = nullptr; |
36 | // Copy the bundle for the shuffling. |
37 | for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI: 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(MCI: MI)) { |
44 | append(ID: MI, Extender, S: HexagonMCInstrInfo::getUnits(MCII, STI, MCI: MI)); |
45 | Extender = nullptr; |
46 | } else |
47 | Extender = &MI; |
48 | } |
49 | } |
50 | |
51 | Loc = MCB.getLoc(); |
52 | BundleFlags = MCB.getOperand(i: 0).getImm(); |
53 | } |
54 | |
55 | void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI, |
56 | bool bInsertAtFront) { |
57 | if (HexagonMCInstrInfo::isBundle(MCI: MCB)) { |
58 | if (bInsertAtFront) |
59 | append(ID: AddMI, Extender: nullptr, S: HexagonMCInstrInfo::getUnits(MCII, STI, MCI: AddMI)); |
60 | MCInst const *Extender = nullptr; |
61 | // Copy the bundle for the shuffling. |
62 | for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCI: MCB)) { |
63 | assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo()); |
64 | MCInst &MI = *const_cast<MCInst *>(I.getInst()); |
65 | if (!HexagonMCInstrInfo::isImmext(MCI: MI)) { |
66 | append(ID: MI, Extender, S: HexagonMCInstrInfo::getUnits(MCII, STI, MCI: MI)); |
67 | Extender = nullptr; |
68 | } else |
69 | Extender = &MI; |
70 | } |
71 | if (!bInsertAtFront) |
72 | append(ID: AddMI, Extender: nullptr, S: HexagonMCInstrInfo::getUnits(MCII, STI, MCI: AddMI)); |
73 | } |
74 | |
75 | Loc = MCB.getLoc(); |
76 | BundleFlags = MCB.getOperand(i: 0).getImm(); |
77 | } |
78 | |
79 | void HexagonMCShuffler::copyTo(MCInst &MCB) { |
80 | MCB.clear(); |
81 | MCB.addOperand(Op: MCOperand::createImm(Val: BundleFlags)); |
82 | MCB.setLoc(Loc); |
83 | // Copy the results into the bundle. |
84 | for (auto &I : *this) { |
85 | MCInst const &MI = I.getDesc(); |
86 | MCInst const *Extender = I.getExtender(); |
87 | if (Extender) |
88 | MCB.addOperand(Op: MCOperand::createInst(Val: Extender)); |
89 | MCB.addOperand(Op: MCOperand::createInst(Val: &MI)); |
90 | } |
91 | } |
92 | |
93 | bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) { |
94 | if (shuffle()) { |
95 | // Copy the results into the bundle. |
96 | copyTo(MCB); |
97 | return true; |
98 | } |
99 | LLVM_DEBUG(MCB.dump()); |
100 | return false; |
101 | } |
102 | |
103 | bool llvm::HexagonMCShuffle(MCContext &Context, bool ReportErrors, |
104 | MCInstrInfo const &MCII, MCSubtargetInfo const &STI, |
105 | MCInst &MCB) { |
106 | HexagonMCShuffler MCS(Context, ReportErrors, MCII, STI, MCB); |
107 | |
108 | if (DisableShuffle) |
109 | // Ignore if user chose so. |
110 | return false; |
111 | |
112 | if (!HexagonMCInstrInfo::bundleSize(MCI: MCB)) { |
113 | // There once was a bundle: |
114 | // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5, |
115 | // implicit-def %d7, ... |
116 | // * %d2 = IMPLICIT_DEF; flags: |
117 | // * %d7 = IMPLICIT_DEF; flags: |
118 | // After the IMPLICIT_DEFs were removed by the asm printer, the bundle |
119 | // became empty. |
120 | LLVM_DEBUG(dbgs() << "Skipping empty bundle" ); |
121 | return false; |
122 | } else if (!HexagonMCInstrInfo::isBundle(MCI: MCB)) { |
123 | LLVM_DEBUG(dbgs() << "Skipping stand-alone insn" ); |
124 | return false; |
125 | } |
126 | |
127 | return MCS.reshuffleTo(MCB); |
128 | } |
129 | |
130 | bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII, |
131 | MCSubtargetInfo const &STI, MCInst &MCB, |
132 | SmallVector<DuplexCandidate, 8> possibleDuplexes) { |
133 | |
134 | if (DisableShuffle || possibleDuplexes.size() == 0) |
135 | return false; |
136 | |
137 | if (!HexagonMCInstrInfo::bundleSize(MCI: MCB)) { |
138 | // There once was a bundle: |
139 | // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5, |
140 | // implicit-def %d7, ... |
141 | // * %d2 = IMPLICIT_DEF; flags: |
142 | // * %d7 = IMPLICIT_DEF; flags: |
143 | // After the IMPLICIT_DEFs were removed by the asm printer, the bundle |
144 | // became empty. |
145 | LLVM_DEBUG(dbgs() << "Skipping empty bundle" ); |
146 | return false; |
147 | } else if (!HexagonMCInstrInfo::isBundle(MCI: MCB)) { |
148 | LLVM_DEBUG(dbgs() << "Skipping stand-alone insn" ); |
149 | return false; |
150 | } |
151 | |
152 | bool doneShuffling = false; |
153 | while (possibleDuplexes.size() > 0 && (!doneShuffling)) { |
154 | // case of Duplex Found |
155 | DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val(); |
156 | MCInst Attempt(MCB); |
157 | HexagonMCInstrInfo::replaceDuplex(Context, MCI&: Attempt, Candidate: duplexToTry); |
158 | HexagonMCShuffler MCS(Context, false, MCII, STI, Attempt); // copy packet to the shuffler |
159 | if (MCS.size() == 1) { // case of one duplex |
160 | // copy the created duplex in the shuffler to the bundle |
161 | MCS.copyTo(MCB); |
162 | return false; |
163 | } |
164 | // try shuffle with this duplex |
165 | doneShuffling = MCS.reshuffleTo(MCB); |
166 | |
167 | if (doneShuffling) |
168 | break; |
169 | } |
170 | |
171 | if (!doneShuffling) { |
172 | HexagonMCShuffler MCS(Context, false, MCII, STI, MCB); |
173 | doneShuffling = MCS.reshuffleTo(MCB); // shuffle |
174 | } |
175 | |
176 | return doneShuffling; |
177 | } |
178 | |
179 | bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII, |
180 | MCSubtargetInfo const &STI, MCInst &MCB, |
181 | MCInst const &AddMI, int fixupCount) { |
182 | if (!HexagonMCInstrInfo::isBundle(MCI: MCB)) |
183 | return false; |
184 | |
185 | // if fixups present, make sure we don't insert too many nops that would |
186 | // later prevent an extender from being inserted. |
187 | unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCI: MCB); |
188 | if (bundleSize >= HEXAGON_PACKET_SIZE) |
189 | return false; |
190 | bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, MCI: MCB); |
191 | if (fixupCount >= 2) { |
192 | if (bhasDuplex) { |
193 | if (bundleSize >= HEXAGON_PACKET_SIZE - 1) { |
194 | return false; |
195 | } |
196 | } else { |
197 | return false; |
198 | } |
199 | } else { |
200 | if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount) |
201 | return false; |
202 | } |
203 | |
204 | if (DisableShuffle) |
205 | return false; |
206 | |
207 | // mgl: temporary code (shuffler doesn't take into account the fact that |
208 | // a duplex takes up two slots. for example, 3 nops can be put into a packet |
209 | // containing a duplex oversubscribing slots by 1). |
210 | unsigned maxBundleSize = (HexagonMCInstrInfo::hasImmExt(MCI: MCB)) |
211 | ? HEXAGON_PACKET_SIZE |
212 | : HEXAGON_PACKET_SIZE - 1; |
213 | if (bhasDuplex && bundleSize >= maxBundleSize) |
214 | return false; |
215 | |
216 | HexagonMCShuffler MCS(Context, false, MCII, STI, MCB, AddMI, false); |
217 | return MCS.reshuffleTo(MCB); |
218 | } |
219 | |