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