10b57cec5SDimitry Andric //===- HexagonMCDuplexInfo.cpp - Instruction bundle checking --------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This implements duplexing of instructions to reduce code size
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric
135ffd83dbSDimitry Andric #include "HexagonMCExpr.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/HexagonBaseInfo.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCTargetDesc.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
190b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
200b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
210b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric #include <cassert>
240b57cec5SDimitry Andric #include <cstdint>
250b57cec5SDimitry Andric #include <iterator>
260b57cec5SDimitry Andric #include <map>
270b57cec5SDimitry Andric #include <utility>
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric using namespace llvm;
300b57cec5SDimitry Andric using namespace Hexagon;
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #define DEBUG_TYPE "hexagon-mcduplex-info"
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric // pair table of subInstructions with opcodes
350b57cec5SDimitry Andric static const std::pair<unsigned, unsigned> opcodeData[] = {
360b57cec5SDimitry Andric std::make_pair((unsigned)SA1_addi, 0),
370b57cec5SDimitry Andric std::make_pair((unsigned)SA1_addrx, 6144),
380b57cec5SDimitry Andric std::make_pair((unsigned)SA1_addsp, 3072),
390b57cec5SDimitry Andric std::make_pair((unsigned)SA1_and1, 4608),
400b57cec5SDimitry Andric std::make_pair((unsigned)SA1_clrf, 6768),
410b57cec5SDimitry Andric std::make_pair((unsigned)SA1_clrfnew, 6736),
420b57cec5SDimitry Andric std::make_pair((unsigned)SA1_clrt, 6752),
430b57cec5SDimitry Andric std::make_pair((unsigned)SA1_clrtnew, 6720),
440b57cec5SDimitry Andric std::make_pair((unsigned)SA1_cmpeqi, 6400),
450b57cec5SDimitry Andric std::make_pair((unsigned)SA1_combine0i, 7168),
460b57cec5SDimitry Andric std::make_pair((unsigned)SA1_combine1i, 7176),
470b57cec5SDimitry Andric std::make_pair((unsigned)SA1_combine2i, 7184),
480b57cec5SDimitry Andric std::make_pair((unsigned)SA1_combine3i, 7192),
490b57cec5SDimitry Andric std::make_pair((unsigned)SA1_combinerz, 7432),
500b57cec5SDimitry Andric std::make_pair((unsigned)SA1_combinezr, 7424),
510b57cec5SDimitry Andric std::make_pair((unsigned)SA1_dec, 4864),
520b57cec5SDimitry Andric std::make_pair((unsigned)SA1_inc, 4352),
530b57cec5SDimitry Andric std::make_pair((unsigned)SA1_seti, 2048),
540b57cec5SDimitry Andric std::make_pair((unsigned)SA1_setin1, 6656),
550b57cec5SDimitry Andric std::make_pair((unsigned)SA1_sxtb, 5376),
560b57cec5SDimitry Andric std::make_pair((unsigned)SA1_sxth, 5120),
570b57cec5SDimitry Andric std::make_pair((unsigned)SA1_tfr, 4096),
580b57cec5SDimitry Andric std::make_pair((unsigned)SA1_zxtb, 5888),
590b57cec5SDimitry Andric std::make_pair((unsigned)SA1_zxth, 5632),
600b57cec5SDimitry Andric std::make_pair((unsigned)SL1_loadri_io, 0),
610b57cec5SDimitry Andric std::make_pair((unsigned)SL1_loadrub_io, 4096),
620b57cec5SDimitry Andric std::make_pair((unsigned)SL2_deallocframe, 7936),
630b57cec5SDimitry Andric std::make_pair((unsigned)SL2_jumpr31, 8128),
640b57cec5SDimitry Andric std::make_pair((unsigned)SL2_jumpr31_f, 8133),
650b57cec5SDimitry Andric std::make_pair((unsigned)SL2_jumpr31_fnew, 8135),
660b57cec5SDimitry Andric std::make_pair((unsigned)SL2_jumpr31_t, 8132),
670b57cec5SDimitry Andric std::make_pair((unsigned)SL2_jumpr31_tnew, 8134),
680b57cec5SDimitry Andric std::make_pair((unsigned)SL2_loadrb_io, 4096),
690b57cec5SDimitry Andric std::make_pair((unsigned)SL2_loadrd_sp, 7680),
700b57cec5SDimitry Andric std::make_pair((unsigned)SL2_loadrh_io, 0),
710b57cec5SDimitry Andric std::make_pair((unsigned)SL2_loadri_sp, 7168),
720b57cec5SDimitry Andric std::make_pair((unsigned)SL2_loadruh_io, 2048),
730b57cec5SDimitry Andric std::make_pair((unsigned)SL2_return, 8000),
740b57cec5SDimitry Andric std::make_pair((unsigned)SL2_return_f, 8005),
750b57cec5SDimitry Andric std::make_pair((unsigned)SL2_return_fnew, 8007),
760b57cec5SDimitry Andric std::make_pair((unsigned)SL2_return_t, 8004),
770b57cec5SDimitry Andric std::make_pair((unsigned)SL2_return_tnew, 8006),
780b57cec5SDimitry Andric std::make_pair((unsigned)SS1_storeb_io, 4096),
790b57cec5SDimitry Andric std::make_pair((unsigned)SS1_storew_io, 0),
800b57cec5SDimitry Andric std::make_pair((unsigned)SS2_allocframe, 7168),
810b57cec5SDimitry Andric std::make_pair((unsigned)SS2_storebi0, 4608),
820b57cec5SDimitry Andric std::make_pair((unsigned)SS2_storebi1, 4864),
830b57cec5SDimitry Andric std::make_pair((unsigned)SS2_stored_sp, 2560),
840b57cec5SDimitry Andric std::make_pair((unsigned)SS2_storeh_io, 0),
850b57cec5SDimitry Andric std::make_pair((unsigned)SS2_storew_sp, 2048),
860b57cec5SDimitry Andric std::make_pair((unsigned)SS2_storewi0, 4096),
870b57cec5SDimitry Andric std::make_pair((unsigned)SS2_storewi1, 4352)};
880b57cec5SDimitry Andric
isDuplexPairMatch(unsigned Ga,unsigned Gb)890b57cec5SDimitry Andric bool HexagonMCInstrInfo::isDuplexPairMatch(unsigned Ga, unsigned Gb) {
900b57cec5SDimitry Andric switch (Ga) {
910b57cec5SDimitry Andric case HexagonII::HSIG_None:
920b57cec5SDimitry Andric default:
930b57cec5SDimitry Andric return false;
940b57cec5SDimitry Andric case HexagonII::HSIG_L1:
950b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_A);
960b57cec5SDimitry Andric case HexagonII::HSIG_L2:
970b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
980b57cec5SDimitry Andric Gb == HexagonII::HSIG_A);
990b57cec5SDimitry Andric case HexagonII::HSIG_S1:
1000b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
1010b57cec5SDimitry Andric Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_A);
1020b57cec5SDimitry Andric case HexagonII::HSIG_S2:
1030b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_L1 || Gb == HexagonII::HSIG_L2 ||
1040b57cec5SDimitry Andric Gb == HexagonII::HSIG_S1 || Gb == HexagonII::HSIG_S2 ||
1050b57cec5SDimitry Andric Gb == HexagonII::HSIG_A);
1060b57cec5SDimitry Andric case HexagonII::HSIG_A:
1070b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_A);
1080b57cec5SDimitry Andric case HexagonII::HSIG_Compound:
1090b57cec5SDimitry Andric return (Gb == HexagonII::HSIG_Compound);
1100b57cec5SDimitry Andric }
1110b57cec5SDimitry Andric return false;
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric
iClassOfDuplexPair(unsigned Ga,unsigned Gb)1140b57cec5SDimitry Andric unsigned HexagonMCInstrInfo::iClassOfDuplexPair(unsigned Ga, unsigned Gb) {
1150b57cec5SDimitry Andric switch (Ga) {
1160b57cec5SDimitry Andric case HexagonII::HSIG_None:
1170b57cec5SDimitry Andric default:
1180b57cec5SDimitry Andric break;
1190b57cec5SDimitry Andric case HexagonII::HSIG_L1:
1200b57cec5SDimitry Andric switch (Gb) {
1210b57cec5SDimitry Andric default:
1220b57cec5SDimitry Andric break;
1230b57cec5SDimitry Andric case HexagonII::HSIG_L1:
1240b57cec5SDimitry Andric return 0;
1250b57cec5SDimitry Andric case HexagonII::HSIG_A:
1260b57cec5SDimitry Andric return 0x4;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric break;
1290b57cec5SDimitry Andric case HexagonII::HSIG_L2:
1300b57cec5SDimitry Andric switch (Gb) {
1310b57cec5SDimitry Andric default:
1320b57cec5SDimitry Andric break;
1330b57cec5SDimitry Andric case HexagonII::HSIG_L1:
1340b57cec5SDimitry Andric return 0x1;
1350b57cec5SDimitry Andric case HexagonII::HSIG_L2:
1360b57cec5SDimitry Andric return 0x2;
1370b57cec5SDimitry Andric case HexagonII::HSIG_A:
1380b57cec5SDimitry Andric return 0x5;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric break;
1410b57cec5SDimitry Andric case HexagonII::HSIG_S1:
1420b57cec5SDimitry Andric switch (Gb) {
1430b57cec5SDimitry Andric default:
1440b57cec5SDimitry Andric break;
1450b57cec5SDimitry Andric case HexagonII::HSIG_L1:
1460b57cec5SDimitry Andric return 0x8;
1470b57cec5SDimitry Andric case HexagonII::HSIG_L2:
1480b57cec5SDimitry Andric return 0x9;
1490b57cec5SDimitry Andric case HexagonII::HSIG_S1:
1500b57cec5SDimitry Andric return 0xA;
1510b57cec5SDimitry Andric case HexagonII::HSIG_A:
1520b57cec5SDimitry Andric return 0x6;
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric break;
1550b57cec5SDimitry Andric case HexagonII::HSIG_S2:
1560b57cec5SDimitry Andric switch (Gb) {
1570b57cec5SDimitry Andric default:
1580b57cec5SDimitry Andric break;
1590b57cec5SDimitry Andric case HexagonII::HSIG_L1:
1600b57cec5SDimitry Andric return 0xC;
1610b57cec5SDimitry Andric case HexagonII::HSIG_L2:
1620b57cec5SDimitry Andric return 0xD;
1630b57cec5SDimitry Andric case HexagonII::HSIG_S1:
1640b57cec5SDimitry Andric return 0xB;
1650b57cec5SDimitry Andric case HexagonII::HSIG_S2:
1660b57cec5SDimitry Andric return 0xE;
1670b57cec5SDimitry Andric case HexagonII::HSIG_A:
1680b57cec5SDimitry Andric return 0x7;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric break;
1710b57cec5SDimitry Andric case HexagonII::HSIG_A:
1720b57cec5SDimitry Andric switch (Gb) {
1730b57cec5SDimitry Andric default:
1740b57cec5SDimitry Andric break;
1750b57cec5SDimitry Andric case HexagonII::HSIG_A:
1760b57cec5SDimitry Andric return 0x3;
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric break;
1790b57cec5SDimitry Andric case HexagonII::HSIG_Compound:
1800b57cec5SDimitry Andric switch (Gb) {
1810b57cec5SDimitry Andric case HexagonII::HSIG_Compound:
1820b57cec5SDimitry Andric return 0xFFFFFFFF;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric break;
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric return 0xFFFFFFFF;
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric
getDuplexCandidateGroup(MCInst const & MCI)1890b57cec5SDimitry Andric unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
1900b57cec5SDimitry Andric unsigned DstReg, PredReg, SrcReg, Src1Reg, Src2Reg;
1910b57cec5SDimitry Andric
1920b57cec5SDimitry Andric switch (MCI.getOpcode()) {
1930b57cec5SDimitry Andric default:
1940b57cec5SDimitry Andric return HexagonII::HSIG_None;
1950b57cec5SDimitry Andric //
1960b57cec5SDimitry Andric // Group L1:
1970b57cec5SDimitry Andric //
1980b57cec5SDimitry Andric // Rd = memw(Rs+#u4:2)
1990b57cec5SDimitry Andric // Rd = memub(Rs+#u4:0)
2000b57cec5SDimitry Andric case Hexagon::L2_loadri_io:
2010b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
2020b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
2030b57cec5SDimitry Andric // Special case this one from Group L2.
2040b57cec5SDimitry Andric // Rd = memw(r29+#u5:2)
2050b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
2060b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntReg(SrcReg) &&
2070b57cec5SDimitry Andric Hexagon::R29 == SrcReg && inRange<5, 2>(MCI, 2)) {
2080b57cec5SDimitry Andric return HexagonII::HSIG_L2;
2090b57cec5SDimitry Andric }
2100b57cec5SDimitry Andric // Rd = memw(Rs+#u4:2)
2110b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
2120b57cec5SDimitry Andric inRange<4, 2>(MCI, 2)) {
2130b57cec5SDimitry Andric return HexagonII::HSIG_L1;
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric }
2160b57cec5SDimitry Andric break;
2170b57cec5SDimitry Andric case Hexagon::L2_loadrub_io:
2180b57cec5SDimitry Andric // Rd = memub(Rs+#u4:0)
2190b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
2200b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
2210b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
2220b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
2230b57cec5SDimitry Andric inRange<4>(MCI, 2)) {
2240b57cec5SDimitry Andric return HexagonII::HSIG_L1;
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric break;
2270b57cec5SDimitry Andric //
2280b57cec5SDimitry Andric // Group L2:
2290b57cec5SDimitry Andric //
2300b57cec5SDimitry Andric // Rd = memh/memuh(Rs+#u3:1)
2310b57cec5SDimitry Andric // Rd = memb(Rs+#u3:0)
2320b57cec5SDimitry Andric // Rd = memw(r29+#u5:2) - Handled above.
2330b57cec5SDimitry Andric // Rdd = memd(r29+#u5:3)
2340b57cec5SDimitry Andric // deallocframe
2350b57cec5SDimitry Andric // [if ([!]p0[.new])] dealloc_return
2360b57cec5SDimitry Andric // [if ([!]p0[.new])] jumpr r31
2370b57cec5SDimitry Andric case Hexagon::L2_loadrh_io:
2380b57cec5SDimitry Andric case Hexagon::L2_loadruh_io:
2390b57cec5SDimitry Andric // Rd = memh/memuh(Rs+#u3:1)
2400b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
2410b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
2420b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
2430b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
2440b57cec5SDimitry Andric inRange<3, 1>(MCI, 2)) {
2450b57cec5SDimitry Andric return HexagonII::HSIG_L2;
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric break;
2480b57cec5SDimitry Andric case Hexagon::L2_loadrb_io:
2490b57cec5SDimitry Andric // Rd = memb(Rs+#u3:0)
2500b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
2510b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
2520b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
2530b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
2540b57cec5SDimitry Andric inRange<3>(MCI, 2)) {
2550b57cec5SDimitry Andric return HexagonII::HSIG_L2;
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric break;
2580b57cec5SDimitry Andric case Hexagon::L2_loadrd_io:
2590b57cec5SDimitry Andric // Rdd = memd(r29+#u5:3)
2600b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
2610b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
2620b57cec5SDimitry Andric if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
2630b57cec5SDimitry Andric HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
2640b57cec5SDimitry Andric inRange<5, 3>(MCI, 2)) {
2650b57cec5SDimitry Andric return HexagonII::HSIG_L2;
2660b57cec5SDimitry Andric }
2670b57cec5SDimitry Andric break;
2680b57cec5SDimitry Andric
2690b57cec5SDimitry Andric case Hexagon::L4_return:
2700b57cec5SDimitry Andric case Hexagon::L2_deallocframe:
2710b57cec5SDimitry Andric return HexagonII::HSIG_L2;
2720b57cec5SDimitry Andric
2730b57cec5SDimitry Andric case Hexagon::EH_RETURN_JMPR:
2740b57cec5SDimitry Andric case Hexagon::J2_jumpr:
2750b57cec5SDimitry Andric case Hexagon::PS_jmpret:
2760b57cec5SDimitry Andric // jumpr r31
2770b57cec5SDimitry Andric // Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0.
2780b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
2790b57cec5SDimitry Andric if (Hexagon::R31 == DstReg)
2800b57cec5SDimitry Andric return HexagonII::HSIG_L2;
2810b57cec5SDimitry Andric break;
2820b57cec5SDimitry Andric
2830b57cec5SDimitry Andric case Hexagon::J2_jumprt:
2840b57cec5SDimitry Andric case Hexagon::J2_jumprf:
2850b57cec5SDimitry Andric case Hexagon::J2_jumprtnew:
2860b57cec5SDimitry Andric case Hexagon::J2_jumprfnew:
2870b57cec5SDimitry Andric case Hexagon::PS_jmprett:
2880b57cec5SDimitry Andric case Hexagon::PS_jmpretf:
2890b57cec5SDimitry Andric case Hexagon::PS_jmprettnew:
2900b57cec5SDimitry Andric case Hexagon::PS_jmpretfnew:
2910b57cec5SDimitry Andric case Hexagon::PS_jmprettnewpt:
2920b57cec5SDimitry Andric case Hexagon::PS_jmpretfnewpt:
2930b57cec5SDimitry Andric DstReg = MCI.getOperand(1).getReg();
2940b57cec5SDimitry Andric SrcReg = MCI.getOperand(0).getReg();
2950b57cec5SDimitry Andric // [if ([!]p0[.new])] jumpr r31
2965ffd83dbSDimitry Andric if ((Hexagon::P0 == SrcReg) && (Hexagon::R31 == DstReg)) {
2970b57cec5SDimitry Andric return HexagonII::HSIG_L2;
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric break;
3000b57cec5SDimitry Andric case Hexagon::L4_return_t:
3010b57cec5SDimitry Andric case Hexagon::L4_return_f:
3020b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pnt:
3030b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pnt:
3040b57cec5SDimitry Andric // [if ([!]p0[.new])] dealloc_return
3050b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
3060b57cec5SDimitry Andric if (Hexagon::P0 == SrcReg) {
3070b57cec5SDimitry Andric return HexagonII::HSIG_L2;
3080b57cec5SDimitry Andric }
3090b57cec5SDimitry Andric break;
3100b57cec5SDimitry Andric //
3110b57cec5SDimitry Andric // Group S1:
3120b57cec5SDimitry Andric //
3130b57cec5SDimitry Andric // memw(Rs+#u4:2) = Rt
3140b57cec5SDimitry Andric // memb(Rs+#u4:0) = Rt
3150b57cec5SDimitry Andric case Hexagon::S2_storeri_io:
3160b57cec5SDimitry Andric // Special case this one from Group S2.
3170b57cec5SDimitry Andric // memw(r29+#u5:2) = Rt
3180b57cec5SDimitry Andric Src1Reg = MCI.getOperand(0).getReg();
3190b57cec5SDimitry Andric Src2Reg = MCI.getOperand(2).getReg();
3200b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntReg(Src1Reg) &&
3210b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
3220b57cec5SDimitry Andric Hexagon::R29 == Src1Reg && inRange<5, 2>(MCI, 1)) {
3230b57cec5SDimitry Andric return HexagonII::HSIG_S2;
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric // memw(Rs+#u4:2) = Rt
3260b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
3270b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
3280b57cec5SDimitry Andric inRange<4, 2>(MCI, 1)) {
3290b57cec5SDimitry Andric return HexagonII::HSIG_S1;
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric break;
3320b57cec5SDimitry Andric case Hexagon::S2_storerb_io:
3330b57cec5SDimitry Andric // memb(Rs+#u4:0) = Rt
3340b57cec5SDimitry Andric Src1Reg = MCI.getOperand(0).getReg();
3350b57cec5SDimitry Andric Src2Reg = MCI.getOperand(2).getReg();
3360b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
3370b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
3380b57cec5SDimitry Andric inRange<4>(MCI, 1)) {
3390b57cec5SDimitry Andric return HexagonII::HSIG_S1;
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric break;
3420b57cec5SDimitry Andric //
3430b57cec5SDimitry Andric // Group S2:
3440b57cec5SDimitry Andric //
3450b57cec5SDimitry Andric // memh(Rs+#u3:1) = Rt
3460b57cec5SDimitry Andric // memw(r29+#u5:2) = Rt
3470b57cec5SDimitry Andric // memd(r29+#s6:3) = Rtt
3480b57cec5SDimitry Andric // memw(Rs+#u4:2) = #U1
3490b57cec5SDimitry Andric // memb(Rs+#u4) = #U1
3500b57cec5SDimitry Andric // allocframe(#u5:3)
3510b57cec5SDimitry Andric case Hexagon::S2_storerh_io:
3520b57cec5SDimitry Andric // memh(Rs+#u3:1) = Rt
3530b57cec5SDimitry Andric Src1Reg = MCI.getOperand(0).getReg();
3540b57cec5SDimitry Andric Src2Reg = MCI.getOperand(2).getReg();
3550b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
3560b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg) &&
3570b57cec5SDimitry Andric inRange<3, 1>(MCI, 1)) {
3580b57cec5SDimitry Andric return HexagonII::HSIG_S2;
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric break;
3610b57cec5SDimitry Andric case Hexagon::S2_storerd_io:
3620b57cec5SDimitry Andric // memd(r29+#s6:3) = Rtt
3630b57cec5SDimitry Andric Src1Reg = MCI.getOperand(0).getReg();
3640b57cec5SDimitry Andric Src2Reg = MCI.getOperand(2).getReg();
3650b57cec5SDimitry Andric if (HexagonMCInstrInfo::isDblRegForSubInst(Src2Reg) &&
3660b57cec5SDimitry Andric HexagonMCInstrInfo::isIntReg(Src1Reg) && Hexagon::R29 == Src1Reg &&
3670b57cec5SDimitry Andric inSRange<6, 3>(MCI, 1)) {
3680b57cec5SDimitry Andric return HexagonII::HSIG_S2;
3690b57cec5SDimitry Andric }
3700b57cec5SDimitry Andric break;
3710b57cec5SDimitry Andric case Hexagon::S4_storeiri_io:
3720b57cec5SDimitry Andric // memw(Rs+#u4:2) = #U1
3730b57cec5SDimitry Andric Src1Reg = MCI.getOperand(0).getReg();
3740b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
3750b57cec5SDimitry Andric inRange<4, 2>(MCI, 1) && inRange<1>(MCI, 2)) {
3760b57cec5SDimitry Andric return HexagonII::HSIG_S2;
3770b57cec5SDimitry Andric }
3780b57cec5SDimitry Andric break;
3790b57cec5SDimitry Andric case Hexagon::S4_storeirb_io:
3800b57cec5SDimitry Andric // memb(Rs+#u4) = #U1
3810b57cec5SDimitry Andric Src1Reg = MCI.getOperand(0).getReg();
3820b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(Src1Reg) &&
3830b57cec5SDimitry Andric inRange<4>(MCI, 1) && inRange<1>(MCI, 2)) {
3840b57cec5SDimitry Andric return HexagonII::HSIG_S2;
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric break;
3870b57cec5SDimitry Andric case Hexagon::S2_allocframe:
3880b57cec5SDimitry Andric if (inRange<5, 3>(MCI, 2))
3890b57cec5SDimitry Andric return HexagonII::HSIG_S2;
3900b57cec5SDimitry Andric break;
3910b57cec5SDimitry Andric //
3920b57cec5SDimitry Andric // Group A:
3930b57cec5SDimitry Andric //
3940b57cec5SDimitry Andric // Rx = add(Rx,#s7)
3950b57cec5SDimitry Andric // Rd = Rs
3960b57cec5SDimitry Andric // Rd = #u6
3970b57cec5SDimitry Andric // Rd = #-1
3980b57cec5SDimitry Andric // if ([!]P0[.new]) Rd = #0
3990b57cec5SDimitry Andric // Rd = add(r29,#u6:2)
4000b57cec5SDimitry Andric // Rx = add(Rx,Rs)
4010b57cec5SDimitry Andric // P0 = cmp.eq(Rs,#u2)
4020b57cec5SDimitry Andric // Rdd = combine(#0,Rs)
4030b57cec5SDimitry Andric // Rdd = combine(Rs,#0)
4040b57cec5SDimitry Andric // Rdd = combine(#u2,#U2)
4050b57cec5SDimitry Andric // Rd = add(Rs,#1)
4060b57cec5SDimitry Andric // Rd = add(Rs,#-1)
4070b57cec5SDimitry Andric // Rd = sxth/sxtb/zxtb/zxth(Rs)
4080b57cec5SDimitry Andric // Rd = and(Rs,#1)
4090b57cec5SDimitry Andric case Hexagon::A2_addi:
4100b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
4110b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
4120b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
4130b57cec5SDimitry Andric // Rd = add(r29,#u6:2)
4140b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntReg(SrcReg) && Hexagon::R29 == SrcReg &&
4150b57cec5SDimitry Andric inRange<6, 2>(MCI, 2)) {
4160b57cec5SDimitry Andric return HexagonII::HSIG_A;
4170b57cec5SDimitry Andric }
4180b57cec5SDimitry Andric // Rx = add(Rx,#s7)
4190b57cec5SDimitry Andric if (DstReg == SrcReg) {
4200b57cec5SDimitry Andric return HexagonII::HSIG_A;
4210b57cec5SDimitry Andric }
4220b57cec5SDimitry Andric // Rd = add(Rs,#1)
4230b57cec5SDimitry Andric // Rd = add(Rs,#-1)
4240b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
4250b57cec5SDimitry Andric (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == -1)) {
4260b57cec5SDimitry Andric return HexagonII::HSIG_A;
4270b57cec5SDimitry Andric }
4280b57cec5SDimitry Andric }
4290b57cec5SDimitry Andric break;
4300b57cec5SDimitry Andric case Hexagon::A2_add:
4310b57cec5SDimitry Andric // Rx = add(Rx,Rs)
4320b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
4330b57cec5SDimitry Andric Src1Reg = MCI.getOperand(1).getReg();
4340b57cec5SDimitry Andric Src2Reg = MCI.getOperand(2).getReg();
4350b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) && (DstReg == Src1Reg) &&
4360b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(Src2Reg)) {
4370b57cec5SDimitry Andric return HexagonII::HSIG_A;
4380b57cec5SDimitry Andric }
4390b57cec5SDimitry Andric break;
4400b57cec5SDimitry Andric case Hexagon::A2_andir:
4410b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
4420b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
4430b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
4440b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
4450b57cec5SDimitry Andric (minConstant(MCI, 2) == 1 || minConstant(MCI, 2) == 255)) {
4460b57cec5SDimitry Andric return HexagonII::HSIG_A;
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric break;
4490b57cec5SDimitry Andric case Hexagon::A2_tfr:
4500b57cec5SDimitry Andric // Rd = Rs
4510b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
4520b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
4530b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
4540b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg)) {
4550b57cec5SDimitry Andric return HexagonII::HSIG_A;
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric break;
4580b57cec5SDimitry Andric case Hexagon::A2_tfrsi:
4590b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
4600b57cec5SDimitry Andric
4610b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
4620b57cec5SDimitry Andric return HexagonII::HSIG_A;
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric break;
4650b57cec5SDimitry Andric case Hexagon::C2_cmoveit:
4660b57cec5SDimitry Andric case Hexagon::C2_cmovenewit:
4670b57cec5SDimitry Andric case Hexagon::C2_cmoveif:
4680b57cec5SDimitry Andric case Hexagon::C2_cmovenewif:
4690b57cec5SDimitry Andric // if ([!]P0[.new]) Rd = #0
4700b57cec5SDimitry Andric // Actual form:
4710b57cec5SDimitry Andric // %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16;
4720b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg(); // Rd
4730b57cec5SDimitry Andric PredReg = MCI.getOperand(1).getReg(); // P0
4740b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
4750b57cec5SDimitry Andric Hexagon::P0 == PredReg && minConstant(MCI, 2) == 0) {
4760b57cec5SDimitry Andric return HexagonII::HSIG_A;
4770b57cec5SDimitry Andric }
4780b57cec5SDimitry Andric break;
4790b57cec5SDimitry Andric case Hexagon::C2_cmpeqi:
4800b57cec5SDimitry Andric // P0 = cmp.eq(Rs,#u2)
4810b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
4820b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
4830b57cec5SDimitry Andric if (Hexagon::P0 == DstReg &&
4840b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
4850b57cec5SDimitry Andric inRange<2>(MCI, 2)) {
4860b57cec5SDimitry Andric return HexagonII::HSIG_A;
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric break;
4890b57cec5SDimitry Andric case Hexagon::A2_combineii:
4900b57cec5SDimitry Andric case Hexagon::A4_combineii:
4910b57cec5SDimitry Andric // Rdd = combine(#u2,#U2)
4920b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
4930b57cec5SDimitry Andric if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
4940b57cec5SDimitry Andric inRange<2>(MCI, 1) && inRange<2>(MCI, 2)) {
4950b57cec5SDimitry Andric return HexagonII::HSIG_A;
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric break;
4980b57cec5SDimitry Andric case Hexagon::A4_combineri:
4990b57cec5SDimitry Andric // Rdd = combine(Rs,#0)
5000b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
5010b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
5020b57cec5SDimitry Andric if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
5030b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
5040b57cec5SDimitry Andric minConstant(MCI, 2) == 0) {
5050b57cec5SDimitry Andric return HexagonII::HSIG_A;
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric break;
5080b57cec5SDimitry Andric case Hexagon::A4_combineir:
5090b57cec5SDimitry Andric // Rdd = combine(#0,Rs)
5100b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
5110b57cec5SDimitry Andric SrcReg = MCI.getOperand(2).getReg();
5120b57cec5SDimitry Andric if (HexagonMCInstrInfo::isDblRegForSubInst(DstReg) &&
5130b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg) &&
5140b57cec5SDimitry Andric minConstant(MCI, 1) == 0) {
5150b57cec5SDimitry Andric return HexagonII::HSIG_A;
5160b57cec5SDimitry Andric }
5170b57cec5SDimitry Andric break;
5180b57cec5SDimitry Andric case Hexagon::A2_sxtb:
5190b57cec5SDimitry Andric case Hexagon::A2_sxth:
5200b57cec5SDimitry Andric case Hexagon::A2_zxtb:
5210b57cec5SDimitry Andric case Hexagon::A2_zxth:
5220b57cec5SDimitry Andric // Rd = sxth/sxtb/zxtb/zxth(Rs)
5230b57cec5SDimitry Andric DstReg = MCI.getOperand(0).getReg();
5240b57cec5SDimitry Andric SrcReg = MCI.getOperand(1).getReg();
5250b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
5260b57cec5SDimitry Andric HexagonMCInstrInfo::isIntRegForSubInst(SrcReg)) {
5270b57cec5SDimitry Andric return HexagonII::HSIG_A;
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric break;
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric
5320b57cec5SDimitry Andric return HexagonII::HSIG_None;
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric
subInstWouldBeExtended(MCInst const & potentialDuplex)5350b57cec5SDimitry Andric bool HexagonMCInstrInfo::subInstWouldBeExtended(MCInst const &potentialDuplex) {
5360b57cec5SDimitry Andric unsigned DstReg, SrcReg;
5370b57cec5SDimitry Andric switch (potentialDuplex.getOpcode()) {
5380b57cec5SDimitry Andric case Hexagon::A2_addi:
5390b57cec5SDimitry Andric // testing for case of: Rx = add(Rx,#s7)
5400b57cec5SDimitry Andric DstReg = potentialDuplex.getOperand(0).getReg();
5410b57cec5SDimitry Andric SrcReg = potentialDuplex.getOperand(1).getReg();
5420b57cec5SDimitry Andric if (DstReg == SrcReg && HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
5430b57cec5SDimitry Andric int64_t Value;
5440b57cec5SDimitry Andric if (!potentialDuplex.getOperand(2).getExpr()->evaluateAsAbsolute(Value))
5450b57cec5SDimitry Andric return true;
5460b57cec5SDimitry Andric if (!isShiftedInt<7, 0>(Value))
5470b57cec5SDimitry Andric return true;
5480b57cec5SDimitry Andric }
5490b57cec5SDimitry Andric break;
5500b57cec5SDimitry Andric case Hexagon::A2_tfrsi:
5510b57cec5SDimitry Andric DstReg = potentialDuplex.getOperand(0).getReg();
5520b57cec5SDimitry Andric
5530b57cec5SDimitry Andric if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg)) {
5540b57cec5SDimitry Andric int64_t Value;
5550b57cec5SDimitry Andric if (!potentialDuplex.getOperand(1).getExpr()->evaluateAsAbsolute(Value))
5560b57cec5SDimitry Andric return true;
5570b57cec5SDimitry Andric // Check for case of Rd = #-1.
5580b57cec5SDimitry Andric if (Value == -1)
5590b57cec5SDimitry Andric return false;
5600b57cec5SDimitry Andric // Check for case of Rd = #u6.
5610b57cec5SDimitry Andric if (!isShiftedUInt<6, 0>(Value))
5620b57cec5SDimitry Andric return true;
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric break;
5650b57cec5SDimitry Andric default:
5660b57cec5SDimitry Andric break;
5670b57cec5SDimitry Andric }
5680b57cec5SDimitry Andric return false;
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric
5710b57cec5SDimitry Andric /// 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)5720b57cec5SDimitry Andric bool HexagonMCInstrInfo::isOrderedDuplexPair(MCInstrInfo const &MCII,
5730b57cec5SDimitry Andric MCInst const &MIa, bool ExtendedA,
5740b57cec5SDimitry Andric MCInst const &MIb, bool ExtendedB,
5750b57cec5SDimitry Andric bool bisReversable,
5760b57cec5SDimitry Andric MCSubtargetInfo const &STI) {
5770b57cec5SDimitry Andric // Slot 1 cannot be extended in duplexes PRM 10.5
5780b57cec5SDimitry Andric if (ExtendedA)
5790b57cec5SDimitry Andric return false;
5800b57cec5SDimitry Andric // Only A2_addi and A2_tfrsi can be extended in duplex form PRM 10.5
5810b57cec5SDimitry Andric if (ExtendedB) {
5820b57cec5SDimitry Andric unsigned Opcode = MIb.getOpcode();
5830b57cec5SDimitry Andric if ((Opcode != Hexagon::A2_addi) && (Opcode != Hexagon::A2_tfrsi))
5840b57cec5SDimitry Andric return false;
5850b57cec5SDimitry Andric }
5860b57cec5SDimitry Andric unsigned MIaG = HexagonMCInstrInfo::getDuplexCandidateGroup(MIa),
5870b57cec5SDimitry Andric MIbG = HexagonMCInstrInfo::getDuplexCandidateGroup(MIb);
5880b57cec5SDimitry Andric
5890b57cec5SDimitry Andric static std::map<unsigned, unsigned> subinstOpcodeMap(std::begin(opcodeData),
5900b57cec5SDimitry Andric std::end(opcodeData));
5910b57cec5SDimitry Andric
5920b57cec5SDimitry Andric // If a duplex contains 2 insns in the same group, the insns must be
5930b57cec5SDimitry Andric // ordered such that the numerically smaller opcode is in slot 1.
5940b57cec5SDimitry Andric if ((MIaG != HexagonII::HSIG_None) && (MIaG == MIbG) && bisReversable) {
5950b57cec5SDimitry Andric MCInst SubInst0 = HexagonMCInstrInfo::deriveSubInst(MIa);
5960b57cec5SDimitry Andric MCInst SubInst1 = HexagonMCInstrInfo::deriveSubInst(MIb);
5970b57cec5SDimitry Andric
5980b57cec5SDimitry Andric unsigned zeroedSubInstS0 =
5990b57cec5SDimitry Andric subinstOpcodeMap.find(SubInst0.getOpcode())->second;
6000b57cec5SDimitry Andric unsigned zeroedSubInstS1 =
6010b57cec5SDimitry Andric subinstOpcodeMap.find(SubInst1.getOpcode())->second;
6020b57cec5SDimitry Andric
6030b57cec5SDimitry Andric if (zeroedSubInstS0 < zeroedSubInstS1)
6040b57cec5SDimitry Andric // subinstS0 (maps to slot 0) must be greater than
6050b57cec5SDimitry Andric // subinstS1 (maps to slot 1)
6060b57cec5SDimitry Andric return false;
6070b57cec5SDimitry Andric }
6080b57cec5SDimitry Andric
6090b57cec5SDimitry Andric // allocframe must always be in slot 0
6100b57cec5SDimitry Andric if (MIb.getOpcode() == Hexagon::S2_allocframe)
6110b57cec5SDimitry Andric return false;
6120b57cec5SDimitry Andric
6130b57cec5SDimitry Andric if ((MIaG != HexagonII::HSIG_None) && (MIbG != HexagonII::HSIG_None)) {
6140b57cec5SDimitry Andric // Prevent 2 instructions with extenders from duplexing
6150b57cec5SDimitry Andric // Note that MIb (slot1) can be extended and MIa (slot0)
6160b57cec5SDimitry Andric // can never be extended
6170b57cec5SDimitry Andric if (subInstWouldBeExtended(MIa))
6180b57cec5SDimitry Andric return false;
6190b57cec5SDimitry Andric
6200b57cec5SDimitry Andric // If duplexing produces an extender, but the original did not
6210b57cec5SDimitry Andric // have an extender, do not duplex.
6220b57cec5SDimitry Andric if (subInstWouldBeExtended(MIb) && !ExtendedB)
6230b57cec5SDimitry Andric return false;
6240b57cec5SDimitry Andric }
6250b57cec5SDimitry Andric
6260b57cec5SDimitry Andric // If jumpr r31 appears, it must be in slot 0, and never slot 1 (MIb).
6270b57cec5SDimitry Andric if (MIbG == HexagonII::HSIG_L2) {
6280b57cec5SDimitry Andric if ((MIb.getNumOperands() > 1) && MIb.getOperand(1).isReg() &&
6290b57cec5SDimitry Andric (MIb.getOperand(1).getReg() == Hexagon::R31))
6300b57cec5SDimitry Andric return false;
6310b57cec5SDimitry Andric if ((MIb.getNumOperands() > 0) && MIb.getOperand(0).isReg() &&
6320b57cec5SDimitry Andric (MIb.getOperand(0).getReg() == Hexagon::R31))
6330b57cec5SDimitry Andric return false;
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric
636fe6060f1SDimitry Andric if (STI.getCPU().equals_insensitive("hexagonv5") ||
637fe6060f1SDimitry Andric STI.getCPU().equals_insensitive("hexagonv55") ||
638fe6060f1SDimitry Andric STI.getCPU().equals_insensitive("hexagonv60")) {
6390b57cec5SDimitry Andric // If a store appears, it must be in slot 0 (MIa) 1st, and then slot 1 (MIb);
6400b57cec5SDimitry Andric // therefore, not duplexable if slot 1 is a store, and slot 0 is not.
6410b57cec5SDimitry Andric if ((MIbG == HexagonII::HSIG_S1) || (MIbG == HexagonII::HSIG_S2)) {
6420b57cec5SDimitry Andric if ((MIaG != HexagonII::HSIG_S1) && (MIaG != HexagonII::HSIG_S2))
6430b57cec5SDimitry Andric return false;
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric
6470b57cec5SDimitry Andric return (isDuplexPairMatch(MIaG, MIbG));
6480b57cec5SDimitry Andric }
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric /// Symmetrical. See if these two instructions are fit for duplex pair.
isDuplexPair(MCInst const & MIa,MCInst const & MIb)6510b57cec5SDimitry Andric bool HexagonMCInstrInfo::isDuplexPair(MCInst const &MIa, MCInst const &MIb) {
6520b57cec5SDimitry Andric unsigned MIaG = getDuplexCandidateGroup(MIa),
6530b57cec5SDimitry Andric MIbG = getDuplexCandidateGroup(MIb);
6540b57cec5SDimitry Andric return (isDuplexPairMatch(MIaG, MIbG) || isDuplexPairMatch(MIbG, MIaG));
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric
addOps(MCInst & subInstPtr,MCInst const & Inst,unsigned opNum)6570b57cec5SDimitry Andric inline static void addOps(MCInst &subInstPtr, MCInst const &Inst,
6580b57cec5SDimitry Andric unsigned opNum) {
6590b57cec5SDimitry Andric if (Inst.getOperand(opNum).isReg()) {
6600b57cec5SDimitry Andric switch (Inst.getOperand(opNum).getReg()) {
6610b57cec5SDimitry Andric default:
6620b57cec5SDimitry Andric llvm_unreachable("Not Duplexable Register");
6630b57cec5SDimitry Andric break;
6640b57cec5SDimitry Andric case Hexagon::R0:
6650b57cec5SDimitry Andric case Hexagon::R1:
6660b57cec5SDimitry Andric case Hexagon::R2:
6670b57cec5SDimitry Andric case Hexagon::R3:
6680b57cec5SDimitry Andric case Hexagon::R4:
6690b57cec5SDimitry Andric case Hexagon::R5:
6700b57cec5SDimitry Andric case Hexagon::R6:
6710b57cec5SDimitry Andric case Hexagon::R7:
6720b57cec5SDimitry Andric case Hexagon::D0:
6730b57cec5SDimitry Andric case Hexagon::D1:
6740b57cec5SDimitry Andric case Hexagon::D2:
6750b57cec5SDimitry Andric case Hexagon::D3:
6760b57cec5SDimitry Andric case Hexagon::R16:
6770b57cec5SDimitry Andric case Hexagon::R17:
6780b57cec5SDimitry Andric case Hexagon::R18:
6790b57cec5SDimitry Andric case Hexagon::R19:
6800b57cec5SDimitry Andric case Hexagon::R20:
6810b57cec5SDimitry Andric case Hexagon::R21:
6820b57cec5SDimitry Andric case Hexagon::R22:
6830b57cec5SDimitry Andric case Hexagon::R23:
6840b57cec5SDimitry Andric case Hexagon::D8:
6850b57cec5SDimitry Andric case Hexagon::D9:
6860b57cec5SDimitry Andric case Hexagon::D10:
6870b57cec5SDimitry Andric case Hexagon::D11:
6880b57cec5SDimitry Andric case Hexagon::P0:
6890b57cec5SDimitry Andric subInstPtr.addOperand(Inst.getOperand(opNum));
6900b57cec5SDimitry Andric break;
6910b57cec5SDimitry Andric }
6920b57cec5SDimitry Andric } else
6930b57cec5SDimitry Andric subInstPtr.addOperand(Inst.getOperand(opNum));
6940b57cec5SDimitry Andric }
6950b57cec5SDimitry Andric
deriveSubInst(MCInst const & Inst)6960b57cec5SDimitry Andric MCInst HexagonMCInstrInfo::deriveSubInst(MCInst const &Inst) {
6970b57cec5SDimitry Andric MCInst Result;
698*04eeddc0SDimitry Andric Result.setLoc(Inst.getLoc());
6990b57cec5SDimitry Andric bool Absolute;
7000b57cec5SDimitry Andric int64_t Value;
7010b57cec5SDimitry Andric switch (Inst.getOpcode()) {
7020b57cec5SDimitry Andric default:
7030b57cec5SDimitry Andric // dbgs() << "opcode: "<< Inst->getOpcode() << "\n";
7040b57cec5SDimitry Andric llvm_unreachable("Unimplemented subinstruction \n");
7050b57cec5SDimitry Andric break;
7060b57cec5SDimitry Andric case Hexagon::A2_addi:
7070b57cec5SDimitry Andric Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
7080b57cec5SDimitry Andric if (Absolute) {
7090b57cec5SDimitry Andric if (Value == 1) {
7100b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_inc);
7110b57cec5SDimitry Andric addOps(Result, Inst, 0);
7120b57cec5SDimitry Andric addOps(Result, Inst, 1);
7130b57cec5SDimitry Andric break;
7140b57cec5SDimitry Andric } // 1,2 SUBInst $Rd = add($Rs, #1)
7150b57cec5SDimitry Andric if (Value == -1) {
7160b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_dec);
7170b57cec5SDimitry Andric addOps(Result, Inst, 0);
7180b57cec5SDimitry Andric addOps(Result, Inst, 1);
7190b57cec5SDimitry Andric addOps(Result, Inst, 2);
7200b57cec5SDimitry Andric break;
7210b57cec5SDimitry Andric } // 1,2 SUBInst $Rd = add($Rs,#-1)
7220b57cec5SDimitry Andric if (Inst.getOperand(1).getReg() == Hexagon::R29) {
7230b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_addsp);
7240b57cec5SDimitry Andric addOps(Result, Inst, 0);
7250b57cec5SDimitry Andric addOps(Result, Inst, 2);
7260b57cec5SDimitry Andric break;
7270b57cec5SDimitry Andric } // 1,3 SUBInst $Rd = add(r29, #$u6_2)
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_addi);
7300b57cec5SDimitry Andric addOps(Result, Inst, 0);
7310b57cec5SDimitry Andric addOps(Result, Inst, 1);
7320b57cec5SDimitry Andric addOps(Result, Inst, 2);
7330b57cec5SDimitry Andric break; // 1,2,3 SUBInst $Rx = add($Rx, #$s7)
7340b57cec5SDimitry Andric case Hexagon::A2_add:
7350b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_addrx);
7360b57cec5SDimitry Andric addOps(Result, Inst, 0);
7370b57cec5SDimitry Andric addOps(Result, Inst, 1);
7380b57cec5SDimitry Andric addOps(Result, Inst, 2);
7390b57cec5SDimitry Andric break; // 1,2,3 SUBInst $Rx = add($_src_, $Rs)
7400b57cec5SDimitry Andric case Hexagon::S2_allocframe:
7410b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_allocframe);
7420b57cec5SDimitry Andric addOps(Result, Inst, 2);
7430b57cec5SDimitry Andric break; // 1 SUBInst allocframe(#$u5_3)
7440b57cec5SDimitry Andric case Hexagon::A2_andir:
7450b57cec5SDimitry Andric if (minConstant(Inst, 2) == 255) {
7460b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_zxtb);
7470b57cec5SDimitry Andric addOps(Result, Inst, 0);
7480b57cec5SDimitry Andric addOps(Result, Inst, 1);
7490b57cec5SDimitry Andric break; // 1,2 $Rd = and($Rs, #255)
7500b57cec5SDimitry Andric } else {
7510b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_and1);
7520b57cec5SDimitry Andric addOps(Result, Inst, 0);
7530b57cec5SDimitry Andric addOps(Result, Inst, 1);
7540b57cec5SDimitry Andric break; // 1,2 SUBInst $Rd = and($Rs, #1)
7550b57cec5SDimitry Andric }
7560b57cec5SDimitry Andric case Hexagon::C2_cmpeqi:
7570b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_cmpeqi);
7580b57cec5SDimitry Andric addOps(Result, Inst, 1);
7590b57cec5SDimitry Andric addOps(Result, Inst, 2);
7600b57cec5SDimitry Andric break; // 2,3 SUBInst p0 = cmp.eq($Rs, #$u2)
7610b57cec5SDimitry Andric case Hexagon::A4_combineii:
7620b57cec5SDimitry Andric case Hexagon::A2_combineii:
7630b57cec5SDimitry Andric Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
7640b57cec5SDimitry Andric assert(Absolute);(void)Absolute;
7650b57cec5SDimitry Andric if (Value == 1) {
7660b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_combine1i);
7670b57cec5SDimitry Andric addOps(Result, Inst, 0);
7680b57cec5SDimitry Andric addOps(Result, Inst, 2);
7690b57cec5SDimitry Andric break; // 1,3 SUBInst $Rdd = combine(#1, #$u2)
7700b57cec5SDimitry Andric }
7710b57cec5SDimitry Andric if (Value == 3) {
7720b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_combine3i);
7730b57cec5SDimitry Andric addOps(Result, Inst, 0);
7740b57cec5SDimitry Andric addOps(Result, Inst, 2);
7750b57cec5SDimitry Andric break; // 1,3 SUBInst $Rdd = combine(#3, #$u2)
7760b57cec5SDimitry Andric }
7770b57cec5SDimitry Andric if (Value == 0) {
7780b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_combine0i);
7790b57cec5SDimitry Andric addOps(Result, Inst, 0);
7800b57cec5SDimitry Andric addOps(Result, Inst, 2);
7810b57cec5SDimitry Andric break; // 1,3 SUBInst $Rdd = combine(#0, #$u2)
7820b57cec5SDimitry Andric }
7830b57cec5SDimitry Andric if (Value == 2) {
7840b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_combine2i);
7850b57cec5SDimitry Andric addOps(Result, Inst, 0);
7860b57cec5SDimitry Andric addOps(Result, Inst, 2);
7870b57cec5SDimitry Andric break; // 1,3 SUBInst $Rdd = combine(#2, #$u2)
7880b57cec5SDimitry Andric }
7890b57cec5SDimitry Andric break;
7900b57cec5SDimitry Andric case Hexagon::A4_combineir:
7910b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_combinezr);
7920b57cec5SDimitry Andric addOps(Result, Inst, 0);
7930b57cec5SDimitry Andric addOps(Result, Inst, 2);
7940b57cec5SDimitry Andric break; // 1,3 SUBInst $Rdd = combine(#0, $Rs)
7950b57cec5SDimitry Andric case Hexagon::A4_combineri:
7960b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_combinerz);
7970b57cec5SDimitry Andric addOps(Result, Inst, 0);
7980b57cec5SDimitry Andric addOps(Result, Inst, 1);
7990b57cec5SDimitry Andric break; // 1,2 SUBInst $Rdd = combine($Rs, #0)
8000b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pnt:
8010b57cec5SDimitry Andric case Hexagon::L4_return_tnew_pt:
8020b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_return_tnew);
8030b57cec5SDimitry Andric break; // none SUBInst if (p0.new) dealloc_return:nt
8040b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pnt:
8050b57cec5SDimitry Andric case Hexagon::L4_return_fnew_pt:
8060b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_return_fnew);
8070b57cec5SDimitry Andric break; // none SUBInst if (!p0.new) dealloc_return:nt
8080b57cec5SDimitry Andric case Hexagon::L4_return_f:
8090b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_return_f);
8100b57cec5SDimitry Andric break; // none SUBInst if (!p0) dealloc_return
8110b57cec5SDimitry Andric case Hexagon::L4_return_t:
8120b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_return_t);
8130b57cec5SDimitry Andric break; // none SUBInst if (p0) dealloc_return
8140b57cec5SDimitry Andric case Hexagon::L4_return:
8150b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_return);
8160b57cec5SDimitry Andric break; // none SUBInst dealloc_return
8170b57cec5SDimitry Andric case Hexagon::L2_deallocframe:
8180b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_deallocframe);
8190b57cec5SDimitry Andric break; // none SUBInst deallocframe
8200b57cec5SDimitry Andric case Hexagon::EH_RETURN_JMPR:
8210b57cec5SDimitry Andric case Hexagon::J2_jumpr:
8220b57cec5SDimitry Andric case Hexagon::PS_jmpret:
8230b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_jumpr31);
8240b57cec5SDimitry Andric break; // none SUBInst jumpr r31
8250b57cec5SDimitry Andric case Hexagon::J2_jumprf:
8260b57cec5SDimitry Andric case Hexagon::PS_jmpretf:
8270b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_jumpr31_f);
8280b57cec5SDimitry Andric break; // none SUBInst if (!p0) jumpr r31
8290b57cec5SDimitry Andric case Hexagon::J2_jumprfnew:
8300b57cec5SDimitry Andric case Hexagon::PS_jmpretfnewpt:
8310b57cec5SDimitry Andric case Hexagon::PS_jmpretfnew:
8320b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_jumpr31_fnew);
8330b57cec5SDimitry Andric break; // none SUBInst if (!p0.new) jumpr:nt r31
8340b57cec5SDimitry Andric case Hexagon::J2_jumprt:
8350b57cec5SDimitry Andric case Hexagon::PS_jmprett:
8360b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_jumpr31_t);
8370b57cec5SDimitry Andric break; // none SUBInst if (p0) jumpr r31
8380b57cec5SDimitry Andric case Hexagon::J2_jumprtnew:
8390b57cec5SDimitry Andric case Hexagon::PS_jmprettnewpt:
8400b57cec5SDimitry Andric case Hexagon::PS_jmprettnew:
8410b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_jumpr31_tnew);
8420b57cec5SDimitry Andric break; // none SUBInst if (p0.new) jumpr:nt r31
8430b57cec5SDimitry Andric case Hexagon::L2_loadrb_io:
8440b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_loadrb_io);
8450b57cec5SDimitry Andric addOps(Result, Inst, 0);
8460b57cec5SDimitry Andric addOps(Result, Inst, 1);
8470b57cec5SDimitry Andric addOps(Result, Inst, 2);
8480b57cec5SDimitry Andric break; // 1,2,3 SUBInst $Rd = memb($Rs + #$u3_0)
8490b57cec5SDimitry Andric case Hexagon::L2_loadrd_io:
8500b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_loadrd_sp);
8510b57cec5SDimitry Andric addOps(Result, Inst, 0);
8520b57cec5SDimitry Andric addOps(Result, Inst, 2);
8530b57cec5SDimitry Andric break; // 1,3 SUBInst $Rdd = memd(r29 + #$u5_3)
8540b57cec5SDimitry Andric case Hexagon::L2_loadrh_io:
8550b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_loadrh_io);
8560b57cec5SDimitry Andric addOps(Result, Inst, 0);
8570b57cec5SDimitry Andric addOps(Result, Inst, 1);
8580b57cec5SDimitry Andric addOps(Result, Inst, 2);
8590b57cec5SDimitry Andric break; // 1,2,3 SUBInst $Rd = memh($Rs + #$u3_1)
8600b57cec5SDimitry Andric case Hexagon::L2_loadrub_io:
8610b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL1_loadrub_io);
8620b57cec5SDimitry Andric addOps(Result, Inst, 0);
8630b57cec5SDimitry Andric addOps(Result, Inst, 1);
8640b57cec5SDimitry Andric addOps(Result, Inst, 2);
8650b57cec5SDimitry Andric break; // 1,2,3 SUBInst $Rd = memub($Rs + #$u4_0)
8660b57cec5SDimitry Andric case Hexagon::L2_loadruh_io:
8670b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_loadruh_io);
8680b57cec5SDimitry Andric addOps(Result, Inst, 0);
8690b57cec5SDimitry Andric addOps(Result, Inst, 1);
8700b57cec5SDimitry Andric addOps(Result, Inst, 2);
8710b57cec5SDimitry Andric break; // 1,2,3 SUBInst $Rd = memuh($Rs + #$u3_1)
8720b57cec5SDimitry Andric case Hexagon::L2_loadri_io:
8730b57cec5SDimitry Andric if (Inst.getOperand(1).getReg() == Hexagon::R29) {
8740b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL2_loadri_sp);
8750b57cec5SDimitry Andric addOps(Result, Inst, 0);
8760b57cec5SDimitry Andric addOps(Result, Inst, 2);
8770b57cec5SDimitry Andric break; // 2 1,3 SUBInst $Rd = memw(r29 + #$u5_2)
8780b57cec5SDimitry Andric } else {
8790b57cec5SDimitry Andric Result.setOpcode(Hexagon::SL1_loadri_io);
8800b57cec5SDimitry Andric addOps(Result, Inst, 0);
8810b57cec5SDimitry Andric addOps(Result, Inst, 1);
8820b57cec5SDimitry Andric addOps(Result, Inst, 2);
8830b57cec5SDimitry Andric break; // 1,2,3 SUBInst $Rd = memw($Rs + #$u4_2)
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric case Hexagon::S4_storeirb_io:
8860b57cec5SDimitry Andric Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
8870b57cec5SDimitry Andric assert(Absolute);(void)Absolute;
8880b57cec5SDimitry Andric if (Value == 0) {
8890b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_storebi0);
8900b57cec5SDimitry Andric addOps(Result, Inst, 0);
8910b57cec5SDimitry Andric addOps(Result, Inst, 1);
8920b57cec5SDimitry Andric break; // 1,2 SUBInst memb($Rs + #$u4_0)=#0
8930b57cec5SDimitry Andric } else if (Value == 1) {
8940b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_storebi1);
8950b57cec5SDimitry Andric addOps(Result, Inst, 0);
8960b57cec5SDimitry Andric addOps(Result, Inst, 1);
8970b57cec5SDimitry Andric break; // 2 1,2 SUBInst memb($Rs + #$u4_0)=#1
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric break;
9000b57cec5SDimitry Andric case Hexagon::S2_storerb_io:
9010b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS1_storeb_io);
9020b57cec5SDimitry Andric addOps(Result, Inst, 0);
9030b57cec5SDimitry Andric addOps(Result, Inst, 1);
9040b57cec5SDimitry Andric addOps(Result, Inst, 2);
9050b57cec5SDimitry Andric break; // 1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
9060b57cec5SDimitry Andric case Hexagon::S2_storerd_io:
9070b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_stored_sp);
9080b57cec5SDimitry Andric addOps(Result, Inst, 1);
9090b57cec5SDimitry Andric addOps(Result, Inst, 2);
9100b57cec5SDimitry Andric break; // 2,3 SUBInst memd(r29 + #$s6_3) = $Rtt
9110b57cec5SDimitry Andric case Hexagon::S2_storerh_io:
9120b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_storeh_io);
9130b57cec5SDimitry Andric addOps(Result, Inst, 0);
9140b57cec5SDimitry Andric addOps(Result, Inst, 1);
9150b57cec5SDimitry Andric addOps(Result, Inst, 2);
9160b57cec5SDimitry Andric break; // 1,2,3 SUBInst memb($Rs + #$u4_0) = $Rt
9170b57cec5SDimitry Andric case Hexagon::S4_storeiri_io:
9180b57cec5SDimitry Andric Absolute = Inst.getOperand(2).getExpr()->evaluateAsAbsolute(Value);
9190b57cec5SDimitry Andric assert(Absolute);(void)Absolute;
9200b57cec5SDimitry Andric if (Value == 0) {
9210b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_storewi0);
9220b57cec5SDimitry Andric addOps(Result, Inst, 0);
9230b57cec5SDimitry Andric addOps(Result, Inst, 1);
9240b57cec5SDimitry Andric break; // 3 1,2 SUBInst memw($Rs + #$u4_2)=#0
9250b57cec5SDimitry Andric } else if (Value == 1) {
9260b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_storewi1);
9270b57cec5SDimitry Andric addOps(Result, Inst, 0);
9280b57cec5SDimitry Andric addOps(Result, Inst, 1);
9290b57cec5SDimitry Andric break; // 3 1,2 SUBInst memw($Rs + #$u4_2)=#1
9300b57cec5SDimitry Andric } else if (Inst.getOperand(0).getReg() == Hexagon::R29) {
9310b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_storew_sp);
9320b57cec5SDimitry Andric addOps(Result, Inst, 1);
9330b57cec5SDimitry Andric addOps(Result, Inst, 2);
9340b57cec5SDimitry Andric break; // 1 2,3 SUBInst memw(r29 + #$u5_2) = $Rt
9350b57cec5SDimitry Andric }
9360b57cec5SDimitry Andric break;
9370b57cec5SDimitry Andric case Hexagon::S2_storeri_io:
9380b57cec5SDimitry Andric if (Inst.getOperand(0).getReg() == Hexagon::R29) {
9390b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS2_storew_sp);
9400b57cec5SDimitry Andric addOps(Result, Inst, 1);
9410b57cec5SDimitry Andric addOps(Result, Inst, 2); // 1,2,3 SUBInst memw(sp + #$u5_2) = $Rt
9420b57cec5SDimitry Andric } else {
9430b57cec5SDimitry Andric Result.setOpcode(Hexagon::SS1_storew_io);
9440b57cec5SDimitry Andric addOps(Result, Inst, 0);
9450b57cec5SDimitry Andric addOps(Result, Inst, 1);
9460b57cec5SDimitry Andric addOps(Result, Inst, 2); // 1,2,3 SUBInst memw($Rs + #$u4_2) = $Rt
9470b57cec5SDimitry Andric }
9480b57cec5SDimitry Andric break;
9490b57cec5SDimitry Andric case Hexagon::A2_sxtb:
9500b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_sxtb);
9510b57cec5SDimitry Andric addOps(Result, Inst, 0);
9520b57cec5SDimitry Andric addOps(Result, Inst, 1);
9530b57cec5SDimitry Andric break; // 1,2 SUBInst $Rd = sxtb($Rs)
9540b57cec5SDimitry Andric case Hexagon::A2_sxth:
9550b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_sxth);
9560b57cec5SDimitry Andric addOps(Result, Inst, 0);
9570b57cec5SDimitry Andric addOps(Result, Inst, 1);
9580b57cec5SDimitry Andric break; // 1,2 SUBInst $Rd = sxth($Rs)
9590b57cec5SDimitry Andric case Hexagon::A2_tfr:
9600b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_tfr);
9610b57cec5SDimitry Andric addOps(Result, Inst, 0);
9620b57cec5SDimitry Andric addOps(Result, Inst, 1);
9630b57cec5SDimitry Andric break; // 1,2 SUBInst $Rd = $Rs
9640b57cec5SDimitry Andric case Hexagon::C2_cmovenewif:
9650b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_clrfnew);
9660b57cec5SDimitry Andric addOps(Result, Inst, 0);
9670b57cec5SDimitry Andric addOps(Result, Inst, 1);
9680b57cec5SDimitry Andric break; // 2 SUBInst if (!p0.new) $Rd = #0
9690b57cec5SDimitry Andric case Hexagon::C2_cmovenewit:
9700b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_clrtnew);
9710b57cec5SDimitry Andric addOps(Result, Inst, 0);
9720b57cec5SDimitry Andric addOps(Result, Inst, 1);
9730b57cec5SDimitry Andric break; // 2 SUBInst if (p0.new) $Rd = #0
9740b57cec5SDimitry Andric case Hexagon::C2_cmoveif:
9750b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_clrf);
9760b57cec5SDimitry Andric addOps(Result, Inst, 0);
9770b57cec5SDimitry Andric addOps(Result, Inst, 1);
9780b57cec5SDimitry Andric break; // 2 SUBInst if (!p0) $Rd = #0
9790b57cec5SDimitry Andric case Hexagon::C2_cmoveit:
9800b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_clrt);
9810b57cec5SDimitry Andric addOps(Result, Inst, 0);
9820b57cec5SDimitry Andric addOps(Result, Inst, 1);
9830b57cec5SDimitry Andric break; // 2 SUBInst if (p0) $Rd = #0
9840b57cec5SDimitry Andric case Hexagon::A2_tfrsi:
9850b57cec5SDimitry Andric Absolute = Inst.getOperand(1).getExpr()->evaluateAsAbsolute(Value);
9860b57cec5SDimitry Andric if (Absolute && Value == -1) {
9870b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_setin1);
9880b57cec5SDimitry Andric addOps(Result, Inst, 0);
9890b57cec5SDimitry Andric addOps(Result, Inst, 1);
9900b57cec5SDimitry Andric break; // 2 1 SUBInst $Rd = #-1
9910b57cec5SDimitry Andric } else {
9920b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_seti);
9930b57cec5SDimitry Andric addOps(Result, Inst, 0);
9940b57cec5SDimitry Andric addOps(Result, Inst, 1);
9950b57cec5SDimitry Andric break; // 1,2 SUBInst $Rd = #$u6
9960b57cec5SDimitry Andric }
9970b57cec5SDimitry Andric case Hexagon::A2_zxtb:
9980b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_zxtb);
9990b57cec5SDimitry Andric addOps(Result, Inst, 0);
10000b57cec5SDimitry Andric addOps(Result, Inst, 1);
10010b57cec5SDimitry Andric break; // 1,2 $Rd = and($Rs, #255)
10020b57cec5SDimitry Andric
10030b57cec5SDimitry Andric case Hexagon::A2_zxth:
10040b57cec5SDimitry Andric Result.setOpcode(Hexagon::SA1_zxth);
10050b57cec5SDimitry Andric addOps(Result, Inst, 0);
10060b57cec5SDimitry Andric addOps(Result, Inst, 1);
10070b57cec5SDimitry Andric break; // 1,2 SUBInst $Rd = zxth($Rs)
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric return Result;
10100b57cec5SDimitry Andric }
10110b57cec5SDimitry Andric
isStoreInst(unsigned opCode)10120b57cec5SDimitry Andric static bool isStoreInst(unsigned opCode) {
10130b57cec5SDimitry Andric switch (opCode) {
10140b57cec5SDimitry Andric case Hexagon::S2_storeri_io:
10150b57cec5SDimitry Andric case Hexagon::S2_storerb_io:
10160b57cec5SDimitry Andric case Hexagon::S2_storerh_io:
10170b57cec5SDimitry Andric case Hexagon::S2_storerd_io:
10180b57cec5SDimitry Andric case Hexagon::S4_storeiri_io:
10190b57cec5SDimitry Andric case Hexagon::S4_storeirb_io:
10200b57cec5SDimitry Andric case Hexagon::S2_allocframe:
10210b57cec5SDimitry Andric return true;
10220b57cec5SDimitry Andric default:
10230b57cec5SDimitry Andric return false;
10240b57cec5SDimitry Andric }
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andric SmallVector<DuplexCandidate, 8>
getDuplexPossibilties(MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst const & MCB)10280b57cec5SDimitry Andric HexagonMCInstrInfo::getDuplexPossibilties(MCInstrInfo const &MCII,
10290b57cec5SDimitry Andric MCSubtargetInfo const &STI,
10300b57cec5SDimitry Andric MCInst const &MCB) {
10310b57cec5SDimitry Andric assert(isBundle(MCB));
10320b57cec5SDimitry Andric SmallVector<DuplexCandidate, 8> duplexToTry;
10330b57cec5SDimitry Andric // Use an "order matters" version of isDuplexPair.
10340b57cec5SDimitry Andric unsigned numInstrInPacket = MCB.getNumOperands();
10350b57cec5SDimitry Andric
10360b57cec5SDimitry Andric for (unsigned distance = 1; distance < numInstrInPacket; ++distance) {
10370b57cec5SDimitry Andric for (unsigned j = HexagonMCInstrInfo::bundleInstructionsOffset,
10380b57cec5SDimitry Andric k = j + distance;
10390b57cec5SDimitry Andric (j < numInstrInPacket) && (k < numInstrInPacket); ++j, ++k) {
10400b57cec5SDimitry Andric
10410b57cec5SDimitry Andric // Check if reversible.
10420b57cec5SDimitry Andric bool bisReversable = true;
10430b57cec5SDimitry Andric if (isStoreInst(MCB.getOperand(j).getInst()->getOpcode()) &&
10440b57cec5SDimitry Andric isStoreInst(MCB.getOperand(k).getInst()->getOpcode())) {
10450b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "skip out of order write pair: " << k << "," << j
10460b57cec5SDimitry Andric << "\n");
10470b57cec5SDimitry Andric bisReversable = false;
10480b57cec5SDimitry Andric }
10490b57cec5SDimitry Andric if (HexagonMCInstrInfo::isMemReorderDisabled(MCB)) // }:mem_noshuf
10500b57cec5SDimitry Andric bisReversable = false;
10510b57cec5SDimitry Andric
10520b57cec5SDimitry Andric // Try in order.
10530b57cec5SDimitry Andric if (isOrderedDuplexPair(
10540b57cec5SDimitry Andric MCII, *MCB.getOperand(k).getInst(),
10550b57cec5SDimitry Andric HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
10560b57cec5SDimitry Andric *MCB.getOperand(j).getInst(),
10570b57cec5SDimitry Andric HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
10580b57cec5SDimitry Andric bisReversable, STI)) {
10590b57cec5SDimitry Andric // Get iClass.
10600b57cec5SDimitry Andric unsigned iClass = iClassOfDuplexPair(
10610b57cec5SDimitry Andric getDuplexCandidateGroup(*MCB.getOperand(k).getInst()),
10620b57cec5SDimitry Andric getDuplexCandidateGroup(*MCB.getOperand(j).getInst()));
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andric // Save off pairs for duplex checking.
10650b57cec5SDimitry Andric duplexToTry.push_back(DuplexCandidate(j, k, iClass));
10660b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "adding pair: " << j << "," << k << ":"
10670b57cec5SDimitry Andric << MCB.getOperand(j).getInst()->getOpcode() << ","
10680b57cec5SDimitry Andric << MCB.getOperand(k).getInst()->getOpcode() << "\n");
10690b57cec5SDimitry Andric continue;
10700b57cec5SDimitry Andric } else {
10710b57cec5SDimitry Andric LLVM_DEBUG(dbgs() << "skipping pair: " << j << "," << k << ":"
10720b57cec5SDimitry Andric << MCB.getOperand(j).getInst()->getOpcode() << ","
10730b57cec5SDimitry Andric << MCB.getOperand(k).getInst()->getOpcode() << "\n");
10740b57cec5SDimitry Andric }
10750b57cec5SDimitry Andric
10760b57cec5SDimitry Andric // Try reverse.
10770b57cec5SDimitry Andric if (bisReversable) {
10780b57cec5SDimitry Andric if (isOrderedDuplexPair(
10790b57cec5SDimitry Andric MCII, *MCB.getOperand(j).getInst(),
10800b57cec5SDimitry Andric HexagonMCInstrInfo::hasExtenderForIndex(MCB, j - 1),
10810b57cec5SDimitry Andric *MCB.getOperand(k).getInst(),
10820b57cec5SDimitry Andric HexagonMCInstrInfo::hasExtenderForIndex(MCB, k - 1),
10830b57cec5SDimitry Andric bisReversable, STI)) {
10840b57cec5SDimitry Andric // Get iClass.
10850b57cec5SDimitry Andric unsigned iClass = iClassOfDuplexPair(
10860b57cec5SDimitry Andric getDuplexCandidateGroup(*MCB.getOperand(j).getInst()),
10870b57cec5SDimitry Andric getDuplexCandidateGroup(*MCB.getOperand(k).getInst()));
10880b57cec5SDimitry Andric
10890b57cec5SDimitry Andric // Save off pairs for duplex checking.
10900b57cec5SDimitry Andric duplexToTry.push_back(DuplexCandidate(k, j, iClass));
10910b57cec5SDimitry Andric LLVM_DEBUG(dbgs()
10920b57cec5SDimitry Andric << "adding pair:" << k << "," << j << ":"
10930b57cec5SDimitry Andric << MCB.getOperand(j).getInst()->getOpcode() << ","
10940b57cec5SDimitry Andric << MCB.getOperand(k).getInst()->getOpcode() << "\n");
10950b57cec5SDimitry Andric } else {
10960b57cec5SDimitry Andric LLVM_DEBUG(dbgs()
10970b57cec5SDimitry Andric << "skipping pair: " << k << "," << j << ":"
10980b57cec5SDimitry Andric << MCB.getOperand(j).getInst()->getOpcode() << ","
10990b57cec5SDimitry Andric << MCB.getOperand(k).getInst()->getOpcode() << "\n");
11000b57cec5SDimitry Andric }
11010b57cec5SDimitry Andric }
11020b57cec5SDimitry Andric }
11030b57cec5SDimitry Andric }
11040b57cec5SDimitry Andric return duplexToTry;
11050b57cec5SDimitry Andric }
1106