HexagonMCShuffler.cpp revision 353358
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
27using namespace llvm;
28
29static cl::opt<bool>
30    DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),
31                   cl::desc("Disable Hexagon instruction shuffling"));
32
33void 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
55void 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
79void 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
94bool 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
104bool 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
131bool
132llvm::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
182bool 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