1//=== HexagonMCCompound.cpp - Hexagon Compound checker  -------------------===//
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 file is looks at a packet and tries to form compound insns
10//
11//===----------------------------------------------------------------------===//
12
13#include "MCTargetDesc/HexagonBaseInfo.h"
14#include "MCTargetDesc/HexagonMCInstrInfo.h"
15#include "MCTargetDesc/HexagonMCShuffler.h"
16#include "llvm/MC/MCContext.h"
17#include "llvm/MC/MCInst.h"
18#include "llvm/Support/Debug.h"
19#include "llvm/Support/ErrorHandling.h"
20#include "llvm/Support/raw_ostream.h"
21#include <cassert>
22#include <cstdint>
23
24using namespace llvm;
25using namespace Hexagon;
26
27#define DEBUG_TYPE "hexagon-mccompound"
28
29enum OpcodeIndex {
30  fp0_jump_nt = 0,
31  fp0_jump_t,
32  fp1_jump_nt,
33  fp1_jump_t,
34  tp0_jump_nt,
35  tp0_jump_t,
36  tp1_jump_nt,
37  tp1_jump_t
38};
39
40static const unsigned tstBitOpcode[8] = {
41    J4_tstbit0_fp0_jump_nt, J4_tstbit0_fp0_jump_t,  J4_tstbit0_fp1_jump_nt,
42    J4_tstbit0_fp1_jump_t,  J4_tstbit0_tp0_jump_nt, J4_tstbit0_tp0_jump_t,
43    J4_tstbit0_tp1_jump_nt, J4_tstbit0_tp1_jump_t};
44static const unsigned cmpeqBitOpcode[8] = {
45    J4_cmpeq_fp0_jump_nt, J4_cmpeq_fp0_jump_t,  J4_cmpeq_fp1_jump_nt,
46    J4_cmpeq_fp1_jump_t,  J4_cmpeq_tp0_jump_nt, J4_cmpeq_tp0_jump_t,
47    J4_cmpeq_tp1_jump_nt, J4_cmpeq_tp1_jump_t};
48static const unsigned cmpgtBitOpcode[8] = {
49    J4_cmpgt_fp0_jump_nt, J4_cmpgt_fp0_jump_t,  J4_cmpgt_fp1_jump_nt,
50    J4_cmpgt_fp1_jump_t,  J4_cmpgt_tp0_jump_nt, J4_cmpgt_tp0_jump_t,
51    J4_cmpgt_tp1_jump_nt, J4_cmpgt_tp1_jump_t};
52static const unsigned cmpgtuBitOpcode[8] = {
53    J4_cmpgtu_fp0_jump_nt, J4_cmpgtu_fp0_jump_t,  J4_cmpgtu_fp1_jump_nt,
54    J4_cmpgtu_fp1_jump_t,  J4_cmpgtu_tp0_jump_nt, J4_cmpgtu_tp0_jump_t,
55    J4_cmpgtu_tp1_jump_nt, J4_cmpgtu_tp1_jump_t};
56static const unsigned cmpeqiBitOpcode[8] = {
57    J4_cmpeqi_fp0_jump_nt, J4_cmpeqi_fp0_jump_t,  J4_cmpeqi_fp1_jump_nt,
58    J4_cmpeqi_fp1_jump_t,  J4_cmpeqi_tp0_jump_nt, J4_cmpeqi_tp0_jump_t,
59    J4_cmpeqi_tp1_jump_nt, J4_cmpeqi_tp1_jump_t};
60static const unsigned cmpgtiBitOpcode[8] = {
61    J4_cmpgti_fp0_jump_nt, J4_cmpgti_fp0_jump_t,  J4_cmpgti_fp1_jump_nt,
62    J4_cmpgti_fp1_jump_t,  J4_cmpgti_tp0_jump_nt, J4_cmpgti_tp0_jump_t,
63    J4_cmpgti_tp1_jump_nt, J4_cmpgti_tp1_jump_t};
64static const unsigned cmpgtuiBitOpcode[8] = {
65    J4_cmpgtui_fp0_jump_nt, J4_cmpgtui_fp0_jump_t,  J4_cmpgtui_fp1_jump_nt,
66    J4_cmpgtui_fp1_jump_t,  J4_cmpgtui_tp0_jump_nt, J4_cmpgtui_tp0_jump_t,
67    J4_cmpgtui_tp1_jump_nt, J4_cmpgtui_tp1_jump_t};
68static const unsigned cmpeqn1BitOpcode[8] = {
69    J4_cmpeqn1_fp0_jump_nt, J4_cmpeqn1_fp0_jump_t,  J4_cmpeqn1_fp1_jump_nt,
70    J4_cmpeqn1_fp1_jump_t,  J4_cmpeqn1_tp0_jump_nt, J4_cmpeqn1_tp0_jump_t,
71    J4_cmpeqn1_tp1_jump_nt, J4_cmpeqn1_tp1_jump_t};
72static const unsigned cmpgtn1BitOpcode[8] = {
73    J4_cmpgtn1_fp0_jump_nt, J4_cmpgtn1_fp0_jump_t,  J4_cmpgtn1_fp1_jump_nt,
74    J4_cmpgtn1_fp1_jump_t,  J4_cmpgtn1_tp0_jump_nt, J4_cmpgtn1_tp0_jump_t,
75    J4_cmpgtn1_tp1_jump_nt, J4_cmpgtn1_tp1_jump_t,
76};
77
78// enum HexagonII::CompoundGroup
79static unsigned getCompoundCandidateGroup(MCInst const &MI, bool IsExtended) {
80  unsigned DstReg, SrcReg, Src1Reg, Src2Reg;
81
82  switch (MI.getOpcode()) {
83  default:
84    return HexagonII::HCG_None;
85  //
86  // Compound pairs.
87  // "p0=cmp.eq(Rs16,Rt16); if (p0.new) jump:nt #r9:2"
88  // "Rd16=#U6 ; jump #r9:2"
89  // "Rd16=Rs16 ; jump #r9:2"
90  //
91  case Hexagon::C2_cmpeq:
92  case Hexagon::C2_cmpgt:
93  case Hexagon::C2_cmpgtu:
94    if (IsExtended)
95      return HexagonII::HCG_None;
96    DstReg = MI.getOperand(0).getReg();
97    Src1Reg = MI.getOperand(1).getReg();
98    Src2Reg = MI.getOperand(2).getReg();
99    if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
100        HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
101        HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg))
102      return HexagonII::HCG_A;
103    break;
104  case Hexagon::C2_cmpeqi:
105  case Hexagon::C2_cmpgti:
106  case Hexagon::C2_cmpgtui:
107    if (IsExtended)
108      return HexagonII::HCG_None;
109    // P0 = cmp.eq(Rs,#u2)
110    DstReg = MI.getOperand(0).getReg();
111    SrcReg = MI.getOperand(1).getReg();
112    if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
113        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
114        (HexagonMCInstrInfo::inRange<5>(MI, 2) ||
115         HexagonMCInstrInfo::minConstant(MI, 2) == -1))
116      return HexagonII::HCG_A;
117    break;
118  case Hexagon::A2_tfr:
119    if (IsExtended)
120      return HexagonII::HCG_None;
121    // Rd = Rs
122    DstReg = MI.getOperand(0).getReg();
123    SrcReg = MI.getOperand(1).getReg();
124    if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
125        HexagonMCInstrInfo::isIntRegForSubInst(SrcReg))
126      return HexagonII::HCG_A;
127    break;
128  case Hexagon::A2_tfrsi:
129    if (IsExtended)
130      return HexagonII::HCG_None;
131    // Rd = #u6
132    DstReg = MI.getOperand(0).getReg();
133    if (HexagonMCInstrInfo::minConstant(MI, 1) <= 63 &&
134        HexagonMCInstrInfo::minConstant(MI, 1) >= 0 &&
135        HexagonMCInstrInfo::isIntRegForSubInst(DstReg))
136      return HexagonII::HCG_A;
137    break;
138  case Hexagon::S2_tstbit_i:
139    if (IsExtended)
140      return HexagonII::HCG_None;
141    DstReg = MI.getOperand(0).getReg();
142    Src1Reg = MI.getOperand(1).getReg();
143    if ((Hexagon::P0 == DstReg || Hexagon::P1 == DstReg) &&
144        HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
145        HexagonMCInstrInfo::minConstant(MI, 2) == 0)
146      return HexagonII::HCG_A;
147    break;
148  // The fact that .new form is used pretty much guarantees
149  // that predicate register will match. Nevertheless,
150  // there could be some false positives without additional
151  // checking.
152  case Hexagon::J2_jumptnew:
153  case Hexagon::J2_jumpfnew:
154  case Hexagon::J2_jumptnewpt:
155  case Hexagon::J2_jumpfnewpt:
156    Src1Reg = MI.getOperand(0).getReg();
157    if (Hexagon::P0 == Src1Reg || Hexagon::P1 == Src1Reg)
158      return HexagonII::HCG_B;
159    break;
160  // Transfer and jump:
161  // Rd=#U6 ; jump #r9:2
162  // Rd=Rs ; jump #r9:2
163  // Do not test for jump range here.
164  case Hexagon::J2_jump:
165  case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
166    return HexagonII::HCG_C;
167    break;
168  }
169
170  return HexagonII::HCG_None;
171}
172
173/// getCompoundOp - Return the index from 0-7 into the above opcode lists.
174static unsigned getCompoundOp(MCInst const &HMCI) {
175  const MCOperand &Predicate = HMCI.getOperand(0);
176  unsigned PredReg = Predicate.getReg();
177
178  assert((PredReg == Hexagon::P0) || (PredReg == Hexagon::P1) ||
179         (PredReg == Hexagon::P2) || (PredReg == Hexagon::P3));
180
181  switch (HMCI.getOpcode()) {
182  default:
183    llvm_unreachable("Expected match not found.\n");
184    break;
185  case Hexagon::J2_jumpfnew:
186    return (PredReg == Hexagon::P0) ? fp0_jump_nt : fp1_jump_nt;
187  case Hexagon::J2_jumpfnewpt:
188    return (PredReg == Hexagon::P0) ? fp0_jump_t : fp1_jump_t;
189  case Hexagon::J2_jumptnew:
190    return (PredReg == Hexagon::P0) ? tp0_jump_nt : tp1_jump_nt;
191  case Hexagon::J2_jumptnewpt:
192    return (PredReg == Hexagon::P0) ? tp0_jump_t : tp1_jump_t;
193  }
194}
195
196static MCInst *getCompoundInsn(MCContext &Context, MCInst const &L,
197                               MCInst const &R) {
198  MCInst *CompoundInsn = nullptr;
199  unsigned compoundOpcode;
200  MCOperand Rs, Rt;
201  int64_t Value;
202  bool Success;
203
204  switch (L.getOpcode()) {
205  default:
206    LLVM_DEBUG(dbgs() << "Possible compound ignored\n");
207    return CompoundInsn;
208
209  case Hexagon::A2_tfrsi:
210    Rt = L.getOperand(0);
211    compoundOpcode = J4_jumpseti;
212    CompoundInsn = new (Context) MCInst;
213    CompoundInsn->setOpcode(compoundOpcode);
214
215    CompoundInsn->addOperand(Rt);
216    CompoundInsn->addOperand(L.getOperand(1)); // Immediate
217    CompoundInsn->addOperand(R.getOperand(0)); // Jump target
218    break;
219
220  case Hexagon::A2_tfr:
221    Rt = L.getOperand(0);
222    Rs = L.getOperand(1);
223
224    compoundOpcode = J4_jumpsetr;
225    CompoundInsn = new (Context) MCInst;
226    CompoundInsn->setOpcode(compoundOpcode);
227    CompoundInsn->addOperand(Rt);
228    CompoundInsn->addOperand(Rs);
229    CompoundInsn->addOperand(R.getOperand(0)); // Jump target.
230
231    break;
232
233  case Hexagon::C2_cmpeq:
234    LLVM_DEBUG(dbgs() << "CX: C2_cmpeq\n");
235    Rs = L.getOperand(1);
236    Rt = L.getOperand(2);
237
238    compoundOpcode = cmpeqBitOpcode[getCompoundOp(R)];
239    CompoundInsn = new (Context) MCInst;
240    CompoundInsn->setOpcode(compoundOpcode);
241    CompoundInsn->addOperand(Rs);
242    CompoundInsn->addOperand(Rt);
243    CompoundInsn->addOperand(R.getOperand(1));
244    break;
245
246  case Hexagon::C2_cmpgt:
247    LLVM_DEBUG(dbgs() << "CX: C2_cmpgt\n");
248    Rs = L.getOperand(1);
249    Rt = L.getOperand(2);
250
251    compoundOpcode = cmpgtBitOpcode[getCompoundOp(R)];
252    CompoundInsn = new (Context) MCInst;
253    CompoundInsn->setOpcode(compoundOpcode);
254    CompoundInsn->addOperand(Rs);
255    CompoundInsn->addOperand(Rt);
256    CompoundInsn->addOperand(R.getOperand(1));
257    break;
258
259  case Hexagon::C2_cmpgtu:
260    LLVM_DEBUG(dbgs() << "CX: C2_cmpgtu\n");
261    Rs = L.getOperand(1);
262    Rt = L.getOperand(2);
263
264    compoundOpcode = cmpgtuBitOpcode[getCompoundOp(R)];
265    CompoundInsn = new (Context) MCInst;
266    CompoundInsn->setOpcode(compoundOpcode);
267    CompoundInsn->addOperand(Rs);
268    CompoundInsn->addOperand(Rt);
269    CompoundInsn->addOperand(R.getOperand(1));
270    break;
271
272  case Hexagon::C2_cmpeqi:
273    LLVM_DEBUG(dbgs() << "CX: C2_cmpeqi\n");
274    Success = L.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
275    (void)Success;
276    assert(Success);
277    if (Value == -1)
278      compoundOpcode = cmpeqn1BitOpcode[getCompoundOp(R)];
279    else
280      compoundOpcode = cmpeqiBitOpcode[getCompoundOp(R)];
281
282    Rs = L.getOperand(1);
283    CompoundInsn = new (Context) MCInst;
284    CompoundInsn->setOpcode(compoundOpcode);
285    CompoundInsn->addOperand(Rs);
286    CompoundInsn->addOperand(L.getOperand(2));
287    CompoundInsn->addOperand(R.getOperand(1));
288    break;
289
290  case Hexagon::C2_cmpgti:
291    LLVM_DEBUG(dbgs() << "CX: C2_cmpgti\n");
292    Success = L.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
293    (void)Success;
294    assert(Success);
295    if (Value == -1)
296      compoundOpcode = cmpgtn1BitOpcode[getCompoundOp(R)];
297    else
298      compoundOpcode = cmpgtiBitOpcode[getCompoundOp(R)];
299
300    Rs = L.getOperand(1);
301    CompoundInsn = new (Context) MCInst;
302    CompoundInsn->setOpcode(compoundOpcode);
303    CompoundInsn->addOperand(Rs);
304    CompoundInsn->addOperand(L.getOperand(2));
305    CompoundInsn->addOperand(R.getOperand(1));
306    break;
307
308  case Hexagon::C2_cmpgtui:
309    LLVM_DEBUG(dbgs() << "CX: C2_cmpgtui\n");
310    Rs = L.getOperand(1);
311    compoundOpcode = cmpgtuiBitOpcode[getCompoundOp(R)];
312    CompoundInsn = new (Context) MCInst;
313    CompoundInsn->setOpcode(compoundOpcode);
314    CompoundInsn->addOperand(Rs);
315    CompoundInsn->addOperand(L.getOperand(2));
316    CompoundInsn->addOperand(R.getOperand(1));
317    break;
318
319  case Hexagon::S2_tstbit_i:
320    LLVM_DEBUG(dbgs() << "CX: S2_tstbit_i\n");
321    Rs = L.getOperand(1);
322    compoundOpcode = tstBitOpcode[getCompoundOp(R)];
323    CompoundInsn = new (Context) MCInst;
324    CompoundInsn->setOpcode(compoundOpcode);
325    CompoundInsn->addOperand(Rs);
326    CompoundInsn->addOperand(R.getOperand(1));
327    break;
328  }
329
330  return CompoundInsn;
331}
332
333/// Non-Symmetrical. See if these two instructions are fit for compound pair.
334static bool isOrderedCompoundPair(MCInst const &MIa, bool IsExtendedA,
335                                  MCInst const &MIb, bool IsExtendedB) {
336  unsigned MIaG = getCompoundCandidateGroup(MIa, IsExtendedA);
337  unsigned MIbG = getCompoundCandidateGroup(MIb, IsExtendedB);
338  // We have two candidates - check that this is the same register
339  // we are talking about.
340  unsigned Opca = MIa.getOpcode();
341  if (MIaG == HexagonII::HCG_A && MIbG == HexagonII::HCG_C &&
342      (Opca == Hexagon::A2_tfr || Opca == Hexagon::A2_tfrsi))
343    return true;
344  return ((MIaG == HexagonII::HCG_A && MIbG == HexagonII::HCG_B) &&
345          (MIa.getOperand(0).getReg() == MIb.getOperand(0).getReg()));
346}
347
348static bool lookForCompound(MCInstrInfo const &MCII, MCContext &Context,
349                            MCInst &MCI) {
350  assert(HexagonMCInstrInfo::isBundle(MCI));
351  bool JExtended = false;
352  for (MCInst::iterator J =
353           MCI.begin() + HexagonMCInstrInfo::bundleInstructionsOffset;
354       J != MCI.end(); ++J) {
355    MCInst const *JumpInst = J->getInst();
356    if (HexagonMCInstrInfo::isImmext(*JumpInst)) {
357      JExtended = true;
358      continue;
359    }
360    if (HexagonMCInstrInfo::getType(MCII, *JumpInst) == HexagonII::TypeJ) {
361      // Try to pair with another insn (B)undled with jump.
362      bool BExtended = false;
363      for (MCInst::iterator B =
364               MCI.begin() + HexagonMCInstrInfo::bundleInstructionsOffset;
365           B != MCI.end(); ++B) {
366        MCInst const *Inst = B->getInst();
367        if (JumpInst == Inst)
368          continue;
369        if (HexagonMCInstrInfo::isImmext(*Inst)) {
370          BExtended = true;
371          continue;
372        }
373        LLVM_DEBUG(dbgs() << "J,B: " << JumpInst->getOpcode() << ","
374                          << Inst->getOpcode() << "\n");
375        if (isOrderedCompoundPair(*Inst, BExtended, *JumpInst, JExtended)) {
376          MCInst *CompoundInsn = getCompoundInsn(Context, *Inst, *JumpInst);
377          if (CompoundInsn) {
378            LLVM_DEBUG(dbgs() << "B: " << Inst->getOpcode() << ","
379                              << JumpInst->getOpcode() << " Compounds to "
380                              << CompoundInsn->getOpcode() << "\n");
381            J->setInst(CompoundInsn);
382            MCI.erase(B);
383            return true;
384          }
385        }
386        BExtended = false;
387      }
388    }
389    JExtended = false;
390  }
391  return false;
392}
393
394/// tryCompound - Given a bundle check for compound insns when one
395/// is found update the contents fo the bundle with the compound insn.
396/// If a compound instruction is found then the bundle will have one
397/// additional slot.
398void HexagonMCInstrInfo::tryCompound(MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
399                                     MCContext &Context, MCInst &MCI) {
400  assert(HexagonMCInstrInfo::isBundle(MCI) &&
401         "Non-Bundle where Bundle expected");
402
403  // By definition a compound must have 2 insn.
404  if (MCI.size() < 2)
405    return;
406
407  bool StartedValid = llvm::HexagonMCShuffle(Context, false, MCII, STI, MCI);
408
409  // Create a vector, needed to keep the order of jump instructions.
410  MCInst CheckList(MCI);
411
412  // Look for compounds until none are found, only update the bundle when
413  // a compound is found.
414  while (lookForCompound(MCII, Context, CheckList)) {
415    // Keep the original bundle around in case the shuffle fails.
416    MCInst OriginalBundle(MCI);
417
418    // Need to update the bundle.
419    MCI = CheckList;
420
421    if (StartedValid &&
422        !llvm::HexagonMCShuffle(Context, false, MCII, STI, MCI)) {
423      LLVM_DEBUG(dbgs() << "Found ERROR\n");
424      MCI = OriginalBundle;
425    }
426  }
427}
428