219 lines · cpp
1//===----- HexagonMCShuffler.cpp - MC bundle shuffling --------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This implements the shuffling of insns inside a bundle according to the10// packet formation rules of the Hexagon ISA.11//12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/HexagonMCShuffler.h"15#include "MCTargetDesc/HexagonMCInstrInfo.h"16#include "MCTargetDesc/HexagonShuffler.h"17#include "llvm/MC/MCInst.h"18#include "llvm/MC/MCInstrDesc.h"19#include "llvm/MC/MCInstrInfo.h"20#include "llvm/Support/CommandLine.h"21#include "llvm/Support/Debug.h"22#include "llvm/Support/raw_ostream.h"23#include <cassert>24 25#define DEBUG_TYPE "hexagon-shuffle"26 27using namespace llvm;28 29static cl::opt<bool>30 DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false),31 cl::desc("Disable Hexagon instruction shuffling"));32 33void HexagonMCShuffler::init(MCInst &MCB) {34 if (HexagonMCInstrInfo::isBundle(MCB)) {35 MCInst const *Extender = nullptr;36 // Copy the bundle for the shuffling.37 for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {38 MCInst &MI = *const_cast<MCInst *>(I.getInst());39 LLVM_DEBUG(dbgs() << "Shuffling: " << MCII.getName(MI.getOpcode())40 << '\n');41 assert(!HexagonMCInstrInfo::getDesc(MCII, MI).isPseudo());42 43 if (!HexagonMCInstrInfo::isImmext(MI)) {44 append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));45 Extender = nullptr;46 } else47 Extender = &MI;48 }49 }50 51 Loc = MCB.getLoc();52 BundleFlags = MCB.getOperand(0).getImm();53}54 55void HexagonMCShuffler::init(MCInst &MCB, MCInst const &AddMI,56 bool bInsertAtFront) {57 if (HexagonMCInstrInfo::isBundle(MCB)) {58 if (bInsertAtFront)59 append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));60 MCInst const *Extender = nullptr;61 // Copy the bundle for the shuffling.62 for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {63 assert(!HexagonMCInstrInfo::getDesc(MCII, *I.getInst()).isPseudo());64 MCInst &MI = *const_cast<MCInst *>(I.getInst());65 if (!HexagonMCInstrInfo::isImmext(MI)) {66 append(MI, Extender, HexagonMCInstrInfo::getUnits(MCII, STI, MI));67 Extender = nullptr;68 } else69 Extender = &MI;70 }71 if (!bInsertAtFront)72 append(AddMI, nullptr, HexagonMCInstrInfo::getUnits(MCII, STI, AddMI));73 }74 75 Loc = MCB.getLoc();76 BundleFlags = MCB.getOperand(0).getImm();77}78 79void HexagonMCShuffler::copyTo(MCInst &MCB) {80 MCB.clear();81 MCB.addOperand(MCOperand::createImm(BundleFlags));82 MCB.setLoc(Loc);83 // Copy the results into the bundle.84 for (auto &I : *this) {85 MCInst const &MI = I.getDesc();86 MCInst const *Extender = I.getExtender();87 if (Extender)88 MCB.addOperand(MCOperand::createInst(Extender));89 MCB.addOperand(MCOperand::createInst(&MI));90 }91}92 93bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) {94 if (shuffle()) {95 // Copy the results into the bundle.96 copyTo(MCB);97 return true;98 }99 LLVM_DEBUG(MCB.dump());100 return false;101}102 103bool llvm::HexagonMCShuffle(MCContext &Context, bool ReportErrors,104 MCInstrInfo const &MCII, MCSubtargetInfo const &STI,105 MCInst &MCB) {106 HexagonMCShuffler MCS(Context, ReportErrors, MCII, STI, MCB);107 108 if (DisableShuffle)109 // Ignore if user chose so.110 return false;111 112 if (!HexagonMCInstrInfo::bundleSize(MCB)) {113 // There once was a bundle:114 // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,115 // implicit-def %d7, ...116 // * %d2 = IMPLICIT_DEF; flags:117 // * %d7 = IMPLICIT_DEF; flags:118 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle119 // became empty.120 LLVM_DEBUG(dbgs() << "Skipping empty bundle");121 return false;122 } else if (!HexagonMCInstrInfo::isBundle(MCB)) {123 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");124 return false;125 }126 127 return MCS.reshuffleTo(MCB);128}129 130bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,131 MCSubtargetInfo const &STI, MCInst &MCB,132 SmallVector<DuplexCandidate, 8> possibleDuplexes) {133 134 if (DisableShuffle || possibleDuplexes.size() == 0)135 return false;136 137 if (!HexagonMCInstrInfo::bundleSize(MCB)) {138 // There once was a bundle:139 // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,140 // implicit-def %d7, ...141 // * %d2 = IMPLICIT_DEF; flags:142 // * %d7 = IMPLICIT_DEF; flags:143 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle144 // became empty.145 LLVM_DEBUG(dbgs() << "Skipping empty bundle");146 return false;147 } else if (!HexagonMCInstrInfo::isBundle(MCB)) {148 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn");149 return false;150 }151 152 bool doneShuffling = false;153 while (possibleDuplexes.size() > 0 && (!doneShuffling)) {154 // case of Duplex Found155 DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val();156 MCInst Attempt(MCB);157 HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry);158 HexagonMCShuffler MCS(Context, false, MCII, STI, Attempt); // copy packet to the shuffler159 if (MCS.size() == 1) { // case of one duplex160 // copy the created duplex in the shuffler to the bundle161 MCS.copyTo(MCB);162 return false;163 }164 // try shuffle with this duplex165 doneShuffling = MCS.reshuffleTo(MCB);166 167 if (doneShuffling)168 break;169 }170 171 if (!doneShuffling) {172 HexagonMCShuffler MCS(Context, false, MCII, STI, MCB);173 doneShuffling = MCS.reshuffleTo(MCB); // shuffle174 }175 176 return doneShuffling;177}178 179bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,180 MCSubtargetInfo const &STI, MCInst &MCB,181 MCInst const &AddMI, int fixupCount) {182 if (!HexagonMCInstrInfo::isBundle(MCB))183 return false;184 185 // if fixups present, make sure we don't insert too many nops that would186 // later prevent an extender from being inserted.187 unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB);188 if (bundleSize >= HEXAGON_PACKET_SIZE)189 return false;190 bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, MCB);191 if (fixupCount >= 2) {192 if (bhasDuplex) {193 if (bundleSize >= HEXAGON_PACKET_SIZE - 1) {194 return false;195 }196 } else {197 return false;198 }199 } else {200 if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount)201 return false;202 }203 204 if (DisableShuffle)205 return false;206 207 // mgl: temporary code (shuffler doesn't take into account the fact that208 // a duplex takes up two slots. for example, 3 nops can be put into a packet209 // containing a duplex oversubscribing slots by 1).210 unsigned maxBundleSize = (HexagonMCInstrInfo::hasImmExt(MCB))211 ? HEXAGON_PACKET_SIZE212 : HEXAGON_PACKET_SIZE - 1;213 if (bhasDuplex && bundleSize >= maxBundleSize)214 return false;215 216 HexagonMCShuffler MCS(Context, false, MCII, STI, MCB, AddMI, false);217 return MCS.reshuffleTo(MCB);218}219