Coverage Report

Created: 2026-01-14 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp
Line
Count
Source
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/Debug.h"
22
#include "llvm/Support/raw_ostream.h"
23
24
using namespace llvm_ks;
25
26
static bool DisableShuffle = false;
27
28
16.5k
void HexagonMCShuffler::init(MCInst &MCB) {
29
16.5k
  if (HexagonMCInstrInfo::isBundle(MCB)) {
30
16.5k
    MCInst const *Extender = nullptr;
31
    // Copy the bundle for the shuffling.
32
28.5k
    for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
33
28.5k
      assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
34
28.5k
      MCInst *MI = const_cast<MCInst *>(I.getInst());
35
36
28.5k
      if (!HexagonMCInstrInfo::isImmext(*MI)) {
37
21.7k
        append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
38
21.7k
               false);
39
21.7k
        Extender = nullptr;
40
21.7k
      } else
41
6.82k
        Extender = MI;
42
28.5k
    }
43
16.5k
  }
44
45
16.5k
  BundleFlags = MCB.getOperand(0).getImm();
46
16.5k
}
47
48
void HexagonMCShuffler::init(MCInst &MCB, MCInst const *AddMI,
49
0
                             bool bInsertAtFront) {
50
0
  if (HexagonMCInstrInfo::isBundle(MCB)) {
51
0
    if (bInsertAtFront && AddMI)
52
0
      append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
53
0
             false);
54
0
    MCInst const *Extender = nullptr;
55
    // Copy the bundle for the shuffling.
56
0
    for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
57
0
      assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
58
0
      MCInst *MI = const_cast<MCInst *>(I.getInst());
59
0
      if (!HexagonMCInstrInfo::isImmext(*MI)) {
60
0
        append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, *MI),
61
0
               false);
62
0
        Extender = nullptr;
63
0
      } else
64
0
        Extender = MI;
65
0
    }
66
0
    if (!bInsertAtFront && AddMI)
67
0
      append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, *AddMI),
68
0
             false);
69
0
  }
70
71
0
  BundleFlags = MCB.getOperand(0).getImm();
72
0
}
73
74
9.37k
void HexagonMCShuffler::copyTo(MCInst &MCB) {
75
9.37k
  MCB.clear();
76
9.37k
  MCB.addOperand(MCOperand::createImm(BundleFlags));
77
  // Copy the results into the bundle.
78
18.7k
  for (HexagonShuffler::iterator I = begin(); I != end(); ++I) {
79
80
9.41k
    MCInst const *MI = I->getDesc();
81
9.41k
    MCInst const *Extender = I->getExtender();
82
9.41k
    if (Extender)
83
1.14k
      MCB.addOperand(MCOperand::createInst(Extender));
84
9.41k
    MCB.addOperand(MCOperand::createInst(MI));
85
9.41k
  }
86
9.37k
}
87
88
9.36k
bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
89
9.36k
  if (shuffle()) {
90
    // Copy the results into the bundle.
91
9.36k
    copyTo(MCB);
92
9.36k
  }
93
  //  else
94
  //    DEBUG(MCB.dump());
95
96
9.36k
  return (!getError());
97
9.36k
}
98
99
bool llvm_ks::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
100
6.32k
                            MCInst &MCB) {
101
6.32k
  HexagonMCShuffler MCS(MCII, STI, MCB);
102
103
6.32k
  if (DisableShuffle)
104
    // Ignore if user chose so.
105
0
    return false;
106
107
6.32k
  if (!HexagonMCInstrInfo::bundleSize(MCB)) {
108
    // There once was a bundle:
109
    //    BUNDLE %D2<imp-def>, %R4<imp-def>, %R5<imp-def>, %D7<imp-def>, ...
110
    //      * %D2<def> = IMPLICIT_DEF; flags:
111
    //      * %D7<def> = IMPLICIT_DEF; flags:
112
    // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
113
    // became empty.
114
80
    DEBUG(dbgs() << "Skipping empty bundle");
115
80
    return false;
116
6.24k
  } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
117
0
    DEBUG(dbgs() << "Skipping stand-alone insn");
118
0
    return false;
119
0
  }
120
121
  // Reorder the bundle and copy the result.
