106f32e7eSjoerg //===- HexagonMCDuplexInfo.cpp - Instruction bundle checking --------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This implements duplexing of instructions to reduce code size
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
13*da58b97aSjoerg #include "HexagonMCExpr.h"
1406f32e7eSjoerg #include "MCTargetDesc/HexagonBaseInfo.h"
1506f32e7eSjoerg #include "MCTargetDesc/HexagonMCInstrInfo.h"
1606f32e7eSjoerg #include "MCTargetDesc/HexagonMCTargetDesc.h"
1706f32e7eSjoerg #include "llvm/ADT/SmallVector.h"
1806f32e7eSjoerg #include "llvm/MC/MCSubtargetInfo.h"
1906f32e7eSjoerg #include "llvm/Support/Debug.h"
2006f32e7eSjoerg #include "llvm/Support/ErrorHandling.h"
2106f32e7eSjoerg #include "llvm/Support/MathExtras.h"
2206f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
2306f32e7eSjoerg #include <cassert>
2406f32e7eSjoerg #include <cstdint>
2506f32e7eSjoerg #include <iterator>
2606f32e7eSjoerg #include <map>
2706f32e7eSjoerg #include <utility>
2806f32e7eSjoerg 
2906f32e7eSjoerg using namespace llvm;
3006f32e7eSjoerg using namespace Hexagon;
3106f32e7eSjoerg 
3206f32e7eSjoerg #define DEBUG_TYPE "hexagon-mcduplex-info"
3306f32e7eSjoerg 
3406f32e7eSjoerg // pair table of subInstructions with opcodes
3506f32e7eSjoerg static const std::pair<unsigned, unsigned> opcodeData[] = {
3606f32e7eSjoerg     std::make_pair((unsigned)SA1_addi, 0),
3706f32e7eSjoerg     std::make_pair((unsigned)SA1_addrx, 6144),
3806f32e7eSjoerg     std::make_pair((unsigned)SA1_addsp, 3072),
3906f32e7eSjoerg     std::make_pair((unsigned)SA1_and1, 4608),
4006f32e7eSjoerg     std::make_pair((unsigned)SA1_clrf, 6768),
4106f32e7eSjoerg     std::make_pair((unsigned)SA1_clrfnew, 6736),
4206f32e7eSjoerg     std::make_pair((unsigned)SA1_clrt, 6752),
4306f32e7eSjoerg     std::make_pair((unsigned)SA1_clrtnew, 6720),
4406f32e7eSjoerg     std::make_pair((unsigned)SA1_cmpeqi, 6400),
4506f32e7eSjoerg     std::make_pair((unsigned)SA1_combine0i, 7168),
4606f32e7eSjoerg     std::make_pair((unsigned)SA1_combine1i, 7176),
4706f32e7eSjoerg     std::make_pair((unsigned)SA1_combine2i, 7184),
4806f32e7eSjoerg     std::make_pair((unsigned)SA1_combine3i, 7192),
4906f32e7eSjoerg     std::make_pair((unsigned)SA1_combinerz, 7432),
5006f32e7eSjoerg     std::make_pair((unsigned)SA1_combinezr, 7424),
5106f32e7eSjoerg     std::make_pair((unsigned)SA1_dec, 4864),
5206f32e7eSjoerg     std::make_pair((unsigned)SA1_inc, 4352),
5306f32e7eSjoerg     std::make_pair((unsigned)SA1_seti, 2048),
5406f32e7eSjoerg     std::make_pair((unsigned)SA1_setin1, 6656),
5506f32e7eSjoerg     std::make_pair((unsigned)SA1_sxtb, 5376),
5606f32e7eSjoerg     std::make_pair((unsigned)SA1_sxth, 5120),
5706f32e7eSjoerg     std::make_pair((unsigned)SA1_tfr, 4096),
5806f32e7eSjoerg     std::make_pair((unsigned)SA1_zxtb, 5888),
5906f32e7eSjoerg     std::make_pair((unsigned)SA1_zxth, 5632),
6006f32e7eSjoerg     std::make_pair((unsigned)SL1_loadri_io, 0),
6106f32e7eSjoerg     std::make_pair((unsigned)SL1_loadrub_io, 4096),
6206f32e7eSjoerg     std::make_pair((unsigned)SL2_deallocframe, 7936),
6306f32e7eSjoerg     std::make_pair((unsigned)SL2_jumpr31, 8128),
6406f32e7eSjoerg     std::make_pair((unsigned)SL2_jumpr31_f, 8133),
6506f32e7eSjoerg     std::make_pair((unsigned)SL2_jumpr31_fnew, 8135),
6606f32e7eSjoerg     std::make_pair((unsigned)SL2_jumpr31_t, 8132),
6706f32e7eSjoerg     std::make_pair((unsigned)SL2_jumpr31_tnew, 8134),
6806f32e7eSjoerg     std::make_pair((unsigned)SL2_loadrb_io, 4096),
6906f32e7eSjoerg     std::make_pair((unsigned)SL2_loadrd_sp, 7680),
7006f32e7eSjoerg     std::make_pair((unsigned)SL2_loadrh_io, 0),
7106f32e7eSjoerg     std::make_pair((unsigned)SL2_loadri_sp, 7168),
7206f32e7eSjoerg     std::make_pair((unsigned)SL2_loadruh_io, 2048),
7306f32e7eSjoerg     std::make_pair((unsigned)SL2_return, 8000),
7406f32e7eSjoerg     std::make_pair((unsigned)SL2_return_f, 8005),
7506f32e7eSjoerg     std::make_pair((unsigned)SL2_return_fnew, 8007),
7606f32e7eSjoerg     std::make_pair((unsigned)SL2_return_t, 8004),
7706f32e7eSjoerg     std::make_pair((unsigned)SL2_return_tnew, 8006),
7806f32e7eSjoerg     std::make_pair((unsigned)SS1_storeb_io, 4096),
7906f32e7eSjoerg     std::make_pair((unsigned)SS1_storew_io, 0),
8006f32e7eSjoerg     std::make_pair((unsigned)SS2_allocframe, 7168),
8106f32e7eSjoerg     std::make_pair((unsigned)SS2_storebi0, 4608),
8206f32e7eSjoerg     std::make_pair((unsigned)SS2_storebi1, 4864),
8306f32e7eSjoerg     std::make_pair((unsigned)SS2_stored_sp, 2560),
8406f32e7eSjoerg     std::make_pair((unsigned)SS2_storeh_io, 0),
8506f32e7eSjoerg     std::make_pair((unsigned)SS2_storew_sp, 2048),
8606f32e7eSjoerg     std::make_pair((unsigned)SS2_storewi0, 4096),
8706f32e7eSjoerg     std::make_pair((unsigned)SS2_storewi1, 4352)};
8806f32e7eSjoerg 
isDuplexPairMatch(unsigned Ga,unsigned Gb)8906f32e7eSjoerg bool HexagonMCInstrInfo::isDuplexPairMatch(unsigned Ga, unsigned Gb) {
9006f32e7eSjoerg   switch (Ga) {
9106f32e7eSjoerg   case HexagonII::HSIG_None:
9206f32e7eSjoerg   default:
9306f32e7eSjoerg     return false;
9406f32e7eSjoerg   case HexagonII::HSIG_L1:
9506f32e7eSjoerg     return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_A);
9606f32e7eSjoerg   case HexagonII::HSIG_L2:
9706f32e7eSjoerg     return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
9806f32e7eSjoerg             Gb == HexagonII::HSIG_A);
9906f32e7eSjoerg   case HexagonII::HSIG_S1:
10006f32e7eSjoerg     return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
10106f32e7eSjoerg             Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_A);
10206f32e7eSjoerg   case HexagonII::HSIG_S2:
10306f32e7eSjoerg     return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
10406f32e7eSjoerg             Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_S2 ||
10506f32e7eSjoerg             Gb == HexagonII::HSIG_A);
10606f32e7eSjoerg   case HexagonII::HSIG_A:
10706f32e7eSjoerg     return (Gb == HexagonII::HSIG_A);
10806f32e7eSjoerg   case HexagonII::HSIG_Compound:
10906f32e7eSjoerg     return (Gb == HexagonII::HSIG_Compound);
11006f32e7eSjoerg   }
11106f32e7eSjoerg   return false;
11206f32e7eSjoerg }
11306f32e7eSjoerg 
iClassOfDuplexPair(unsigned Ga,unsigned Gb)11406f32e7eSjoerg unsigned HexagonMCInstrInfo::iClassOfDuplexPair(unsigned Ga, unsigned Gb) {
11506f32e7eSjoerg   switch (Ga) {
11606f32e7eSjoerg   case HexagonII::HSIG_None:
11706f32e7eSjoerg   default:
11806f32e7eSjoerg     break;
11906f32e7eSjoerg   case HexagonII::HSIG_L1:
12006f32e7eSjoerg     switch (Gb) {
12106f32e7eSjoerg     default:
12206f32e7eSjoerg       break;
12306f32e7eSjoerg     case HexagonII::HSIG_L1:
12406f32e7eSjoerg       return 0;
12506f32e7eSjoerg     case HexagonII::HSIG_A:
12606f32e7eSjoerg       return 0x4;
12706f32e7eSjoerg     }
12806f32e7eSjoerg     break;
12906f32e7eSjoerg   case HexagonII::HSIG_L2:
13006f32e7eSjoerg     switch (Gb) {
13106f32e7eSjoerg     default:
13206f32e7eSjoerg       break;
13306f32e7eSjoerg     case HexagonII::HSIG_L1:
13406f32e7eSjoerg       return 0x1;
13506f32e7eSjoerg     case HexagonII::HSIG_L2:
13606f32e7eSjoerg       return 0x2;
13706f32e7eSjoerg     case HexagonII::HSIG_A:
13806f32e7eSjoerg       return 0x5;
13906f32e7eSjoerg     }
14006f32e7eSjoerg     break;
14106f32e7eSjoerg   case HexagonII::HSIG_S1:
14206f32e7eSjoerg     switch (Gb) {
14306f32e7eSjoerg     default:
14406f32e7eSjoerg       break;
14506f32e7eSjoerg     case HexagonII::HSIG_L1:
14606f32e7eSjoerg       return 0x8;
14706f32e7eSjoerg     case HexagonII::HSIG_L2:
14806f32e7eSjoerg       return 0x9;
14906f32e7eSjoerg     case HexagonII::HSIG_S1:
15006f32e7eSjoerg       return 0xA;
15106f32e7eSjoerg     case HexagonII::HSIG_A:
15206f32e7eSjoerg       return 0x6;
15306f32e7eSjoerg     }
15406f32e7eSjoerg     break;
15506f32e7eSjoerg   case HexagonII::HSIG_S2:
15606f32e7eSjoerg     switch (Gb) {
15706f32e7eSjoerg     default:
15806f32e7eSjoerg       break;
15906f32e7eSjoerg     case HexagonII::HSIG_L1:
16006f32e7eSjoerg       return 0xC;
16106f32e7eSjoerg     case HexagonII::HSIG_L2:
16206f32e7eSjoerg       return 0xD;
16306f32e7eSjoerg     case HexagonII::HSIG_S1:
16406f32e7eSjoerg       return 0xB;
16506f32e7eSjoerg     case HexagonII::HSIG_S2:
16606f32e7eSjoerg       return 0xE;
16706f32e7eSjoerg     case HexagonII::HSIG_A:
16806f32e7eSjoerg       return 0x7;
16906f32e7eSjoerg     }
17006f32e7eSjoerg     break;
17106f32e7eSjoerg   case HexagonII::HSIG_A:
17206f32e7eSjoerg     switch (Gb) {
17306f32e7eSjoerg     default:
17406f32e7eSjoerg       break;
17506f32e7eSjoerg     case HexagonII::HSIG_A:
17606f32e7eSjoerg       return 0x3;
17706f32e7eSjoerg     }
17806f32e7eSjoerg     break;
17906f32e7eSjoerg   case HexagonII::HSIG_Compound:
18006f32e7eSjoerg     switch (Gb) {
18106f32e7eSjoerg     case HexagonII::HSIG_Compound:
18206f32e7eSjoerg       return 0xFFFFFFFF;
18306f32e7eSjoerg     }
18406f32e7eSjoerg     break;
18506f32e7eSjoerg   }
18606f32e7eSjoerg   return 0xFFFFFFFF;
18706f32e7eSjoerg }
18806f32e7eSjoerg 
getDuplexCandidateGroup(MCInst const & MCI)18906f32e7eSjoerg unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
19006f32e7eSjoerg   unsigned DstReg, PredReg, SrcReg, Src1Reg, Src2Reg;
19106f32e7eSjoerg 
19206f32e7eSjoerg   switch (MCI.getOpcode()) {
19306f32e7eSjoerg   default:
19406f32e7eSjoerg     return HexagonII::HSIG_None;
19506f32e7eSjoerg   //
19606f32e7eSjoerg   // Group L1:
19706f32e7eSjoerg   //
19806f32e7eSjoerg   // Rd = memw(Rs+#u4:2)
19906f32e7eSjoerg   // Rd = memub(Rs+#u4:0)
20006f32e7eSjoerg   case Hexagon::L2_loadri_io:
20106f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
20206f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
20306f32e7eSjoerg     // Special case this one from Group L2.
20406f32e7eSjoerg     // Rd = memw(r29+#u5:2)
20506f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
20606f32e7eSjoerg       if (HexagonMCInstrInfo::isIntReg(SrcReg) &&
20706f32e7eSjoerg           Hexagon::R29 == SrcReg && inRange<5, 2>(MCI, 2)) {
20806f32e7eSjoerg         return HexagonII::HSIG_L2;
20906f32e7eSjoerg       }
21006f32e7eSjoerg       // Rd = memw(Rs+#u4:2)
21106f32e7eSjoerg       if (HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
21206f32e7eSjoerg           inRange<4, 2>(MCI, 2)) {
21306f32e7eSjoerg         return HexagonII::HSIG_L1;
21406f32e7eSjoerg       }
21506f32e7eSjoerg     }
21606f32e7eSjoerg     break;
21706f32e7eSjoerg   case Hexagon::L2_loadrub_io:
21806f32e7eSjoerg     // Rd = memub(Rs+#u4:0)
21906f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
22006f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
22106f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
22206f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
22306f32e7eSjoerg         inRange<4>(MCI, 2)) {
22406f32e7eSjoerg       return HexagonII::HSIG_L1;
22506f32e7eSjoerg     }
22606f32e7eSjoerg     break;
22706f32e7eSjoerg   //
22806f32e7eSjoerg   // Group L2:
22906f32e7eSjoerg   //
23006f32e7eSjoerg   // Rd = memh/memuh(Rs+#u3:1)
23106f32e7eSjoerg   // Rd = memb(Rs+#u3:0)
23206f32e7eSjoerg   // Rd = memw(r29+#u5:2) - Handled above.
23306f32e7eSjoerg   // Rdd = memd(r29+#u5:3)
23406f32e7eSjoerg   // deallocframe
23506f32e7eSjoerg   // [if ([!]p0[.new])] dealloc_return
23606f32e7eSjoerg   // [if ([!]p0[.new])] jumpr r31
23706f32e7eSjoerg   case Hexagon::L2_loadrh_io:
23806f32e7eSjoerg   case Hexagon::L2_loadruh_io:
23906f32e7eSjoerg     // Rd = memh/memuh(Rs+#u3:1)
24006f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
24106f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
24206f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
24306f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
24406f32e7eSjoerg         inRange<3, 1>(MCI, 2)) {
24506f32e7eSjoerg       return HexagonII::HSIG_L2;
24606f32e7eSjoerg     }
24706f32e7eSjoerg     break;
24806f32e7eSjoerg   case Hexagon::L2_loadrb_io:
24906f32e7eSjoerg     // Rd = memb(Rs+#u3:0)
25006f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
25106f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
25206f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
25306f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
25406f32e7eSjoerg         inRange<3>(MCI, 2)) {
25506f32e7eSjoerg       return HexagonII::HSIG_L2;
25606f32e7eSjoerg     }
25706f32e7eSjoerg     break;
25806f32e7eSjoerg   case Hexagon::L2_loadrd_io:
25906f32e7eSjoerg     // Rdd = memd(r29+#u5:3)
26006f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
26106f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
26206f32e7eSjoerg     if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
26306f32e7eSjoerg         HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
26406f32e7eSjoerg         inRange<5, 3>(MCI, 2)) {
26506f32e7eSjoerg       return HexagonII::HSIG_L2;
26606f32e7eSjoerg     }
26706f32e7eSjoerg     break;
26806f32e7eSjoerg 
26906f32e7eSjoerg   case Hexagon::L4_return:
27006f32e7eSjoerg   case Hexagon::L2_deallocframe:
27106f32e7eSjoerg     return HexagonII::HSIG_L2;
27206f32e7eSjoerg 
27306f32e7eSjoerg   case Hexagon::EH_RETURN_JMPR:
27406f32e7eSjoerg   case Hexagon::J2_jumpr:
27506f32e7eSjoerg   case Hexagon::PS_jmpret:
27606f32e7eSjoerg     // jumpr r31
27706f32e7eSjoerg     // Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0.
27806f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
27906f32e7eSjoerg     if (Hexagon::R31 == DstReg)
28006f32e7eSjoerg       return HexagonII::HSIG_L2;
28106f32e7eSjoerg     break;
28206f32e7eSjoerg 
28306f32e7eSjoerg   case Hexagon::J2_jumprt:
28406f32e7eSjoerg   case Hexagon::J2_jumprf:
28506f32e7eSjoerg   case Hexagon::J2_jumprtnew:
28606f32e7eSjoerg   case Hexagon::J2_jumprfnew:
28706f32e7eSjoerg   case Hexagon::J2_jumprtnewpt:
28806f32e7eSjoerg   case Hexagon::J2_jumprfnewpt:
28906f32e7eSjoerg   case Hexagon::PS_jmprett:
29006f32e7eSjoerg   case Hexagon::PS_jmpretf:
29106f32e7eSjoerg   case Hexagon::PS_jmprettnew:
29206f32e7eSjoerg   case Hexagon::PS_jmpretfnew:
29306f32e7eSjoerg   case Hexagon::PS_jmprettnewpt:
29406f32e7eSjoerg   case Hexagon::PS_jmpretfnewpt:
29506f32e7eSjoerg     DstReg = MCI.getOperand(1).getReg();
29606f32e7eSjoerg     SrcReg = MCI.getOperand(0).getReg();
29706f32e7eSjoerg     // [if ([!]p0[.new])] jumpr r31
298*da58b97aSjoerg     if ((Hexagon::P0 == SrcReg) && (Hexagon::R31 == DstReg)) {
29906f32e7eSjoerg       return HexagonII::HSIG_L2;
30006f32e7eSjoerg     }
30106f32e7eSjoerg     break;
30206f32e7eSjoerg   case Hexagon::L4_return_t:
30306f32e7eSjoerg   case Hexagon::L4_return_f:
30406f32e7eSjoerg   case Hexagon::L4_return_tnew_pnt:
30506f32e7eSjoerg   case Hexagon::L4_return_fnew_pnt:
30606f32e7eSjoerg   case Hexagon::L4_return_tnew_pt:
30706f32e7eSjoerg   case Hexagon::L4_return_fnew_pt:
30806f32e7eSjoerg     // [if ([!]p0[.new])] dealloc_return
30906f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
31006f32e7eSjoerg     if (Hexagon::P0 == SrcReg) {
31106f32e7eSjoerg       return HexagonII::HSIG_L2;
31206f32e7eSjoerg     }
31306f32e7eSjoerg     break;
31406f32e7eSjoerg   //
31506f32e7eSjoerg   // Group S1:
31606f32e7eSjoerg   //
31706f32e7eSjoerg   // memw(Rs+#u4:2) = Rt
31806f32e7eSjoerg   // memb(Rs+#u4:0) = Rt
31906f32e7eSjoerg   case Hexagon::S2_storeri_io:
32006f32e7eSjoerg     // Special case this one from Group S2.
32106f32e7eSjoerg     // memw(r29+#u5:2) = Rt
32206f32e7eSjoerg     Src1Reg = MCI.getOperand(0).getReg();
32306f32e7eSjoerg     Src2Reg = MCI.getOperand(2).getReg();
32406f32e7eSjoerg     if (HexagonMCInstrInfo::isIntReg(Src1Reg) &&
32506f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
32606f32e7eSjoerg         Hexagon::R29 == Src1Reg && inRange<5, 2>(MCI, 1)) {
32706f32e7eSjoerg       return HexagonII::HSIG_S2;
32806f32e7eSjoerg     }
32906f32e7eSjoerg     // memw(Rs+#u4:2) = Rt
33006f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
33106f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
33206f32e7eSjoerg         inRange<4, 2>(MCI, 1)) {
33306f32e7eSjoerg       return HexagonII::HSIG_S1;
33406f32e7eSjoerg     }
33506f32e7eSjoerg     break;
33606f32e7eSjoerg   case Hexagon::S2_storerb_io:
33706f32e7eSjoerg     // memb(Rs+#u4:0) = Rt
33806f32e7eSjoerg     Src1Reg = MCI.getOperand(0).getReg();
33906f32e7eSjoerg     Src2Reg = MCI.getOperand(2).getReg();
34006f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
34106f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
34206f32e7eSjoerg         inRange<4>(MCI, 1)) {
34306f32e7eSjoerg       return HexagonII::HSIG_S1;
34406f32e7eSjoerg     }
34506f32e7eSjoerg     break;
34606f32e7eSjoerg   //
34706f32e7eSjoerg   // Group S2:
34806f32e7eSjoerg   //
34906f32e7eSjoerg   // memh(Rs+#u3:1) = Rt
35006f32e7eSjoerg   // memw(r29+#u5:2) = Rt
35106f32e7eSjoerg   // memd(r29+#s6:3) = Rtt
35206f32e7eSjoerg   // memw(Rs+#u4:2) = #U1
35306f32e7eSjoerg   // memb(Rs+#u4) = #U1
35406f32e7eSjoerg   // allocframe(#u5:3)
35506f32e7eSjoerg   case Hexagon::S2_storerh_io:
35606f32e7eSjoerg     // memh(Rs+#u3:1) = Rt
35706f32e7eSjoerg     Src1Reg = MCI.getOperand(0).getReg();
35806f32e7eSjoerg     Src2Reg = MCI.getOperand(2).getReg();
35906f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
36006f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
36106f32e7eSjoerg         inRange<3, 1>(MCI, 1)) {
36206f32e7eSjoerg       return HexagonII::HSIG_S2;
36306f32e7eSjoerg     }
36406f32e7eSjoerg     break;
36506f32e7eSjoerg   case Hexagon::S2_storerd_io:
36606f32e7eSjoerg     // memd(r29+#s6:3) = Rtt
36706f32e7eSjoerg     Src1Reg = MCI.getOperand(0).getReg();
36806f32e7eSjoerg     Src2Reg = MCI.getOperand(2).getReg();
36906f32e7eSjoerg     if (HexagonMCInstrInfo::isDblRegForSubInst(Src2Reg) &&
37006f32e7eSjoerg         HexagonMCInstrInfo::isIntReg(Src1Reg) && Hexagon::R29 == Src1Reg &&
37106f32e7eSjoerg         inSRange<6, 3>(MCI, 1)) {
37206f32e7eSjoerg       return HexagonII::HSIG_S2;
37306f32e7eSjoerg     }
37406f32e7eSjoerg     break;
37506f32e7eSjoerg   case Hexagon::S4_storeiri_io:
37606f32e7eSjoerg     // memw(Rs+#u4:2) = #U1
37706f32e7eSjoerg     Src1Reg = MCI.getOperand(0).getReg();
37806f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
37906f32e7eSjoerg         inRange<4, 2>(MCI, 1) && inRange<1>(MCI, 2)) {
38006f32e7eSjoerg       return HexagonII::HSIG_S2;
38106f32e7eSjoerg     }
38206f32e7eSjoerg     break;
38306f32e7eSjoerg   case Hexagon::S4_storeirb_io:
38406f32e7eSjoerg     // memb(Rs+#u4) = #U1
38506f32e7eSjoerg     Src1Reg = MCI.getOperand(0).getReg();
38606f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
38706f32e7eSjoerg         inRange<4>(MCI, 1) && inRange<1>(MCI, 2)) {
38806f32e7eSjoerg       return HexagonII::HSIG_S2;
38906f32e7eSjoerg     }
39006f32e7eSjoerg     break;
39106f32e7eSjoerg   case Hexagon::S2_allocframe:
39206f32e7eSjoerg     if (inRange<5, 3>(MCI, 2))
39306f32e7eSjoerg       return HexagonII::HSIG_S2;
39406f32e7eSjoerg     break;
39506f32e7eSjoerg   //
39606f32e7eSjoerg   // Group A:
39706f32e7eSjoerg   //
39806f32e7eSjoerg   // Rx = add(Rx,#s7)
39906f32e7eSjoerg   // Rd = Rs
40006f32e7eSjoerg   // Rd = #u6
40106f32e7eSjoerg   // Rd = #-1
40206f32e7eSjoerg   // if ([!]P0[.new]) Rd = #0
40306f32e7eSjoerg   // Rd = add(r29,#u6:2)
40406f32e7eSjoerg   // Rx = add(Rx,Rs)
40506f32e7eSjoerg   // P0 = cmp.eq(Rs,#u2)
40606f32e7eSjoerg   // Rdd = combine(#0,Rs)
40706f32e7eSjoerg   // Rdd = combine(Rs,#0)
40806f32e7eSjoerg   // Rdd = combine(#u2,#U2)
40906f32e7eSjoerg   // Rd = add(Rs,#1)
41006f32e7eSjoerg   // Rd = add(Rs,#-1)
41106f32e7eSjoerg   // Rd = sxth/sxtb/zxtb/zxth(Rs)
41206f32e7eSjoerg   // Rd = and(Rs,#1)
41306f32e7eSjoerg   case Hexagon::A2_addi:
41406f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
41506f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
41606f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
41706f32e7eSjoerg       // Rd = add(r29,#u6:2)
41806f32e7eSjoerg       if (HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
41906f32e7eSjoerg           inRange<6, 2>(MCI, 2)) {
42006f32e7eSjoerg         return HexagonII::HSIG_A;
42106f32e7eSjoerg       }
42206f32e7eSjoerg       // Rx = add(Rx,#s7)
42306f32e7eSjoerg       if (DstReg == SrcReg) {
42406f32e7eSjoerg         return HexagonII::HSIG_A;
42506f32e7eSjoerg       }
42606f32e7eSjoerg       // Rd = add(Rs,#1)
42706f32e7eSjoerg       // Rd = add(Rs,#-1)
42806f32e7eSjoerg       if (HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
42906f32e7eSjoerg           (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == -1)) {
43006f32e7eSjoerg         return HexagonII::HSIG_A;
43106f32e7eSjoerg       }
43206f32e7eSjoerg     }
43306f32e7eSjoerg     break;
43406f32e7eSjoerg   case Hexagon::A2_add:
43506f32e7eSjoerg     // Rx = add(Rx,Rs)
43606f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
43706f32e7eSjoerg     Src1Reg = MCI.getOperand(1).getReg();
43806f32e7eSjoerg     Src2Reg = MCI.getOperand(2).getReg();
43906f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) && (DstReg == Src1Reg) &&
44006f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg)) {
44106f32e7eSjoerg       return HexagonII::HSIG_A;
44206f32e7eSjoerg     }
44306f32e7eSjoerg     break;
44406f32e7eSjoerg   case Hexagon::A2_andir:
44506f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
44606f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
44706f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
44806f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
44906f32e7eSjoerg         (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == 255)) {
45006f32e7eSjoerg       return HexagonII::HSIG_A;
45106f32e7eSjoerg     }
45206f32e7eSjoerg     break;
45306f32e7eSjoerg   case Hexagon::A2_tfr:
45406f32e7eSjoerg     // Rd = Rs
45506f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
45606f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
45706f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
45806f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg)) {
45906f32e7eSjoerg       return HexagonII::HSIG_A;
46006f32e7eSjoerg     }
46106f32e7eSjoerg     break;
46206f32e7eSjoerg   case Hexagon::A2_tfrsi:
46306f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
46406f32e7eSjoerg 
46506f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
46606f32e7eSjoerg       return HexagonII::HSIG_A;
46706f32e7eSjoerg     }
46806f32e7eSjoerg     break;
46906f32e7eSjoerg   case Hexagon::C2_cmoveit:
47006f32e7eSjoerg   case Hexagon::C2_cmovenewit:
47106f32e7eSjoerg   case Hexagon::C2_cmoveif:
47206f32e7eSjoerg   case Hexagon::C2_cmovenewif:
47306f32e7eSjoerg     // if ([!]P0[.new]) Rd = #0
47406f32e7eSjoerg     // Actual form:
47506f32e7eSjoerg     // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16;
47606f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();  // Rd
47706f32e7eSjoerg     PredReg = MCI.getOperand(1).getReg(); // P0
47806f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
47906f32e7eSjoerg         Hexagon::P0 == PredReg && minConstant(MCI, 2) == 0) {
48006f32e7eSjoerg       return HexagonII::HSIG_A;
48106f32e7eSjoerg     }
48206f32e7eSjoerg     break;
48306f32e7eSjoerg   case Hexagon::C2_cmpeqi:
48406f32e7eSjoerg     // P0 = cmp.eq(Rs,#u2)
48506f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
48606f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
48706f32e7eSjoerg     if (Hexagon::P0 == DstReg &&
48806f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
48906f32e7eSjoerg         inRange<2>(MCI, 2)) {
49006f32e7eSjoerg       return HexagonII::HSIG_A;
49106f32e7eSjoerg     }
49206f32e7eSjoerg     break;
49306f32e7eSjoerg   case Hexagon::A2_combineii:
49406f32e7eSjoerg   case Hexagon::A4_combineii:
49506f32e7eSjoerg     // Rdd = combine(#u2,#U2)
49606f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
49706f32e7eSjoerg     if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
49806f32e7eSjoerg         inRange<2>(MCI, 1) && inRange<2>(MCI, 2)) {
49906f32e7eSjoerg       return HexagonII::HSIG_A;
50006f32e7eSjoerg     }
50106f32e7eSjoerg     break;
50206f32e7eSjoerg   case Hexagon::A4_combineri:
50306f32e7eSjoerg     // Rdd = combine(Rs,#0)
50406f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
50506f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
50606f32e7eSjoerg     if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
50706f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
50806f32e7eSjoerg         minConstant(MCI, 2) == 0) {
50906f32e7eSjoerg       return HexagonII::HSIG_A;
51006f32e7eSjoerg     }
51106f32e7eSjoerg     break;
51206f32e7eSjoerg   case Hexagon::A4_combineir:
51306f32e7eSjoerg     // Rdd = combine(#0,Rs)
51406f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
51506f32e7eSjoerg     SrcReg = MCI.getOperand(2).getReg();
51606f32e7eSjoerg     if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
51706f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
51806f32e7eSjoerg         minConstant(MCI, 1) == 0) {
51906f32e7eSjoerg       return HexagonII::HSIG_A;
52006f32e7eSjoerg     }
52106f32e7eSjoerg     break;
52206f32e7eSjoerg   case Hexagon::A2_sxtb:
52306f32e7eSjoerg   case Hexagon::A2_sxth:
52406f32e7eSjoerg   case Hexagon::A2_zxtb:
52506f32e7eSjoerg   case Hexagon::A2_zxth:
52606f32e7eSjoerg     // Rd = sxth/sxtb/zxtb/zxth(Rs)
52706f32e7eSjoerg     DstReg = MCI.getOperand(0).getReg();
52806f32e7eSjoerg     SrcReg = MCI.getOperand(1).getReg();
52906f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
53006f32e7eSjoerg         HexagonMCInstrInfo::isIntRegForSubInst(SrcReg)) {
53106f32e7eSjoerg       return HexagonII::HSIG_A;
53206f32e7eSjoerg     }
53306f32e7eSjoerg     break;
53406f32e7eSjoerg   }
53506f32e7eSjoerg 
53606f32e7eSjoerg   return HexagonII::HSIG_None;
53706f32e7eSjoerg }
53806f32e7eSjoerg 
subInstWouldBeExtended(MCInst const & potentialDuplex)53906f32e7eSjoerg bool HexagonMCInstrInfo::subInstWouldBeExtended(MCInst const &potentialDuplex) {
54006f32e7eSjoerg   unsigned DstReg, SrcReg;
54106f32e7eSjoerg   switch (potentialDuplex.getOpcode()) {
54206f32e7eSjoerg   case Hexagon::A2_addi:
54306f32e7eSjoerg     // testing for case of: Rx = add(Rx,#s7)
54406f32e7eSjoerg     DstReg = potentialDuplex.getOperand(0).getReg();
54506f32e7eSjoerg     SrcReg = potentialDuplex.getOperand(1).getReg();
54606f32e7eSjoerg     if (DstReg == SrcReg && HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
54706f32e7eSjoerg       int64_t Value;
54806f32e7eSjoerg       if (!potentialDuplex.getOperand(2).getExpr()->evaluateAsAbsolute(Value))
54906f32e7eSjoerg         return true;
55006f32e7eSjoerg       if (!isShiftedInt<7, 0>(Value))
55106f32e7eSjoerg         return true;
55206f32e7eSjoerg     }
55306f32e7eSjoerg     break;
55406f32e7eSjoerg   case Hexagon::A2_tfrsi:
55506f32e7eSjoerg     DstReg = potentialDuplex.getOperand(0).getReg();
55606f32e7eSjoerg 
55706f32e7eSjoerg     if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
55806f32e7eSjoerg       int64_t Value;
55906f32e7eSjoerg       if (!potentialDuplex.getOperand(1).getExpr()->evaluateAsAbsolute(Value))
56006f32e7eSjoerg         return true;
56106f32e7eSjoerg       // Check for case of Rd = #-1.
56206f32e7eSjoerg       if (Value == -1)
56306f32e7eSjoerg         return false;
56406f32e7eSjoerg       // Check for case of Rd = #u6.
56506f32e7eSjoerg       if (!isShiftedUInt<6, 0>(Value))
56606f32e7eSjoerg         return true;
56706f32e7eSjoerg     }
56806f32e7eSjoerg     break;
56906f32e7eSjoerg   default:
57006f32e7eSjoerg     break;
57106f32e7eSjoerg   }
57206f32e7eSjoerg   return false;
57306f32e7eSjoerg }
57406f32e7eSjoerg 
57506f32e7eSjoerg /// non-Symmetrical. See if these two instructions are fit for duplex pair.
isOrderedDuplexPair(MCInstrInfo const & MCII,MCInst const & MIa,bool ExtendedA,MCInst const & MIb,bool ExtendedB,bool bisReversable,MCSubtargetInfo const & STI)57606f32e7eSjoerg bool HexagonMCInstrInfo::isOrderedDuplexPair(MCInstrInfo const &MCII,
57706f32e7eSjoerg                                              MCInst const &MIa, bool ExtendedA,
57806f32e7eSjoerg                                              MCInst const &MIb, bool ExtendedB,
57906f32e7eSjoerg                                              bool bisReversable,
58006f32e7eSjoerg                                              MCSubtargetInfo const &STI) {
58106f32e7eSjoerg   // Slot 1 cannot be extended in duplexes PRM 10.5
58206f32e7eSjoerg   if (ExtendedA)
58306f32e7eSjoerg     return false;
58406f32e7eSjoerg   // Only A2_addi and A2_tfrsi can be extended in duplex form PRM 10.5
58506f32e7eSjoerg   if (ExtendedB) {
58606f32e7eSjoerg     unsigned Opcode = MIb.getOpcode();
58706f32e7eSjoerg     if ((Opcode != Hexagon::A2_addi) && (Opcode != Hexagon::A2_tfrsi))
58806f32e7eSjoerg       return false;
58906f32e7eSjoerg   }
59006f32e7eSjoerg   unsigned MIaG = HexagonMCInstrInfo::getDuplexCandidateGroup(MIa),
59106f32e7eSjoerg            MIbG = HexagonMCInstrInfo::getDuplexCandidateGroup(MIb);
59206f32e7eSjoerg 
59306f32e7eSjoerg   static std::map<unsigned, unsigned> subinstOpcodeMap(std::begin(opcodeData),
59406f32e7eSjoerg                                                        std::end(opcodeData));
59506f32e7eSjoerg 
59606f32e7eSjoerg   // If a duplex contains 2 insns in the same group, the insns must be
59706f32e7eSjoerg   // ordered such that the numerically smaller opcode is in slot 1.
59806f32e7eSjoerg   if ((MIaG != HexagonII::HSIG_None) && (MIaG == MIbG) && bisReversable) {
59906f32e7eSjoerg     MCInst SubInst0 = HexagonMCInstrInfo::deriveSubInst(MIa);
60006f32e7eSjoerg     MCInst SubInst1 = HexagonMCInstrInfo::deriveSubInst(MIb);
60106f32e7eSjoerg 
60206f32e7eSjoerg     unsigned zeroedSubInstS0 =
60306f32e7eSjoerg         subinstOpcodeMap.find(SubInst0.getOpcode())->second;
60406f32e7eSjoerg     unsigned zeroedSubInstS1 =
60506f32e7eSjoerg         subinstOpcodeMap.find(SubInst1.getOpcode())->second;
60606f32e7eSjoerg 
60706f32e7eSjoerg     if (zeroedSubInstS0 < zeroedSubInstS1)
60806f32e7eSjoerg       // subinstS0 (maps to slot 0) must be greater than
60906f32e7eSjoerg       // subinstS1 (maps to slot 1)
61006f32e7eSjoerg       return false;
61106f32e7eSjoerg   }
61206f32e7eSjoerg 
61306f32e7eSjoerg   // allocframe must always be in slot 0
61406f32e7eSjoerg   if (MIb.getOpcode() == Hexagon::S2_allocframe)
61506f32e7eSjoerg     return false;
61606f32e7eSjoerg 
61706f32e7eSjoerg   if ((MIaG != HexagonII::HSIG_None) && (MIbG != HexagonII::HSIG_None)) {
61806f32e7eSjoerg     // Prevent 2 instructions with extenders from duplexing
61906f32e7eSjoerg     // Note that MIb (slot1) can be extended and MIa (slot0)
62006f32e7eSjoerg     //   can never be extended
62106f32e7eSjoerg     if (subInstWouldBeExtended(MIa))
62206f32e7eSjoerg       return false;
62306f32e7eSjoerg 
62406f32e7eSjoerg     // If duplexing produces an extender, but the original did not
62506f32e7eSjoerg     //   have an extender, do not duplex.
62606f32e7eSjoerg     if (subInstWouldBeExtended(MIb) && !ExtendedB)
62706f32e7eSjoerg       return false;
62806f32e7eSjoerg   }
62906f32e7eSjoerg 
63006f32e7eSjoerg   // If jumpr r31 appears, it must be in slot 0, and never slot 1 (MIb).
63106f32e7eSjoerg   if (MIbG == HexagonII::HSIG_L2) {
63206f32e7eSjoerg     if ((MIb.getNumOperands() > 1) && MIb.getOperand(1).isReg() &&
63306f32e7eSjoerg         (MIb.getOperand(1).getReg() == Hexagon::R31))
63406f32e7eSjoerg       return false;
63506f32e7eSjoerg     if ((MIb.getNumOperands() > 0) && MIb.getOperand(0).isReg() &&
63606f32e7eSjoerg         (MIb.getOperand(0).getReg() == Hexagon::R31))
63706f32e7eSjoerg       return false;
63806f32e7eSjoerg   }
63906f32e7eSjoerg 
64006f32e7eSjoerg   if (STI.getCPU().equals_lower("hexagonv5") ||
64106f32e7eSjoerg       STI.getCPU().equals_lower("hexagonv55") ||
64206f32e7eSjoerg       STI.getCPU().equals_lower("hexagonv60")) {
64306f32e7eSjoerg     // If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
64406f32e7eSjoerg     //   therefore, not duplexable if slot 1 is a store, and slot 0 is not.
64506f32e7eSjoerg     if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
64606f32e7eSjoerg       if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
64706f32e7eSjoerg         return false;
64806f32e7eSjoerg     }
64906f32e7eSjoerg   }
65006f32e7eSjoerg 
65106f32e7eSjoerg   return (isDuplexPairMatch(MIaG, MIbG));
65206f32e7eSjoerg }
65306f32e7eSjoerg 
65406f32e7eSjoerg /// Symmetrical. See if these two instructions are fit for duplex pair.
isDuplexPair(MCInst const & MIa,MCInst const & MIb)65506f32e7eSjoerg bool HexagonMCInstrInfo::isDuplexPair(MCInst const &MIa, MCInst const &MIb) {
65606f32e7eSjoerg   unsigned MIaG = getDuplexCandidateGroup(MIa),
65706f32e7eSjoerg            MIbG = getDuplexCandidateGroup(MIb);
65806f32e7eSjoerg   return (isDuplexPairMatch(MIaG, MIbG) || isDuplexPairMatch(MIbG, MIaG));
65906f32e7eSjoerg }
66006f32e7eSjoerg 
addOps(MCInst & subInstPtr,MCInst const & Inst,unsigned opNum)66106f32e7eSjoerg inline static void addOps(MCInst &subInstPtr, MCInst const &Inst,
66206f32e7eSjoerg                           unsigned opNum) {
66306f32e7eSjoerg   if (Inst.getOperand(opNum).isReg()) {
66406f32e7eSjoerg     switch (Inst.getOperand(opNum).getReg()) {
66506f32e7eSjoerg     default:
66606f32e7eSjoerg       llvm_unreachable("Not Duplexable Register");
66706f32e7eSjoerg       break;
66806f32e7eSjoerg     case Hexagon::R0:
66906f32e7eSjoerg     case Hexagon::R1:
67006f32e7eSjoerg     case Hexagon::R2:
67106f32e7eSjoerg     case Hexagon::R3:
67206f32e7eSjoerg     case Hexagon::R4:
67306f32e7eSjoerg     case Hexagon::R5:
67406f32e7eSjoerg     case Hexagon::R6:
67506f32e7eSjoerg     case Hexagon::R7:
67606f32e7eSjoerg     case Hexagon::D0:
67706f32e7eSjoerg     case Hexagon::D1:
67806f32e7eSjoerg     case Hexagon::D2:
67906f32e7eSjoerg     case Hexagon::D3:
68006f32e7eSjoerg     case Hexagon::R16:
68106f32e7eSjoerg     case Hexagon::R17:
68206f32e7eSjoerg     case Hexagon::R18:
68306f32e7eSjoerg     case Hexagon::R19:
68406f32e7eSjoerg     case Hexagon::R20:
68506f32e7eSjoerg     case Hexagon::R21:
68606f32e7eSjoerg     case Hexagon::R22:
68706f32e7eSjoerg     case Hexagon::R23:
68806f32e7eSjoerg     case Hexagon::D8:
68906f32e7eSjoerg     case Hexagon::D9:
69006f32e7eSjoerg     case Hexagon::D10:
69106f32e7eSjoerg     case Hexagon::D11:
69206f32e7eSjoerg     case Hexagon::P0:
69306f32e7eSjoerg       subInstPtr.addOperand(Inst.getOperand(opNum));
69406f32e7eSjoerg       break;
69506f32e7eSjoerg     }
69606f32e7eSjoerg   } else
69706f32e7eSjoerg     subInstPtr.addOperand(Inst.getOperand(opNum));
69806f32e7eSjoerg }
69906f32e7eSjoerg 
deriveSubInst(MCInst const & Inst)70006f32e7eSjoerg MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
70106f32e7eSjoerg   MCInst Result;
70206f32e7eSjoerg   bool Absolute;
70306f32e7eSjoerg   int64_t Value;
70406f32e7eSjoerg   switch (Inst.getOpcode()) {
70506f32e7eSjoerg   default:
70606f32e7eSjoerg     // dbgs() << "opcode: "<< Inst->getOpcode() << "\n";
70706f32e7eSjoerg     llvm_unreachable("Unimplemented subinstruction \n");
70806f32e7eSjoerg     break;
70906f32e7eSjoerg   case Hexagon::A2_addi:
71006f32e7eSjoerg     Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
71106f32e7eSjoerg     if (Absolute) {
71206f32e7eSjoerg       if (Value == 1) {
71306f32e7eSjoerg         Result.setOpcode(Hexagon::SA1_inc);
71406f32e7eSjoerg         addOps(Result, Inst, 0);
71506f32e7eSjoerg         addOps(Result, Inst, 1);
71606f32e7eSjoerg         break;
71706f32e7eSjoerg       } //  1,2 SUBInst $Rd = add($Rs, #1)
71806f32e7eSjoerg       if (Value == -1) {
71906f32e7eSjoerg         Result.setOpcode(Hexagon::SA1_dec);
72006f32e7eSjoerg         addOps(Result, Inst, 0);
72106f32e7eSjoerg         addOps(Result, Inst, 1);
72206f32e7eSjoerg         addOps(Result, Inst, 2);
72306f32e7eSjoerg         break;
72406f32e7eSjoerg       } //  1,2 SUBInst $Rd = add($Rs,#-1)
72506f32e7eSjoerg       if (Inst.getOperand(1).getReg() == Hexagon::R29) {
72606f32e7eSjoerg         Result.setOpcode(Hexagon::SA1_addsp);
72706f32e7eSjoerg         addOps(Result, Inst, 0);
72806f32e7eSjoerg         addOps(Result, Inst, 2);
72906f32e7eSjoerg         break;
73006f32e7eSjoerg       } //  1,3 SUBInst $Rd = add(r29, #$u6_2)
73106f32e7eSjoerg     }
73206f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_addi);
73306f32e7eSjoerg     addOps(Result, Inst, 0);
73406f32e7eSjoerg     addOps(Result, Inst, 1);
73506f32e7eSjoerg     addOps(Result, Inst, 2);
73606f32e7eSjoerg     break; //    1,2,3 SUBInst $Rx = add($Rx, #$s7)
73706f32e7eSjoerg   case Hexagon::A2_add:
73806f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_addrx);
73906f32e7eSjoerg     addOps(Result, Inst, 0);
74006f32e7eSjoerg     addOps(Result, Inst, 1);
74106f32e7eSjoerg     addOps(Result, Inst, 2);
74206f32e7eSjoerg     break; //    1,2,3 SUBInst $Rx = add($_src_, $Rs)
74306f32e7eSjoerg   case Hexagon::S2_allocframe:
74406f32e7eSjoerg     Result.setOpcode(Hexagon::SS2_allocframe);
74506f32e7eSjoerg     addOps(Result, Inst, 2);
74606f32e7eSjoerg     break; //    1 SUBInst allocframe(#$u5_3)
74706f32e7eSjoerg   case Hexagon::A2_andir:
74806f32e7eSjoerg     if (minConstant(Inst, 2) == 255) {
74906f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_zxtb);
75006f32e7eSjoerg       addOps(Result, Inst, 0);
75106f32e7eSjoerg       addOps(Result, Inst, 1);
75206f32e7eSjoerg       break; //    1,2    $Rd = and($Rs, #255)
75306f32e7eSjoerg     } else {
75406f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_and1);
75506f32e7eSjoerg       addOps(Result, Inst, 0);
75606f32e7eSjoerg       addOps(Result, Inst, 1);
75706f32e7eSjoerg       break; //    1,2 SUBInst $Rd = and($Rs, #1)
75806f32e7eSjoerg     }
75906f32e7eSjoerg   case Hexagon::C2_cmpeqi:
76006f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_cmpeqi);
76106f32e7eSjoerg     addOps(Result, Inst, 1);
76206f32e7eSjoerg     addOps(Result, Inst, 2);
76306f32e7eSjoerg     break; //    2,3 SUBInst p0 = cmp.eq($Rs, #$u2)
76406f32e7eSjoerg   case Hexagon::A4_combineii:
76506f32e7eSjoerg   case Hexagon::A2_combineii:
76606f32e7eSjoerg     Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
76706f32e7eSjoerg     assert(Absolute);(void)Absolute;
76806f32e7eSjoerg     if (Value == 1) {
76906f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_combine1i);
77006f32e7eSjoerg       addOps(Result, Inst, 0);
77106f32e7eSjoerg       addOps(Result, Inst, 2);
77206f32e7eSjoerg       break; //  1,3 SUBInst $Rdd = combine(#1, #$u2)
77306f32e7eSjoerg     }
77406f32e7eSjoerg     if (Value == 3) {
77506f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_combine3i);
77606f32e7eSjoerg       addOps(Result, Inst, 0);
77706f32e7eSjoerg       addOps(Result, Inst, 2);
77806f32e7eSjoerg       break; //  1,3 SUBInst $Rdd = combine(#3, #$u2)
77906f32e7eSjoerg     }
78006f32e7eSjoerg     if (Value == 0) {
78106f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_combine0i);
78206f32e7eSjoerg       addOps(Result, Inst, 0);
78306f32e7eSjoerg       addOps(Result, Inst, 2);
78406f32e7eSjoerg       break; //  1,3 SUBInst $Rdd = combine(#0, #$u2)
78506f32e7eSjoerg     }
78606f32e7eSjoerg     if (Value == 2) {
78706f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_combine2i);
78806f32e7eSjoerg       addOps(Result, Inst, 0);
78906f32e7eSjoerg       addOps(Result, Inst, 2);
79006f32e7eSjoerg       break; //  1,3 SUBInst $Rdd = combine(#2, #$u2)
79106f32e7eSjoerg     }
79206f32e7eSjoerg     break;
79306f32e7eSjoerg   case Hexagon::A4_combineir:
79406f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_combinezr);
79506f32e7eSjoerg     addOps(Result, Inst, 0);
79606f32e7eSjoerg     addOps(Result, Inst, 2);
79706f32e7eSjoerg     break; //    1,3 SUBInst $Rdd = combine(#0, $Rs)
79806f32e7eSjoerg   case Hexagon::A4_combineri:
79906f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_combinerz);
80006f32e7eSjoerg     addOps(Result, Inst, 0);
80106f32e7eSjoerg     addOps(Result, Inst, 1);
80206f32e7eSjoerg     break; //    1,2 SUBInst $Rdd = combine($Rs, #0)
80306f32e7eSjoerg   case Hexagon::L4_return_tnew_pnt:
80406f32e7eSjoerg   case Hexagon::L4_return_tnew_pt:
80506f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_return_tnew);
80606f32e7eSjoerg     break; //    none  SUBInst if (p0.new) dealloc_return:nt
80706f32e7eSjoerg   case Hexagon::L4_return_fnew_pnt:
80806f32e7eSjoerg   case Hexagon::L4_return_fnew_pt:
80906f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_return_fnew);
81006f32e7eSjoerg     break; //    none  SUBInst if (!p0.new) dealloc_return:nt
81106f32e7eSjoerg   case Hexagon::L4_return_f:
81206f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_return_f);
81306f32e7eSjoerg     break; //    none  SUBInst if (!p0) dealloc_return
81406f32e7eSjoerg   case Hexagon::L4_return_t:
81506f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_return_t);
81606f32e7eSjoerg     break; //    none  SUBInst if (p0) dealloc_return
81706f32e7eSjoerg   case Hexagon::L4_return:
81806f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_return);
81906f32e7eSjoerg     break; //    none  SUBInst dealloc_return
82006f32e7eSjoerg   case Hexagon::L2_deallocframe:
82106f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_deallocframe);
82206f32e7eSjoerg     break; //    none  SUBInst deallocframe
82306f32e7eSjoerg   case Hexagon::EH_RETURN_JMPR:
82406f32e7eSjoerg   case Hexagon::J2_jumpr:
82506f32e7eSjoerg   case Hexagon::PS_jmpret:
82606f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_jumpr31);
82706f32e7eSjoerg     break; //    none  SUBInst jumpr r31
82806f32e7eSjoerg   case Hexagon::J2_jumprf:
82906f32e7eSjoerg   case Hexagon::PS_jmpretf:
83006f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_jumpr31_f);
83106f32e7eSjoerg     break; //    none  SUBInst if (!p0) jumpr r31
83206f32e7eSjoerg   case Hexagon::J2_jumprfnew:
83306f32e7eSjoerg   case Hexagon::J2_jumprfnewpt:
83406f32e7eSjoerg   case Hexagon::PS_jmpretfnewpt:
83506f32e7eSjoerg   case Hexagon::PS_jmpretfnew:
83606f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_jumpr31_fnew);
83706f32e7eSjoerg     break; //    none  SUBInst if (!p0.new) jumpr:nt r31
83806f32e7eSjoerg   case Hexagon::J2_jumprt:
83906f32e7eSjoerg   case Hexagon::PS_jmprett:
84006f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_jumpr31_t);
84106f32e7eSjoerg     break; //    none  SUBInst if (p0) jumpr r31
84206f32e7eSjoerg   case Hexagon::J2_jumprtnew:
84306f32e7eSjoerg   case Hexagon::J2_jumprtnewpt:
84406f32e7eSjoerg   case Hexagon::PS_jmprettnewpt:
84506f32e7eSjoerg   case Hexagon::PS_jmprettnew:
84606f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_jumpr31_tnew);
84706f32e7eSjoerg     break; //    none  SUBInst if (p0.new) jumpr:nt r31
84806f32e7eSjoerg   case Hexagon::L2_loadrb_io:
84906f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_loadrb_io);
85006f32e7eSjoerg     addOps(Result, Inst, 0);
85106f32e7eSjoerg     addOps(Result, Inst, 1);
85206f32e7eSjoerg     addOps(Result, Inst, 2);
85306f32e7eSjoerg     break; //    1,2,3 SUBInst $Rd = memb($Rs + #$u3_0)
85406f32e7eSjoerg   case Hexagon::L2_loadrd_io:
85506f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_loadrd_sp);
85606f32e7eSjoerg     addOps(Result, Inst, 0);
85706f32e7eSjoerg     addOps(Result, Inst, 2);
85806f32e7eSjoerg     break; //    1,3 SUBInst $Rdd = memd(r29 + #$u5_3)
85906f32e7eSjoerg   case Hexagon::L2_loadrh_io:
86006f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_loadrh_io);
86106f32e7eSjoerg     addOps(Result, Inst, 0);
86206f32e7eSjoerg     addOps(Result, Inst, 1);
86306f32e7eSjoerg     addOps(Result, Inst, 2);
86406f32e7eSjoerg     break; //    1,2,3 SUBInst $Rd = memh($Rs + #$u3_1)
86506f32e7eSjoerg   case Hexagon::L2_loadrub_io:
86606f32e7eSjoerg     Result.setOpcode(Hexagon::SL1_loadrub_io);
86706f32e7eSjoerg     addOps(Result, Inst, 0);
86806f32e7eSjoerg     addOps(Result, Inst, 1);
86906f32e7eSjoerg     addOps(Result, Inst, 2);
87006f32e7eSjoerg     break; //    1,2,3 SUBInst $Rd = memub($Rs + #$u4_0)
87106f32e7eSjoerg   case Hexagon::L2_loadruh_io:
87206f32e7eSjoerg     Result.setOpcode(Hexagon::SL2_loadruh_io);
87306f32e7eSjoerg     addOps(Result, Inst, 0);
87406f32e7eSjoerg     addOps(Result, Inst, 1);
87506f32e7eSjoerg     addOps(Result, Inst, 2);
87606f32e7eSjoerg     break; //    1,2,3 SUBInst $Rd = memuh($Rs + #$u3_1)
87706f32e7eSjoerg   case Hexagon::L2_loadri_io:
87806f32e7eSjoerg     if (Inst.getOperand(1).getReg() == Hexagon::R29) {
87906f32e7eSjoerg       Result.setOpcode(Hexagon::SL2_loadri_sp);
88006f32e7eSjoerg       addOps(Result, Inst, 0);
88106f32e7eSjoerg       addOps(Result, Inst, 2);
88206f32e7eSjoerg       break; //  2 1,3 SUBInst $Rd = memw(r29 + #$u5_2)
88306f32e7eSjoerg     } else {
88406f32e7eSjoerg       Result.setOpcode(Hexagon::SL1_loadri_io);
88506f32e7eSjoerg       addOps(Result, Inst, 0);
88606f32e7eSjoerg       addOps(Result, Inst, 1);
88706f32e7eSjoerg       addOps(Result, Inst, 2);
88806f32e7eSjoerg       break; //    1,2,3 SUBInst $Rd = memw($Rs + #$u4_2)
88906f32e7eSjoerg     }
89006f32e7eSjoerg   case Hexagon::S4_storeirb_io:
89106f32e7eSjoerg     Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
89206f32e7eSjoerg     assert(Absolute);(void)Absolute;
89306f32e7eSjoerg     if (Value == 0) {
89406f32e7eSjoerg       Result.setOpcode(Hexagon::SS2_storebi0);
89506f32e7eSjoerg       addOps(Result, Inst, 0);
89606f32e7eSjoerg       addOps(Result, Inst, 1);
89706f32e7eSjoerg       break; //    1,2 SUBInst memb($Rs + #$u4_0)=#0
89806f32e7eSjoerg     } else if (Value == 1) {
89906f32e7eSjoerg       Result.setOpcode(Hexagon::SS2_storebi1);
90006f32e7eSjoerg       addOps(Result, Inst, 0);
90106f32e7eSjoerg       addOps(Result, Inst, 1);
90206f32e7eSjoerg       break; //  2 1,2 SUBInst memb($Rs + #$u4_0)=#1
90306f32e7eSjoerg     }
90406f32e7eSjoerg     break;
90506f32e7eSjoerg   case Hexagon::S2_storerb_io:
90606f32e7eSjoerg     Result.setOpcode(Hexagon::SS1_storeb_io);
90706f32e7eSjoerg     addOps(Result, Inst, 0);
90806f32e7eSjoerg     addOps(Result, Inst, 1);
90906f32e7eSjoerg     addOps(Result, Inst, 2);
91006f32e7eSjoerg     break; //    1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
91106f32e7eSjoerg   case Hexagon::S2_storerd_io:
91206f32e7eSjoerg     Result.setOpcode(Hexagon::SS2_stored_sp);
91306f32e7eSjoerg     addOps(Result, Inst, 1);
91406f32e7eSjoerg     addOps(Result, Inst, 2);
91506f32e7eSjoerg     break; //    2,3 SUBInst memd(r29 + #$s6_3) = $Rtt
91606f32e7eSjoerg   case Hexagon::S2_storerh_io:
91706f32e7eSjoerg     Result.setOpcode(Hexagon::SS2_storeh_io);
91806f32e7eSjoerg     addOps(Result, Inst, 0);
91906f32e7eSjoerg     addOps(Result, Inst, 1);
92006f32e7eSjoerg     addOps(Result, Inst, 2);
92106f32e7eSjoerg     break; //    1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
92206f32e7eSjoerg   case Hexagon::S4_storeiri_io:
92306f32e7eSjoerg     Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
92406f32e7eSjoerg     assert(Absolute);(void)Absolute;
92506f32e7eSjoerg     if (Value == 0) {
92606f32e7eSjoerg       Result.setOpcode(Hexagon::SS2_storewi0);
92706f32e7eSjoerg       addOps(Result, Inst, 0);
92806f32e7eSjoerg       addOps(Result, Inst, 1);
92906f32e7eSjoerg       break; //  3 1,2 SUBInst memw($Rs + #$u4_2)=#0
93006f32e7eSjoerg     } else if (Value == 1) {
93106f32e7eSjoerg       Result.setOpcode(Hexagon::SS2_storewi1);
93206f32e7eSjoerg       addOps(Result, Inst, 0);
93306f32e7eSjoerg       addOps(Result, Inst, 1);
93406f32e7eSjoerg       break; //  3 1,2 SUBInst memw($Rs + #$u4_2)=#1
93506f32e7eSjoerg     } else if (Inst.getOperand(0).getReg() == Hexagon::R29) {
93606f32e7eSjoerg       Result.setOpcode(Hexagon::SS2_storew_sp);
93706f32e7eSjoerg       addOps(Result, Inst, 1);
93806f32e7eSjoerg       addOps(Result, Inst, 2);
93906f32e7eSjoerg       break; //  1 2,3 SUBInst memw(r29 + #$u5_2) = $Rt
94006f32e7eSjoerg     }
94106f32e7eSjoerg     break;
94206f32e7eSjoerg   case Hexagon::S2_storeri_io:
94306f32e7eSjoerg     if (Inst.getOperand(0).getReg() == Hexagon::R29) {
94406f32e7eSjoerg       Result.setOpcode(Hexagon::SS2_storew_sp);
94506f32e7eSjoerg       addOps(Result, Inst, 1);
94606f32e7eSjoerg       addOps(Result, Inst, 2); //  1,2,3 SUBInst memw(sp + #$u5_2) = $Rt
94706f32e7eSjoerg     } else {
94806f32e7eSjoerg       Result.setOpcode(Hexagon::SS1_storew_io);
94906f32e7eSjoerg       addOps(Result, Inst, 0);
95006f32e7eSjoerg       addOps(Result, Inst, 1);
95106f32e7eSjoerg       addOps(Result, Inst, 2); //  1,2,3 SUBInst memw($Rs + #$u4_2) = $Rt
95206f32e7eSjoerg     }
95306f32e7eSjoerg     break;
95406f32e7eSjoerg   case Hexagon::A2_sxtb:
95506f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_sxtb);
95606f32e7eSjoerg     addOps(Result, Inst, 0);
95706f32e7eSjoerg     addOps(Result, Inst, 1);
95806f32e7eSjoerg     break; //  1,2 SUBInst $Rd = sxtb($Rs)
95906f32e7eSjoerg   case Hexagon::A2_sxth:
96006f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_sxth);
96106f32e7eSjoerg     addOps(Result, Inst, 0);
96206f32e7eSjoerg     addOps(Result, Inst, 1);
96306f32e7eSjoerg     break; //  1,2 SUBInst $Rd = sxth($Rs)
96406f32e7eSjoerg   case Hexagon::A2_tfr:
96506f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_tfr);
96606f32e7eSjoerg     addOps(Result, Inst, 0);
96706f32e7eSjoerg     addOps(Result, Inst, 1);
96806f32e7eSjoerg     break; //  1,2 SUBInst $Rd = $Rs
96906f32e7eSjoerg   case Hexagon::C2_cmovenewif:
97006f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_clrfnew);
97106f32e7eSjoerg     addOps(Result, Inst, 0);
97206f32e7eSjoerg     addOps(Result, Inst, 1);
97306f32e7eSjoerg     break; //  2 SUBInst if (!p0.new) $Rd = #0
97406f32e7eSjoerg   case Hexagon::C2_cmovenewit:
97506f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_clrtnew);
97606f32e7eSjoerg     addOps(Result, Inst, 0);
97706f32e7eSjoerg     addOps(Result, Inst, 1);
97806f32e7eSjoerg     break; //  2 SUBInst if (p0.new) $Rd = #0
97906f32e7eSjoerg   case Hexagon::C2_cmoveif:
98006f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_clrf);
98106f32e7eSjoerg     addOps(Result, Inst, 0);
98206f32e7eSjoerg     addOps(Result, Inst, 1);
98306f32e7eSjoerg     break; //  2 SUBInst if (!p0) $Rd = #0
98406f32e7eSjoerg   case Hexagon::C2_cmoveit:
98506f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_clrt);
98606f32e7eSjoerg     addOps(Result, Inst, 0);
98706f32e7eSjoerg     addOps(Result, Inst, 1);
98806f32e7eSjoerg     break; //  2 SUBInst if (p0) $Rd = #0
98906f32e7eSjoerg   case Hexagon::A2_tfrsi:
99006f32e7eSjoerg     Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
99106f32e7eSjoerg     if (Absolute && Value == -1) {
99206f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_setin1);
99306f32e7eSjoerg       addOps(Result, Inst, 0);
99406f32e7eSjoerg       addOps(Result, Inst, 1);
99506f32e7eSjoerg       break; //  2 1 SUBInst $Rd = #-1
99606f32e7eSjoerg     } else {
99706f32e7eSjoerg       Result.setOpcode(Hexagon::SA1_seti);
99806f32e7eSjoerg       addOps(Result, Inst, 0);
99906f32e7eSjoerg       addOps(Result, Inst, 1);
100006f32e7eSjoerg       break; //    1,2 SUBInst $Rd = #$u6
100106f32e7eSjoerg     }
100206f32e7eSjoerg   case Hexagon::A2_zxtb:
100306f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_zxtb);
100406f32e7eSjoerg     addOps(Result, Inst, 0);
100506f32e7eSjoerg     addOps(Result, Inst, 1);
100606f32e7eSjoerg     break; //    1,2    $Rd = and($Rs, #255)
100706f32e7eSjoerg 
100806f32e7eSjoerg   case Hexagon::A2_zxth:
100906f32e7eSjoerg     Result.setOpcode(Hexagon::SA1_zxth);
101006f32e7eSjoerg     addOps(Result, Inst, 0);
101106f32e7eSjoerg     addOps(Result, Inst, 1);
101206f32e7eSjoerg     break; //    1,2 SUBInst $Rd = zxth($Rs)
101306f32e7eSjoerg   }
101406f32e7eSjoerg   return Result;
101506f32e7eSjoerg }
101606f32e7eSjoerg 
isStoreInst(unsigned opCode)101706f32e7eSjoerg static bool isStoreInst(unsigned opCode) {
101806f32e7eSjoerg   switch (opCode) {
101906f32e7eSjoerg   case Hexagon::S2_storeri_io:
102006f32e7eSjoerg   case Hexagon::S2_storerb_io:
102106f32e7eSjoerg   case Hexagon::S2_storerh_io:
102206f32e7eSjoerg   case Hexagon::S2_storerd_io:
102306f32e7eSjoerg   case Hexagon::S4_storeiri_io:
102406f32e7eSjoerg   case Hexagon::S4_storeirb_io:
102506f32e7eSjoerg   case Hexagon::S2_allocframe:
102606f32e7eSjoerg     return true;
102706f32e7eSjoerg   default:
102806f32e7eSjoerg     return false;
102906f32e7eSjoerg   }
103006f32e7eSjoerg }
103106f32e7eSjoerg 
103206f32e7eSjoerg SmallVector<DuplexCandidate, 8>
getDuplexPossibilties(MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst const & MCB)103306f32e7eSjoerg HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
103406f32e7eSjoerg                                           MCSubtargetInfo const &STI,
103506f32e7eSjoerg                                           MCInst const &MCB) {
103606f32e7eSjoerg   assert(isBundle(MCB));
103706f32e7eSjoerg   SmallVector<DuplexCandidate, 8> duplexToTry;
103806f32e7eSjoerg   // Use an "order matters" version of isDuplexPair.
103906f32e7eSjoerg   unsigned numInstrInPacket = MCB.getNumOperands();
104006f32e7eSjoerg 
104106f32e7eSjoerg   for (unsigned distance = 1; distance < numInstrInPacket; ++distance) {
104206f32e7eSjoerg     for (unsigned j = HexagonMCInstrInfo::bundleInstructionsOffset,
104306f32e7eSjoerg                   k = j + distance;
104406f32e7eSjoerg          (j < numInstrInPacket) && (k < numInstrInPacket); ++j, ++k) {
104506f32e7eSjoerg 
104606f32e7eSjoerg       // Check if reversible.
104706f32e7eSjoerg       bool bisReversable = true;
104806f32e7eSjoerg       if (isStoreInst(MCB.getOperand(j).getInst()->getOpcode()) &&
104906f32e7eSjoerg           isStoreInst(MCB.getOperand(k).getInst()->getOpcode())) {
105006f32e7eSjoerg         LLVM_DEBUG(dbgs() << "skip out of order write pair: " << k << "," << j
105106f32e7eSjoerg                           << "\n");
105206f32e7eSjoerg         bisReversable = false;
105306f32e7eSjoerg       }
105406f32e7eSjoerg       if (HexagonMCInstrInfo::isMemReorderDisabled(MCB)) // }:mem_noshuf
105506f32e7eSjoerg         bisReversable = false;
105606f32e7eSjoerg 
105706f32e7eSjoerg       // Try in order.
105806f32e7eSjoerg       if (isOrderedDuplexPair(
105906f32e7eSjoerg               MCII, *MCB.getOperand(k).getInst(),
106006f32e7eSjoerg               HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
106106f32e7eSjoerg               *MCB.getOperand(j).getInst(),
106206f32e7eSjoerg               HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
106306f32e7eSjoerg               bisReversable, STI)) {
106406f32e7eSjoerg         // Get iClass.
106506f32e7eSjoerg         unsigned iClass = iClassOfDuplexPair(
106606f32e7eSjoerg             getDuplexCandidateGroup(*MCB.getOperand(k).getInst()),
106706f32e7eSjoerg             getDuplexCandidateGroup(*MCB.getOperand(j).getInst()));
106806f32e7eSjoerg 
106906f32e7eSjoerg         // Save off pairs for duplex checking.
107006f32e7eSjoerg         duplexToTry.push_back(DuplexCandidate(j, k, iClass));
107106f32e7eSjoerg         LLVM_DEBUG(dbgs() << "adding pair: " << j << "," << k << ":"
107206f32e7eSjoerg                           << MCB.getOperand(j).getInst()->getOpcode() << ","
107306f32e7eSjoerg                           << MCB.getOperand(k).getInst()->getOpcode() << "\n");
107406f32e7eSjoerg         continue;
107506f32e7eSjoerg       } else {
107606f32e7eSjoerg         LLVM_DEBUG(dbgs() << "skipping pair: " << j << "," << k << ":"
107706f32e7eSjoerg                           << MCB.getOperand(j).getInst()->getOpcode() << ","
107806f32e7eSjoerg                           << MCB.getOperand(k).getInst()->getOpcode() << "\n");
107906f32e7eSjoerg       }
108006f32e7eSjoerg 
108106f32e7eSjoerg       // Try reverse.
108206f32e7eSjoerg       if (bisReversable) {
108306f32e7eSjoerg         if (isOrderedDuplexPair(
108406f32e7eSjoerg                 MCII, *MCB.getOperand(j).getInst(),
108506f32e7eSjoerg                 HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
108606f32e7eSjoerg                 *MCB.getOperand(k).getInst(),
108706f32e7eSjoerg                 HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
108806f32e7eSjoerg                 bisReversable, STI)) {
108906f32e7eSjoerg           // Get iClass.
109006f32e7eSjoerg           unsigned iClass = iClassOfDuplexPair(
109106f32e7eSjoerg               getDuplexCandidateGroup(*MCB.getOperand(j).getInst()),
109206f32e7eSjoerg               getDuplexCandidateGroup(*MCB.getOperand(k).getInst()));
109306f32e7eSjoerg 
109406f32e7eSjoerg           // Save off pairs for duplex checking.
109506f32e7eSjoerg           duplexToTry.push_back(DuplexCandidate(k, j, iClass));
109606f32e7eSjoerg           LLVM_DEBUG(dbgs()
109706f32e7eSjoerg                      << "adding pair:" << k << "," << j << ":"
109806f32e7eSjoerg                      << MCB.getOperand(j).getInst()->getOpcode() << ","
109906f32e7eSjoerg                      << MCB.getOperand(k).getInst()->getOpcode() << "\n");
110006f32e7eSjoerg         } else {
110106f32e7eSjoerg           LLVM_DEBUG(dbgs()
110206f32e7eSjoerg                      << "skipping pair: " << k << "," << j << ":"
110306f32e7eSjoerg                      << MCB.getOperand(j).getInst()->getOpcode() << ","
110406f32e7eSjoerg                      << MCB.getOperand(k).getInst()->getOpcode() << "\n");
110506f32e7eSjoerg         }
110606f32e7eSjoerg       }
110706f32e7eSjoerg     }
110806f32e7eSjoerg   }
110906f32e7eSjoerg   return duplexToTry;
111006f32e7eSjoerg }
1111