xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCShuffler.cpp (revision 04eeddc0aa8e0a417a16eaf9d7d095207f4a8623)
10b57cec5SDimitry Andric //===----- HexagonMCShuffler.cpp - MC bundle shuffling --------------------===//
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 the shuffling of insns inside a bundle according to the
100b57cec5SDimitry Andric // packet formation rules of the Hexagon ISA.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCShuffler.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/HexagonMCInstrInfo.h"
160b57cec5SDimitry Andric #include "MCTargetDesc/HexagonShuffler.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInstrDesc.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
200b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
210b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
230b57cec5SDimitry Andric #include <cassert>
240b57cec5SDimitry Andric 
25fe6060f1SDimitry Andric #define DEBUG_TYPE "hexagon-shuffle"
26fe6060f1SDimitry Andric 
270b57cec5SDimitry Andric using namespace llvm;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric static cl::opt<bool>
300b57cec5SDimitry Andric     DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),
310b57cec5SDimitry Andric                    cl::desc("Disable Hexagon instruction shuffling"));
320b57cec5SDimitry Andric 
init(MCInst & MCB)330b57cec5SDimitry Andric void HexagonMCShuffler::init(MCInst &MCB) {
340b57cec5SDimitry Andric   if (HexagonMCInstrInfo::isBundle(MCB)) {
350b57cec5SDimitry Andric     MCInst const *Extender = nullptr;
360b57cec5SDimitry Andric     // Copy the bundle for the shuffling.
370b57cec5SDimitry Andric     for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
380b57cec5SDimitry Andric       MCInst &MI = *const_cast<MCInst *>(I.getInst());
390b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Shuffling: " << MCII.getName(MI.getOpcode())
400b57cec5SDimitry Andric                         << '\n');
410b57cec5SDimitry Andric       assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo());
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric       if (!HexagonMCInstrInfo::isImmext(MI)) {
440b57cec5SDimitry Andric         append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));
450b57cec5SDimitry Andric         Extender = nullptr;
460b57cec5SDimitry Andric       } else
470b57cec5SDimitry Andric         Extender = &MI;
480b57cec5SDimitry Andric     }
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   Loc = MCB.getLoc();
520b57cec5SDimitry Andric   BundleFlags = MCB.getOperand(0).getImm();
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
init(MCInst & MCB,MCInst const & AddMI,bool bInsertAtFront)550b57cec5SDimitry Andric void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI,
560b57cec5SDimitry Andric                              bool bInsertAtFront) {
570b57cec5SDimitry Andric   if (HexagonMCInstrInfo::isBundle(MCB)) {
580b57cec5SDimitry Andric     if (bInsertAtFront)
590b57cec5SDimitry Andric       append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
600b57cec5SDimitry Andric     MCInst const *Extender = nullptr;
610b57cec5SDimitry Andric     // Copy the bundle for the shuffling.
620b57cec5SDimitry Andric     for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
630b57cec5SDimitry Andric       assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());
640b57cec5SDimitry Andric       MCInst &MI = *const_cast<MCInst *>(I.getInst());
650b57cec5SDimitry Andric       if (!HexagonMCInstrInfo::isImmext(MI)) {
660b57cec5SDimitry Andric         append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));
670b57cec5SDimitry Andric         Extender = nullptr;
680b57cec5SDimitry Andric       } else
690b57cec5SDimitry Andric         Extender = &MI;
700b57cec5SDimitry Andric     }
710b57cec5SDimitry Andric     if (!bInsertAtFront)
720b57cec5SDimitry Andric       append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));
730b57cec5SDimitry Andric   }
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   Loc = MCB.getLoc();
760b57cec5SDimitry Andric   BundleFlags = MCB.getOperand(0).getImm();
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
copyTo(MCInst & MCB)790b57cec5SDimitry Andric void HexagonMCShuffler::copyTo(MCInst &MCB) {
800b57cec5SDimitry Andric   MCB.clear();
810b57cec5SDimitry Andric   MCB.addOperand(MCOperand::createImm(BundleFlags));
820b57cec5SDimitry Andric   MCB.setLoc(Loc);
830b57cec5SDimitry Andric   // Copy the results into the bundle.
84*04eeddc0SDimitry Andric   for (auto &I : *this) {
85*04eeddc0SDimitry Andric     MCInst const &MI = I.getDesc();
86*04eeddc0SDimitry Andric     MCInst const *Extender = I.getExtender();
870b57cec5SDimitry Andric     if (Extender)
880b57cec5SDimitry Andric       MCB.addOperand(MCOperand::createInst(Extender));
890b57cec5SDimitry Andric     MCB.addOperand(MCOperand::createInst(&MI));
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
reshuffleTo(MCInst & MCB)930b57cec5SDimitry Andric bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {
940b57cec5SDimitry Andric   if (shuffle()) {
950b57cec5SDimitry Andric     // Copy the results into the bundle.
960b57cec5SDimitry Andric     copyTo(MCB);
970b57cec5SDimitry Andric     return true;
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric   LLVM_DEBUG(MCB.dump());
1000b57cec5SDimitry Andric   return false;
1010b57cec5SDimitry Andric }
1020b57cec5SDimitry Andric 
HexagonMCShuffle(MCContext & Context,bool ReportErrors,MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB)103*04eeddc0SDimitry Andric bool llvm::HexagonMCShuffle(MCContext &Context, bool ReportErrors,
1040b57cec5SDimitry Andric                             MCInstrInfo const &MCII, MCSubtargetInfo const &STI,
1050b57cec5SDimitry Andric                             MCInst &MCB) {
106*04eeddc0SDimitry Andric   HexagonMCShuffler MCS(Context, ReportErrors, MCII, STI, MCB);
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   if (DisableShuffle)
1090b57cec5SDimitry Andric     // Ignore if user chose so.
1100b57cec5SDimitry Andric     return false;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   if (!HexagonMCInstrInfo::bundleSize(MCB)) {
1130b57cec5SDimitry Andric     // There once was a bundle:
1140b57cec5SDimitry Andric     //    BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
1150b57cec5SDimitry Andric     //    implicit-def %d7, ...
1160b57cec5SDimitry Andric     //      * %d2 = IMPLICIT_DEF; flags:
1170b57cec5SDimitry Andric     //      * %d7 = IMPLICIT_DEF; flags:
1180b57cec5SDimitry Andric     // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
1190b57cec5SDimitry Andric     // became empty.
1200b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping empty bundle");
1210b57cec5SDimitry Andric     return false;
1220b57cec5SDimitry Andric   } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
1230b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");
1240b57cec5SDimitry Andric     return false;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   return MCS.reshuffleTo(MCB);
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric 
HexagonMCShuffle(MCContext & Context,MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB,SmallVector<DuplexCandidate,8> possibleDuplexes)130*04eeddc0SDimitry Andric bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
1310b57cec5SDimitry Andric                             MCSubtargetInfo const &STI, MCInst &MCB,
1320b57cec5SDimitry Andric                             SmallVector<DuplexCandidate, 8> possibleDuplexes) {
133*04eeddc0SDimitry Andric 
134*04eeddc0SDimitry Andric   if (DisableShuffle || possibleDuplexes.size() == 0)
1350b57cec5SDimitry Andric     return false;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   if (!HexagonMCInstrInfo::bundleSize(MCB)) {
1380b57cec5SDimitry Andric     // There once was a bundle:
1390b57cec5SDimitry Andric     //    BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
1400b57cec5SDimitry Andric     //    implicit-def %d7, ...
1410b57cec5SDimitry Andric     //      * %d2 = IMPLICIT_DEF; flags:
1420b57cec5SDimitry Andric     //      * %d7 = IMPLICIT_DEF; flags:
1430b57cec5SDimitry Andric     // After the IMPLICIT_DEFs were removed by the asm printer, the bundle
1440b57cec5SDimitry Andric     // became empty.
1450b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping empty bundle");
1460b57cec5SDimitry Andric     return false;
1470b57cec5SDimitry Andric   } else if (!HexagonMCInstrInfo::isBundle(MCB)) {
1480b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");
1490b57cec5SDimitry Andric     return false;
1500b57cec5SDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   bool doneShuffling = false;
1530b57cec5SDimitry Andric   while (possibleDuplexes.size() > 0 && (!doneShuffling)) {
1540b57cec5SDimitry Andric     // case of Duplex Found
1550b57cec5SDimitry Andric     DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();
1560b57cec5SDimitry Andric     MCInst Attempt(MCB);
1570b57cec5SDimitry Andric     HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry);
1580b57cec5SDimitry Andric     HexagonMCShuffler MCS(Context, false, MCII, STI, Attempt); // copy packet to the shuffler
1590b57cec5SDimitry Andric     if (MCS.size() == 1) {                     // case of one duplex
1600b57cec5SDimitry Andric       // copy the created duplex in the shuffler to the bundle
1610b57cec5SDimitry Andric       MCS.copyTo(MCB);
1620b57cec5SDimitry Andric       return false;
1630b57cec5SDimitry Andric     }
1640b57cec5SDimitry Andric     // try shuffle with this duplex
1650b57cec5SDimitry Andric     doneShuffling = MCS.reshuffleTo(MCB);
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric     if (doneShuffling)
1680b57cec5SDimitry Andric       break;
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   if (!doneShuffling) {
1720b57cec5SDimitry Andric     HexagonMCShuffler MCS(Context, false, MCII, STI, MCB);
1730b57cec5SDimitry Andric     doneShuffling = MCS.reshuffleTo(MCB); // shuffle
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric 
176*04eeddc0SDimitry Andric   return doneShuffling;
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric 
HexagonMCShuffle(MCContext & Context,MCInstrInfo const & MCII,MCSubtargetInfo const & STI,MCInst & MCB,MCInst const & AddMI,int fixupCount)1790b57cec5SDimitry Andric bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
1800b57cec5SDimitry Andric                             MCSubtargetInfo const &STI, MCInst &MCB,
1810b57cec5SDimitry Andric                             MCInst const &AddMI, int fixupCount) {
1820b57cec5SDimitry Andric   if (!HexagonMCInstrInfo::isBundle(MCB))
1830b57cec5SDimitry Andric     return false;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   // if fixups present, make sure we don't insert too many nops that would
1860b57cec5SDimitry Andric   // later prevent an extender from being inserted.
1870b57cec5SDimitry Andric   unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);
1880b57cec5SDimitry Andric   if (bundleSize >= HEXAGON_PACKET_SIZE)
1890b57cec5SDimitry Andric     return false;
1900b57cec5SDimitry Andric   bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, MCB);
1910b57cec5SDimitry Andric   if (fixupCount >= 2) {
1920b57cec5SDimitry Andric     if (bhasDuplex) {
1930b57cec5SDimitry Andric       if (bundleSize >= HEXAGON_PACKET_SIZE - 1) {
1940b57cec5SDimitry Andric         return false;
1950b57cec5SDimitry Andric       }
1960b57cec5SDimitry Andric     } else {
1970b57cec5SDimitry Andric       return false;
1980b57cec5SDimitry Andric     }
1990b57cec5SDimitry Andric   } else {
2000b57cec5SDimitry Andric     if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)
2010b57cec5SDimitry Andric       return false;
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   if (DisableShuffle)
2050b57cec5SDimitry Andric     return false;
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   // mgl: temporary code (shuffler doesn't take into account the fact that
2080b57cec5SDimitry Andric   // a duplex takes up two slots.  for example, 3 nops can be put into a packet
2090b57cec5SDimitry Andric   // containing a duplex oversubscribing slots by 1).
2100b57cec5SDimitry Andric   unsigned maxBundleSize = (HexagonMCInstrInfo::hasImmExt(MCB))
2110b57cec5SDimitry Andric                                ? HEXAGON_PACKET_SIZE
2120b57cec5SDimitry Andric                                : HEXAGON_PACKET_SIZE - 1;
2130b57cec5SDimitry Andric   if (bhasDuplex && bundleSize >= maxBundleSize)
2140b57cec5SDimitry Andric     return false;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   HexagonMCShuffler MCS(Context, false, MCII, STI, MCB, AddMI, false);
2170b57cec5SDimitry Andric   return MCS.reshuffleTo(MCB);
2180b57cec5SDimitry Andric }
219