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