122
6.24k
  if (!MCS.reshuffleTo(MCB)) {
123
    // Unless there is any error, which should not happen at this point.
124
0
    unsigned shuffleError = MCS.getError();
125
0
    switch (shuffleError) {
126
0
    default:
127
0
      llvm_unreachable("unknown error");
128
0
    case HexagonShuffler::SHUFFLE_ERROR_INVALID:
129
0
      llvm_unreachable("invalid packet");
130
0
    case HexagonShuffler::SHUFFLE_ERROR_STORES:
131
0
      llvm_unreachable("too many stores");
132
0
    case HexagonShuffler::SHUFFLE_ERROR_LOADS:
133
0
      llvm_unreachable("too many loads");
134
0
    case HexagonShuffler::SHUFFLE_ERROR_BRANCHES:
135
0
      llvm_unreachable("too many branches");
136
0
    case HexagonShuffler::SHUFFLE_ERROR_NOSLOTS:
137
0
      llvm_unreachable("no suitable slot");
138
0
    case HexagonShuffler::SHUFFLE_ERROR_SLOTS:
139
0
      llvm_unreachable("over-subscribed slots");
140
0
    case HexagonShuffler::SHUFFLE_SUCCESS: // Single instruction case.
141
0
      return true;
142
0
    }
143
0
  }
144
145
6.24k
  return true;
146
6.24k
}
147
148
unsigned
149
llvm_ks::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
150
                       MCContext &Context, MCInst &MCB,
151
3.16k
                       SmallVector<DuplexCandidate, 8> possibleDuplexes) {
152
153
3.16k
  if (DisableShuffle)
154
0
    return HexagonShuffler::SHUFFLE_SUCCESS;
155
156
3.16k
  if (!HexagonMCInstrInfo::bundleSize(MCB)) {
157
    // There once was a bundle:
158
    //    BUNDLE %D2<imp-def>, %R4<imp-def>, %R5<imp-def>, %D7<imp-def>, ...
159
    //      * %D2<def> = IMPLICIT_DEF; flags:
160
    //      * %D7<def> = IMPLICIT_DEF; flags:
161
    // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
162
    // became empty.
163
40
    DEBUG(dbgs() << "Skipping empty bundle");
164
40
    return HexagonShuffler::SHUFFLE_SUCCESS;
165
3.12k
  } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
166
0
    DEBUG(dbgs() << "Skipping stand-alone insn");
167
0
    return HexagonShuffler::SHUFFLE_SUCCESS;
168
0
  }
169
170
3.12k
  bool doneShuffling = false;
171
3.12k
  unsigned shuffleError;
172
3.12k
  while (possibleDuplexes.size() > 0 && (!doneShuffling)) {
173
    // case of Duplex Found
174
9
    DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();
175
9
    MCInst Attempt(MCB);
176
9
    HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry);
177
9
    HexagonMCShuffler MCS(MCII, STI, Attempt); // copy packet to the shuffler
178
9
    if (MCS.size() == 1) {                     // case of one duplex
179
      // copy the created duplex in the shuffler to the bundle
180
5
      MCS.copyTo(MCB);
181
5
      doneShuffling = true;
182
5
      return HexagonShuffler::SHUFFLE_SUCCESS;
183
5
    }
184
    // try shuffle with this duplex
185
4
    doneShuffling = MCS.reshuffleTo(MCB);
186
4
    shuffleError = MCS.getError();
187
188
4
    if (doneShuffling)
189
4
      break;
190
4
  }
191
192
3.12k
  if (doneShuffling == false) {
193
3.11k
    HexagonMCShuffler MCS(MCII, STI, MCB);
194
3.11k
    doneShuffling = MCS.reshuffleTo(MCB); // shuffle
195
3.11k
    shuffleError = MCS.getError();
196
3.11k
  }
197
3.12k
  if (!doneShuffling)
198
0
    return shuffleError;
199
200
3.12k
  return HexagonShuffler::SHUFFLE_SUCCESS;
201
3.12k
}
202
203
bool llvm_ks::HexagonMCShuffle(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
204
0
                            MCInst &MCB, MCInst const *AddMI, int fixupCount) {
205
0
  if (!HexagonMCInstrInfo::isBundle(MCB) || !AddMI)
206
0
    return false;
207
208
  // if fixups present, make sure we don't insert too many nops that would
209
  // later prevent an extender from being inserted.
210
0
  unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);
211
0
  if (bundleSize >= HEXAGON_PACKET_SIZE)
212
0
    return false;
213
0
  if (fixupCount >= 2) {
214
0
    return false;
215
0
  } else {
216
0
    if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
217
0
      return false;
218
0
  }
219
220
0
  if (DisableShuffle)
221
0
    return false;
222
223
0
  HexagonMCShuffler MCS(MCII, STI, MCB, AddMI);
224
0
  if (!MCS.reshuffleTo(MCB)) {
225
0
    unsigned shuffleError = MCS.getError();
226
0
    switch (shuffleError) {
227
0
    default:
228
0
      return false;
229
0
    case HexagonShuffler::SHUFFLE_SUCCESS: // single instruction case
230
0
      return true;
231
0
    }
232
0
  }
233
234
0
  return true;
235
0
}