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