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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This implements the shuffling of insns inside a bundle according to the 10 // packet formation rules of the Hexagon ISA. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #define DEBUG_TYPE "hexagon-shuffle" 15 16 #include "MCTargetDesc/HexagonMCShuffler.h" 17 #include "MCTargetDesc/HexagonMCInstrInfo.h" 18 #include "MCTargetDesc/HexagonShuffler.h" 19 #include "llvm/MC/MCInst.h" 20 #include "llvm/MC/MCInstrDesc.h" 21 #include "llvm/MC/MCInstrInfo.h" 22 #include "llvm/Support/CommandLine.h" 23 #include "llvm/Support/Debug.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <cassert> 26 27 using namespace llvm; 28 29 static cl::opt<bool> 30 DisableShuffle("disable-hexagon-shuffle", cl::Hidden, cl::init(false), 31 cl::desc("Disable Hexagon instruction shuffling")); 32 33 void 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 } else 47 Extender = &MI; 48 } 49 } 50 51 Loc = MCB.getLoc(); 52 BundleFlags = MCB.getOperand(0).getImm(); 53 } 54 55 void 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 } else 69 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 79 void 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 (HexagonShuffler::iterator I = begin(); I != end(); ++I) { 85 86 MCInst const &MI = I->getDesc(); 87 MCInst const *Extender = I->getExtender(); 88 if (Extender) 89 MCB.addOperand(MCOperand::createInst(Extender)); 90 MCB.addOperand(MCOperand::createInst(&MI)); 91 } 92 } 93 94 bool HexagonMCShuffler::reshuffleTo(MCInst &MCB) { 95 if (shuffle()) { 96 // Copy the results into the bundle. 97 copyTo(MCB); 98 return true; 99 } 100 LLVM_DEBUG(MCB.dump()); 101 return false; 102 } 103 104 bool llvm::HexagonMCShuffle(MCContext &Context, bool Fatal, 105 MCInstrInfo const &MCII, MCSubtargetInfo const &STI, 106 MCInst &MCB) { 107 HexagonMCShuffler MCS(Context, Fatal, MCII, STI, MCB); 108 109 if (DisableShuffle) 110 // Ignore if user chose so. 111 return false; 112 113 if (!HexagonMCInstrInfo::bundleSize(MCB)) { 114 // There once was a bundle: 115 // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5, 116 // implicit-def %d7, ... 117 // * %d2 = IMPLICIT_DEF; flags: 118 // * %d7 = IMPLICIT_DEF; flags: 119 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle 120 // became empty. 121 LLVM_DEBUG(dbgs() << "Skipping empty bundle"); 122 return false; 123 } else if (!HexagonMCInstrInfo::isBundle(MCB)) { 124 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn"); 125 return false; 126 } 127 128 return MCS.reshuffleTo(MCB); 129 } 130 131 bool 132 llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII, 133 MCSubtargetInfo const &STI, MCInst &MCB, 134 SmallVector<DuplexCandidate, 8> possibleDuplexes) { 135 if (DisableShuffle) 136 return false; 137 138 if (!HexagonMCInstrInfo::bundleSize(MCB)) { 139 // There once was a bundle: 140 // BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5, 141 // implicit-def %d7, ... 142 // * %d2 = IMPLICIT_DEF; flags: 143 // * %d7 = IMPLICIT_DEF; flags: 144 // After the IMPLICIT_DEFs were removed by the asm printer, the bundle 145 // became empty. 146 LLVM_DEBUG(dbgs() << "Skipping empty bundle"); 147 return false; 148 } else if (!HexagonMCInstrInfo::isBundle(MCB)) { 149 LLVM_DEBUG(dbgs() << "Skipping stand-alone insn"); 150 return false; 151 } 152 153 bool doneShuffling = false; 154 while (possibleDuplexes.size() > 0 && (!doneShuffling)) { 155 // case of Duplex Found 156 DuplexCandidate duplexToTry = possibleDuplexes.pop_back_val(); 157 MCInst Attempt(MCB); 158 HexagonMCInstrInfo::replaceDuplex(Context, Attempt, duplexToTry); 159 HexagonMCShuffler MCS(Context, false, MCII, STI, Attempt); // copy packet to the shuffler 160 if (MCS.size() == 1) { // case of one duplex 161 // copy the created duplex in the shuffler to the bundle 162 MCS.copyTo(MCB); 163 return false; 164 } 165 // try shuffle with this duplex 166 doneShuffling = MCS.reshuffleTo(MCB); 167 168 if (doneShuffling) 169 break; 170 } 171 172 if (!doneShuffling) { 173 HexagonMCShuffler MCS(Context, false, MCII, STI, MCB); 174 doneShuffling = MCS.reshuffleTo(MCB); // shuffle 175 } 176 if (!doneShuffling) 177 return true; 178 179 return false; 180 } 181 182 bool llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII, 183 MCSubtargetInfo const &STI, MCInst &MCB, 184 MCInst const &AddMI, int fixupCount) { 185 if (!HexagonMCInstrInfo::isBundle(MCB)) 186 return false; 187 188 // if fixups present, make sure we don't insert too many nops that would 189 // later prevent an extender from being inserted. 190 unsigned int bundleSize = HexagonMCInstrInfo::bundleSize(MCB); 191 if (bundleSize >= HEXAGON_PACKET_SIZE) 192 return false; 193 bool bhasDuplex = HexagonMCInstrInfo::hasDuplex(MCII, MCB); 194 if (fixupCount >= 2) { 195 if (bhasDuplex) { 196 if (bundleSize >= HEXAGON_PACKET_SIZE - 1) { 197 return false; 198 } 199 } else { 200 return false; 201 } 202 } else { 203 if (bundleSize == HEXAGON_PACKET_SIZE - 1 && fixupCount) 204 return false; 205 } 206 207 if (DisableShuffle) 208 return false; 209 210 // mgl: temporary code (shuffler doesn't take into account the fact that 211 // a duplex takes up two slots. for example, 3 nops can be put into a packet 212 // containing a duplex oversubscribing slots by 1). 213 unsigned maxBundleSize = (HexagonMCInstrInfo::hasImmExt(MCB)) 214 ? HEXAGON_PACKET_SIZE 215 : HEXAGON_PACKET_SIZE - 1; 216 if (bhasDuplex && bundleSize >= maxBundleSize) 217 return false; 218 219 HexagonMCShuffler MCS(Context, false, MCII, STI, MCB, AddMI, false); 220 return MCS.reshuffleTo(MCB); 221 } 222