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