• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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