HexagonMCShuffler.cpp revision 309124
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      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
204bool 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