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