xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp (revision dd41de95a84d979615a2ef11df6850622bf6184e)
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 
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 
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 
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 
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 
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
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 
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