LLVM 20.0.0git
HexagonMCShuffler.cpp
Go to the documentation of this file.
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
17#include "llvm/MC/MCInst.h"
18#include "llvm/MC/MCInstrDesc.h"
19#include "llvm/MC/MCInstrInfo.h"
21#include "llvm/Support/Debug.h"
23#include <cassert>
24
25#define DEBUG_TYPE "hexagon-shuffle"
26
27using namespace llvm;
28
29static cl::opt<bool>
30 DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),
31 cl::desc("Disable Hexagon instruction shuffling"));
32
33void HexagonMCShuffler::init(MCInst &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');
42
45 Extender = nullptr;
46 } else
47 Extender = &MI;
48 }
49 }
50
51 Loc = MCB.getLoc();
52 BundleFlags = MCB.getOperand(0).getImm();
53}
54
55void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI,
56 bool bInsertAtFront) {
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)) {
64 MCInst &MI = *const_cast<MCInst *>(I.getInst());
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
80 MCB.clear();
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(MCOperand::createInst(Extender));
90 }
91}
92
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
103bool 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
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(MCB)) {
123 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");
124 return false;
125 }
126
127 return MCS.reshuffleTo(MCB);
128}
129
131 MCSubtargetInfo const &STI, MCInst &MCB,
132 SmallVector<DuplexCandidate, 8> possibleDuplexes) {
133
134 if (DisableShuffle || possibleDuplexes.size() == 0)
135 return false;
136
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(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, Attempt, 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
180 MCSubtargetInfo const &STI, MCInst &MCB,
181 MCInst const &AddMI, int fixupCount) {
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(MCB);
188 if (bundleSize >= HEXAGON_PACKET_SIZE)
189 return false;
190 bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, 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(MCB))
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}
#define LLVM_DEBUG(X)
Definition: Debug.h:101
static cl::opt< bool > DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false), cl::desc("Disable Hexagon instruction shuffling"))
#define HEXAGON_PACKET_SIZE
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool reshuffleTo(MCInst &MCB)
unsigned size() const
MCSubtargetInfo const & STI
void append(MCInst const &ID, MCInst const *Extender, unsigned S)
MCInstrInfo const & MCII
Context object for machine code objects.
Definition: MCContext.h:83
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
SMLoc getLoc() const
Definition: MCInst.h:204
void setLoc(SMLoc loc)
Definition: MCInst.h:203
void dump() const
Definition: MCInst.cpp:107
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void clear()
Definition: MCInst.h:215
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
bool isPseudo() const
Return true if this is a pseudo instruction that doesn't correspond to a real machine instruction.
Definition: MCInstrDesc.h:269
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
Definition: MCInstrInfo.h:70
int64_t getImm() const
Definition: MCInst.h:80
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
static MCOperand createInst(const MCInst *Val)
Definition: MCInst.h:169
Generic base class for all target subtargets.
size_t size() const
Definition: SmallVector.h:91
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
size_t bundleSize(MCInst const &MCI)
MCInstrDesc const & getDesc(MCInstrInfo const &MCII, MCInst const &MCI)
iterator_range< Hexagon::PacketIterator > bundleInstructions(MCInstrInfo const &MCII, MCInst const &MCI)
bool isBundle(MCInst const &MCI)
bool hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI)
unsigned getUnits(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst const &MCI)
Return the slots used by the insn.
bool isImmext(MCInst const &MCI)
bool hasImmExt(MCInst const &MCI)
void replaceDuplex(MCContext &Context, MCInst &MCI, DuplexCandidate Candidate)
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool HexagonMCShuffle(MCContext &Context, bool ReportErrors, MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst &MCB)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163