HexagonMCShuffler.cpp revision 288943
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
25using namespace llvm;
26
27static cl::opt<bool>
28    DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),
29                   cl::desc("Disable Hexagon instruction shuffling"));
30
31void 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
51void 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
77void 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
91bool 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
101bool 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
150unsigned
151llvm::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      doneShuffling = true;
184      return HexagonShuffler::SHUFFLE_SUCCESS;
185    }
186    // try shuffle with this duplex
187    doneShuffling = MCS.reshuffleTo(MCB);
188    shuffleError = MCS.getError();
189
190    if (doneShuffling)
191      break;
192  }
193
194  if (doneShuffling == false) {
195    HexagonMCShuffler MCS(MCII, STI, MCB);
196    doneShuffling = MCS.reshuffleTo(MCB); // shuffle
197    shuffleError = MCS.getError();
198  }
199  if (!doneShuffling)
200    return shuffleError;
201
202  return HexagonShuffler::SHUFFLE_SUCCESS;
203}
204
205bool llvm::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
206                            MCInst &MCB, MCInst const *AddMI, int fixupCount) {
207  if (!HexagonMCInstrInfo::isBundle(MCB) || !AddMI)
208    return false;
209
210  // if fixups present, make sure we don't insert too many nops that would
211  // later prevent an extender from being inserted.
212  unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);
213  if (bundleSize >= HEXAGON_PACKET_SIZE)
214    return false;
215  if (fixupCount >= 2) {
216    return false;
217  } else {
218    if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
219      return false;
220  }
221
222  if (DisableShuffle)
223    return false;
224
225  HexagonMCShuffler MCS(MCII, STI, MCB, AddMI);
226  if (!MCS.reshuffleTo(MCB)) {
227    unsigned shuffleError = MCS.getError();
228    switch (shuffleError) {
229    default:
230      return false;
231    case HexagonShuffler::SHUFFLE_SUCCESS: // single instruction case
232      return true;
233    }
234  }
235
236  return true;
237}
238