diff options
Diffstat (limited to 'lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp')
| -rw-r--r-- | lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp | 275 |
1 files changed, 167 insertions, 108 deletions
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp index 1604e7c8dc54..7709a0f61624 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp @@ -1,4 +1,4 @@ -//===----- HexagonShuffler.cpp - Instruction bundle shuffling -------------===// +//===- HexagonShuffler.cpp - Instruction bundle shuffling -----------------===// // // The LLVM Compiler Infrastructure // @@ -14,32 +14,40 @@ #define DEBUG_TYPE "hexagon-shuffle" -#include "HexagonShuffler.h" +#include "MCTargetDesc/HexagonShuffler.h" #include "Hexagon.h" #include "MCTargetDesc/HexagonBaseInfo.h" #include "MCTargetDesc/HexagonMCInstrInfo.h" #include "MCTargetDesc/HexagonMCTargetDesc.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Twine.h" #include "llvm/MC/MCContext.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <cassert> #include <utility> +#include <vector> using namespace llvm; namespace { + // Insn shuffling priority. class HexagonBid { // The priority is directly proportional to how restricted the insn is based // on its flexibility to run on the available slots. So, the fewer slots it // may run on, the higher its priority. enum { MAX = 360360 }; // LCD of 1/2, 1/3, 1/4,... 1/15. - unsigned Bid; + unsigned Bid = 0; public: - HexagonBid() : Bid(0) {} + HexagonBid() = default; HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; } // Check if the insn priority is overflowed. @@ -58,7 +66,7 @@ class HexagonUnitAuction { unsigned isSold : HEXAGON_PACKET_SIZE; public: - HexagonUnitAuction(unsigned cs = 0) : isSold(cs){}; + HexagonUnitAuction(unsigned cs = 0) : isSold(cs) {} // Allocate slots. bool bid(unsigned B) { @@ -77,6 +85,7 @@ public: return false; } }; + } // end anonymous namespace unsigned HexagonResource::setWeight(unsigned s) { @@ -107,6 +116,7 @@ void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) { (*TUL)[HexagonII::TypeCVI_VP] = UnitsAndLanes(CVI_XLANE, 1); (*TUL)[HexagonII::TypeCVI_VP_VS] = UnitsAndLanes(CVI_XLANE, 2); (*TUL)[HexagonII::TypeCVI_VS] = UnitsAndLanes(CVI_SHIFT, 1); + (*TUL)[HexagonII::TypeCVI_VS_VX] = UnitsAndLanes(CVI_XLANE | CVI_SHIFT, 1); (*TUL)[HexagonII::TypeCVI_VINLANESAT] = (CPU == "hexagonv60") ? UnitsAndLanes(CVI_SHIFT, 1) @@ -120,12 +130,20 @@ void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) { (*TUL)[HexagonII::TypeCVI_VM_NEW_ST] = UnitsAndLanes(CVI_NONE, 0); (*TUL)[HexagonII::TypeCVI_VM_STU] = UnitsAndLanes(CVI_XLANE, 1); (*TUL)[HexagonII::TypeCVI_HIST] = UnitsAndLanes(CVI_XLANE, 4); + (*TUL)[HexagonII::TypeCVI_GATHER] = + UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); + (*TUL)[HexagonII::TypeCVI_SCATTER] = + UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); + (*TUL)[HexagonII::TypeCVI_SCATTER_DV] = + UnitsAndLanes(CVI_XLANE | CVI_MPY0, 2); + (*TUL)[HexagonII::TypeCVI_SCATTER_NEW_ST] = + UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); } HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL, MCInstrInfo const &MCII, unsigned s, MCInst const *id) - : HexagonResource(s), TUL(TUL) { + : HexagonResource(s) { unsigned T = HexagonMCInstrInfo::getType(MCII, *id); if (TUL->count(T)) { @@ -149,10 +167,9 @@ struct CVIUnits { unsigned Units; unsigned Lanes; }; -typedef SmallVector<struct CVIUnits, 8> HVXInstsT; +using HVXInstsT = SmallVector<struct CVIUnits, 8>; static unsigned makeAllBits(unsigned startBit, unsigned Lanes) - { for (unsigned i = 1; i < Lanes; ++i) startBit = (startBit << 1) | startBit; @@ -160,9 +177,7 @@ static unsigned makeAllBits(unsigned startBit, unsigned Lanes) } static bool checkHVXPipes(const HVXInstsT &hvxInsts, unsigned startIdx, - unsigned usedUnits) - -{ + unsigned usedUnits) { if (startIdx < hvxInsts.size()) { if (!hvxInsts[startIdx].Units) return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits); @@ -206,30 +221,89 @@ static struct { } jumpSlots[] = {{8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}}; #define MAX_JUMP_SLOTS (sizeof(jumpSlots) / sizeof(jumpSlots[0])) +void HexagonShuffler::restrictSlot1AOK() { + bool HasRestrictSlot1AOK = false; + SMLoc RestrictLoc; + for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { + MCInst const &Inst = ISJ->getDesc(); + if (HexagonMCInstrInfo::isRestrictSlot1AOK(MCII, Inst)) { + HasRestrictSlot1AOK = true; + RestrictLoc = Inst.getLoc(); + } + } + if (HasRestrictSlot1AOK) + for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { + MCInst const &Inst = ISJ->getDesc(); + unsigned Type = HexagonMCInstrInfo::getType(MCII, Inst); + if (Type != HexagonII::TypeALU32_2op && + Type != HexagonII::TypeALU32_3op && + Type != HexagonII::TypeALU32_ADDI) { + unsigned Units = ISJ->Core.getUnits(); + if (Units & 2U) { + AppliedRestrictions.push_back(std::make_pair( + Inst.getLoc(), + "Instruction was restricted from being in slot 1")); + AppliedRestrictions.push_back( + std::make_pair(RestrictLoc, "Instruction can only be combine " + "with an ALU instruction in slot 1")); + ISJ->Core.setUnits(Units & ~2U); + } + } + } +} + +void HexagonShuffler::restrictNoSlot1Store() { + bool HasRestrictNoSlot1Store = false; + SMLoc RestrictLoc; + for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { + MCInst const &Inst = ISJ->getDesc(); + if (HexagonMCInstrInfo::isRestrictNoSlot1Store(MCII, Inst)) { + HasRestrictNoSlot1Store = true; + RestrictLoc = Inst.getLoc(); + } + } + if (HasRestrictNoSlot1Store) { + bool AppliedRestriction = false; + for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { + MCInst const &Inst = ISJ->getDesc(); + if (HexagonMCInstrInfo::getDesc(MCII, Inst).mayStore()) { + unsigned Units = ISJ->Core.getUnits(); + if (Units & 2U) { + AppliedRestriction = true; + AppliedRestrictions.push_back(std::make_pair( + Inst.getLoc(), + "Instruction was restricted from being in slot 1")); + ISJ->Core.setUnits(Units & ~2U); + } + } + } + if (AppliedRestriction) + AppliedRestrictions.push_back(std::make_pair( + RestrictLoc, "Instruction does not allow a store in slot 1")); + } +} + +void HexagonShuffler::applySlotRestrictions() { + restrictSlot1AOK(); + restrictNoSlot1Store(); +} + /// Check that the packet is legal and enforce relative insn order. bool HexagonShuffler::check() { // Descriptive slot masks. - const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotOne = 0x2, + const unsigned slotSingleLoad = 0x1, slotSingleStore = 0x1, slotThree = 0x8, // slotFirstJump = 0x8, slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1; // Highest slots for branches and stores used to keep their original order. // unsigned slotJump = slotFirstJump; unsigned slotLoadStore = slotFirstLoadStore; - // Number of branches, solo branches, indirect branches. - unsigned jumps = 0, jump1 = 0; // Number of memory operations, loads, solo loads, stores, solo stores, single // stores. unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0; // Number of duplex insns unsigned duplex = 0; - // Number of insns restricting other insns in slot #1 to A type. - unsigned onlyAin1 = 0; - // Number of insns restricting any insn in slot #1, except A2_nop. - unsigned onlyNo1 = 0; unsigned pSlot3Cnt = 0; - unsigned nvstores = 0; unsigned memops = 0; - unsigned deallocs = 0; iterator slot3ISJ = end(); std::vector<iterator> foundBranches; unsigned reservedSlots = 0; @@ -238,15 +312,11 @@ bool HexagonShuffler::check() { for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { MCInst const &ID = ISJ->getDesc(); - if (HexagonMCInstrInfo::isSoloAin1(MCII, ID)) - ++onlyAin1; if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) { ++pSlot3Cnt; slot3ISJ = ISJ; } reservedSlots |= HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID); - if (HexagonMCInstrInfo::isCofMax1(MCII, ID)) - ++jump1; switch (HexagonMCInstrInfo::getType(MCII, ID)) { case HexagonII::TypeS_2op: @@ -254,30 +324,30 @@ bool HexagonShuffler::check() { case HexagonII::TypeALU64: break; case HexagonII::TypeJ: - ++jumps; foundBranches.push_back(ISJ); break; case HexagonII::TypeCVI_VM_VP_LDU: - ++onlyNo1; - LLVM_FALLTHROUGH; case HexagonII::TypeCVI_VM_LD: case HexagonII::TypeCVI_VM_TMP_LD: + case HexagonII::TypeCVI_GATHER: + case HexagonII::TypeCVI_GATHER_RST: case HexagonII::TypeLD: ++loads; ++memory; if (ISJ->Core.getUnits() == slotSingleLoad || HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_VP_LDU) ++load0; - if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) { - ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD. + if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) foundBranches.push_back(ISJ); - } break; case HexagonII::TypeCVI_VM_STU: - ++onlyNo1; - LLVM_FALLTHROUGH; case HexagonII::TypeCVI_VM_ST: case HexagonII::TypeCVI_VM_NEW_ST: + case HexagonII::TypeCVI_SCATTER: + case HexagonII::TypeCVI_SCATTER_DV: + case HexagonII::TypeCVI_SCATTER_RST: + case HexagonII::TypeCVI_SCATTER_NEW_RST: + case HexagonII::TypeCVI_SCATTER_NEW_ST: case HexagonII::TypeST: ++stores; ++memory; @@ -294,7 +364,6 @@ bool HexagonShuffler::check() { break; case HexagonII::TypeNCJ: ++memory; // NV insns are memory-like. - ++jumps, ++jump1; foundBranches.push_back(ISJ); break; case HexagonII::TypeV2LDST: @@ -309,68 +378,38 @@ bool HexagonShuffler::check() { assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()); ++memory; ++stores; - if (HexagonMCInstrInfo::isNewValue(MCII, ID)) - ++nvstores; } break; case HexagonII::TypeCR: // Legacy conditional branch predicated on a register. case HexagonII::TypeCJ: - if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) { - ++jumps; + if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) foundBranches.push_back(ISJ); - } break; case HexagonII::TypeDUPLEX: { ++duplex; MCInst const &Inst0 = *ID.getOperand(0).getInst(); MCInst const &Inst1 = *ID.getOperand(1).getInst(); - if (HexagonMCInstrInfo::isCofMax1(MCII, Inst0)) - ++jump1; - if (HexagonMCInstrInfo::isCofMax1(MCII, Inst1)) - ++jump1; - if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch()) { - ++jumps; + if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isBranch()) foundBranches.push_back(ISJ); - } - if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) { - ++jumps; + if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) foundBranches.push_back(ISJ); - } - if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn()) { - ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD. + if (HexagonMCInstrInfo::getDesc(MCII, Inst0).isReturn()) foundBranches.push_back(ISJ); - } - if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn()) { - ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD. + if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isReturn()) foundBranches.push_back(ISJ); - } break; } } } + applySlotRestrictions(); // Check if the packet is legal. - if ((load0 > 1 || store0 > 1) || - (duplex > 1 || (duplex && memory))) { + if ((load0 > 1 || store0 > 1) || (duplex > 1 || (duplex && memory))) { reportError(llvm::Twine("invalid instruction packet")); return false; } - if (jump1 && jumps > 1) { - // Error if single branch with another branch. - reportError(llvm::Twine("too many branches in packet")); - return false; - } - if ((nvstores || memops) && stores > 1) { - reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store")); - return false; - } - if (deallocs && stores) { - reportError(llvm::Twine("slot 0 instruction does not allow slot 1 store")); - return false; - } - // Modify packet accordingly. // TODO: need to reserve slots #0 and #1 for duplex insns. bool bOnlySlot3 = false; @@ -382,35 +421,49 @@ bool HexagonShuffler::check() { return false; } - // Exclude from slot #1 any insn but A2_nop. - if (HexagonMCInstrInfo::getDesc(MCII, ID).getOpcode() != Hexagon::A2_nop) - if (onlyNo1) - ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne); - - // Exclude from slot #1 any insn but A-type. - if (HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_2op && - HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_3op && - HexagonMCInstrInfo::getType(MCII, ID) != HexagonII::TypeALU32_ADDI) - if (onlyAin1) - ISJ->Core.setUnits(ISJ->Core.getUnits() & ~slotOne); - // A single load must use slot #0. if (HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) { if (loads == 1 && loads == memory && memops == 0) // Pin the load to slot #0. - ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad); + switch (ID.getOpcode()) { + case Hexagon::V6_vgathermw: + case Hexagon::V6_vgathermh: + case Hexagon::V6_vgathermhw: + case Hexagon::V6_vgathermwq: + case Hexagon::V6_vgathermhq: + case Hexagon::V6_vgathermhwq: + // Slot1 only loads + break; + default: + ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleLoad); + break; + } + else if (loads >= 1 && isMemReorderDisabled()) { // }:mem_noshuf + // Loads must keep the original order ONLY if + // isMemReorderDisabled() == true + if (slotLoadStore < slotLastLoadStore) { + // Error if no more slots available for loads. + reportError( + llvm::Twine("invalid instruction packet: too many loads")); + return false; + } + // Pin the load to the highest slot available to it. + ISJ->Core.setUnits(ISJ->Core.getUnits() & slotLoadStore); + // Update the next highest slot available to loads. + slotLoadStore >>= 1; + } } // A single store must use slot #0. if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) { if (!store0) { - if (stores == 1) + if (stores == 1 && (loads == 0 || !isMemReorderDisabled())) + // Pin the store to slot #0 only if isMemReorderDisabled() == false ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore); - else if (stores > 1) { + else if (stores >= 1) { if (slotLoadStore < slotLastLoadStore) { // Error if no more slots available for stores. - reportError( - llvm::Twine("invalid instruction packet: too many stores")); + reportError(Twine("invalid instruction packet: too many stores")); return false; } // Pin the store to the highest slot available to it. @@ -421,7 +474,7 @@ bool HexagonShuffler::check() { } if (store1 && stores > 1) { // Error if a single store with another store. - reportError(llvm::Twine("invalid instruction packet: too many stores")); + reportError(Twine("invalid instruction packet: too many stores")); return false; } } @@ -432,16 +485,16 @@ bool HexagonShuffler::check() { if (!ISJ->Core.getUnits()) { // Error if insn may not be executed in any slot. - reportError(llvm::Twine("invalid instruction packet: out of slots")); + reportError(Twine("invalid instruction packet: out of slots")); return false; } } // preserve branch order bool validateSlots = true; - if (jumps > 1) { + if (foundBranches.size() > 1) { if (foundBranches.size() > 2) { - reportError(llvm::Twine("too many branches in packet")); + reportError(Twine("too many branches in packet")); return false; } @@ -461,11 +514,11 @@ bool HexagonShuffler::check() { foundBranches[1]->Core.setUnits(jumpSlots[i].second); HexagonUnitAuction AuctionCore(reservedSlots); - std::sort(begin(), end(), HexagonInstr::lessCore); + std::stable_sort(begin(), end(), HexagonInstr::lessCore); // see if things ok with that instruction being pinned to slot "slotJump" bool bFail = false; - for (iterator I = begin(); I != end() && bFail != true; ++I) + for (iterator I = begin(); I != end() && !bFail; ++I) if (!AuctionCore.bid(I->Core.getUnits())) bFail = true; @@ -477,13 +530,13 @@ bool HexagonShuffler::check() { // restore original values Packet = PacketSave; } - if (validateSlots == true) { - reportError(llvm::Twine("invalid instruction packet: out of slots")); + if (validateSlots) { + reportError(Twine("invalid instruction packet: out of slots")); return false; } } - if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 && + if (foundBranches.size() <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) { validateSlots = true; // save off slot mask of instruction marked with A_PREFER_SLOT3 @@ -492,11 +545,11 @@ bool HexagonShuffler::check() { slot3ISJ->Core.setUnits(saveUnits & slotThree); HexagonUnitAuction AuctionCore(reservedSlots); - std::sort(begin(), end(), HexagonInstr::lessCore); + std::stable_sort(begin(), end(), HexagonInstr::lessCore); // see if things ok with that instruction being pinned to slot #3 bool bFail = false; - for (iterator I = begin(); I != end() && bFail != true; ++I) + for (iterator I = begin(); I != end() && !bFail; ++I) if (!AuctionCore.bid(I->Core.getUnits())) bFail = true; @@ -516,16 +569,16 @@ bool HexagonShuffler::check() { if (validateSlots) { HexagonUnitAuction AuctionCore(reservedSlots); - std::sort(begin(), end(), HexagonInstr::lessCore); + std::stable_sort(begin(), end(), HexagonInstr::lessCore); for (iterator I = begin(); I != end(); ++I) if (!AuctionCore.bid(I->Core.getUnits())) { - reportError(llvm::Twine("invalid instruction packet: slot error")); + reportError(Twine("invalid instruction packet: slot error")); return false; } } // Verify the CVI slot subscriptions. - std::sort(begin(), end(), HexagonInstr::lessCVI); + std::stable_sort(begin(), end(), HexagonInstr::lessCVI); // create vector of hvx instructions to check HVXInstsT hvxInsts; hvxInsts.clear(); @@ -541,9 +594,9 @@ bool HexagonShuffler::check() { if (hvxInsts.size() > 0) { unsigned startIdx, usedUnits; startIdx = usedUnits = 0x0; - if (checkHVXPipes(hvxInsts, startIdx, usedUnits) == false) { + if (!checkHVXPipes(hvxInsts, startIdx, usedUnits)) { // too many pipes used to be valid - reportError(llvm::Twine("invalid instruction packet: slot error")); + reportError(Twine("invalid instruction packet: slot error")); return false; } } @@ -555,7 +608,7 @@ bool HexagonShuffler::shuffle() { if (size() > HEXAGON_PACKET_SIZE) { // Ignore a packet with with more than what a packet can hold // or with compound or duplex insns for now. - reportError(llvm::Twine("invalid instruction packet")); + reportError(Twine("invalid instruction packet")); return false; } @@ -581,7 +634,7 @@ bool HexagonShuffler::shuffle() { if (slotWeight) // Sort the packet, favoring source order, // beginning after the previous slot. - std::sort(ISJ, Packet.end()); + std::stable_sort(ISJ, Packet.end()); else // Skip unused slot. ++emptySlots; @@ -600,7 +653,13 @@ bool HexagonShuffler::shuffle() { return Ok; } -void HexagonShuffler::reportError(llvm::Twine const &Msg) { - if (ReportErrors) +void HexagonShuffler::reportError(Twine const &Msg) { + if (ReportErrors) { + for (auto const &I : AppliedRestrictions) { + auto SM = Context.getSourceManager(); + if (SM) + SM->PrintMessage(I.first, SourceMgr::DK_Note, I.second); + } Context.reportError(Loc, Msg); + } } |
