diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp | 382 |
1 files changed, 291 insertions, 91 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp index 88f37d620dcf..853f76213d38 100644 --- a/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp +++ b/contrib/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp @@ -22,6 +22,7 @@ #include "MCTargetDesc/HexagonMCInstrInfo.h" #include "HexagonShuffler.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -37,16 +38,16 @@ class HexagonBid { unsigned Bid; public: - HexagonBid() : Bid(0){}; - HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; }; + HexagonBid() : Bid(0){} + HexagonBid(unsigned B) { Bid = B ? MAX / countPopulation(B) : 0; } // Check if the insn priority is overflowed. - bool isSold() const { return (Bid >= MAX); }; + bool isSold() const { return (Bid >= MAX); } HexagonBid &operator+=(const HexagonBid &B) { Bid += B.Bid; return *this; - }; + } }; // Slot shuffling allocation. @@ -56,7 +57,7 @@ class HexagonUnitAuction { unsigned isSold : HEXAGON_PACKET_SIZE; public: - HexagonUnitAuction() : isSold(0){}; + HexagonUnitAuction(unsigned cs = 0) : isSold(cs){}; // Allocate slots. bool bid(unsigned B) { @@ -70,29 +71,29 @@ public: isSold |= Scores[i].isSold() << i; } return true; - ; } else // Error if the desired slots are already full. return false; - }; + } }; } // end anonymous namespace unsigned HexagonResource::setWeight(unsigned s) { const unsigned SlotWeight = 8; const unsigned MaskWeight = SlotWeight - 1; - bool Key = (1 << s) & getUnits(); - - // TODO: Improve this API so that we can prevent misuse statically. - assert(SlotWeight * s < 32 && "Argument to setWeight too large."); + unsigned Units = getUnits(); + unsigned Key = ((1u << s) & Units) != 0; // Calculate relative weight of the insn for the given slot, weighing it the // heavier the more restrictive the insn is and the lowest the slots that the // insn may be executed in. - Weight = - (Key << (SlotWeight * s)) * ((MaskWeight - countPopulation(getUnits())) - << countTrailingZeros(getUnits())); - return (Weight); + if (Key == 0 || Units == 0 || (SlotWeight*s >= 32)) + return Weight = 0; + + unsigned Ctpop = countPopulation(Units); + unsigned Cttz = countTrailingZeros(Units); + Weight = (1u << (SlotWeight * s)) * ((MaskWeight - Ctpop) << Cttz); + return Weight; } void HexagonCVIResource::SetupTUL(TypeUnitsAndLanes *TUL, StringRef CPU) { @@ -104,7 +105,10 @@ 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_VINLANESAT] = UnitsAndLanes(CVI_SHIFT, 1); + (*TUL)[HexagonII::TypeCVI_VINLANESAT] = + (CPU == "hexagonv60" || CPU == "hexagonv61" || CPU == "hexagonv61v1") ? + UnitsAndLanes(CVI_SHIFT, 1) : + UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); (*TUL)[HexagonII::TypeCVI_VM_LD] = UnitsAndLanes(CVI_XLANE | CVI_SHIFT | CVI_MPY0 | CVI_MPY1, 1); (*TUL)[HexagonII::TypeCVI_VM_TMP_LD] = UnitsAndLanes(CVI_NONE, 0); @@ -141,6 +145,40 @@ HexagonCVIResource::HexagonCVIResource(TypeUnitsAndLanes *TUL, } } +struct CVIUnits { + unsigned Units; + unsigned Lanes; +}; +typedef SmallVector<struct CVIUnits, 8> HVXInstsT; + +static unsigned makeAllBits(unsigned startBit, unsigned Lanes) + +{ + for (unsigned i = 1 ; i < Lanes ; ++i) + startBit = (startBit << 1) | startBit; + return startBit; +} + +static bool checkHVXPipes(const HVXInstsT& hvxInsts, unsigned startIdx, unsigned usedUnits) + +{ + if (startIdx < hvxInsts.size()) { + if (!hvxInsts[startIdx].Units) + return checkHVXPipes(hvxInsts, startIdx + 1, usedUnits); + for (unsigned b = 0x1 ; b <= 0x8 ; b <<= 1) { + if ((hvxInsts[startIdx].Units & b) == 0) + continue; + unsigned allBits = makeAllBits(b, hvxInsts[startIdx].Lanes); + if ((allBits & usedUnits) == 0) { + if (checkHVXPipes(hvxInsts, startIdx + 1, usedUnits | allBits)) + return true; + } + } + return false; + } + return true; +} + HexagonShuffler::HexagonShuffler(MCInstrInfo const &MCII, MCSubtargetInfo const &STI) : MCII(MCII), STI(STI) { @@ -154,21 +192,82 @@ void HexagonShuffler::reset() { Error = SHUFFLE_SUCCESS; } -void HexagonShuffler::append(MCInst const *ID, MCInst const *Extender, - unsigned S, bool X) { - HexagonInstr PI(&TUL, MCII, ID, Extender, S, X); +void HexagonShuffler::append(MCInst const &ID, MCInst const *Extender, + unsigned S) { + HexagonInstr PI(&TUL, MCII, &ID, Extender, S); Packet.push_back(PI); } +static struct { + unsigned first; + unsigned second; +} jumpSlots[] = { {8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1} }; +#define MAX_JUMP_SLOTS (sizeof(jumpSlots)/sizeof(jumpSlots[0])) + +namespace { +bool isDuplexAGroup(unsigned Opcode) { + switch (Opcode) { + case Hexagon::SA1_addi: + case Hexagon::SA1_addrx: + case Hexagon::SA1_addsp: + case Hexagon::SA1_and1: + case Hexagon::SA1_clrf: + case Hexagon::SA1_clrfnew: + case Hexagon::SA1_clrt: + case Hexagon::SA1_clrtnew: + case Hexagon::SA1_cmpeqi: + case Hexagon::SA1_combine0i: + case Hexagon::SA1_combine1i: + case Hexagon::SA1_combine2i: + case Hexagon::SA1_combine3i: + case Hexagon::SA1_combinerz: + case Hexagon::SA1_combinezr: + case Hexagon::SA1_dec: + case Hexagon::SA1_inc: + case Hexagon::SA1_seti: + case Hexagon::SA1_setin1: + case Hexagon::SA1_sxtb: + case Hexagon::SA1_sxth: + case Hexagon::SA1_tfr: + case Hexagon::SA1_zxtb: + case Hexagon::SA1_zxth: + return true; + break; + default: + return false; + } +} + +unsigned countNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) { + unsigned Result = 0; + unsigned Type = HexagonMCInstrInfo::getType(MCII, ID); + if (Type == HexagonII::TypeDUPLEX) { + unsigned subInst0Opcode = ID.getOperand(0).getInst()->getOpcode(); + unsigned subInst1Opcode = ID.getOperand(1).getInst()->getOpcode(); + Result += !isDuplexAGroup(subInst0Opcode); + Result += !isDuplexAGroup(subInst1Opcode); + } else + Result += Type != HexagonII::TypeALU32_2op && + Type != HexagonII::TypeALU32_3op && + Type != HexagonII::TypeALU32_ADDI && + Type != HexagonII::TypeS_2op && + Type != HexagonII::TypeS_3op && + Type != HexagonII::TypeALU64 && + (Type != HexagonII::TypeM || + HexagonMCInstrInfo::isFloat(MCII, ID)); + return Result; +} +} + /// 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, - slotThree = 0x8, slotFirstJump = 0x8, slotLastJump = 0x4, + slotThree = 0x8, //slotFirstJump = 0x8, slotFirstLoadStore = 0x2, slotLastLoadStore = 0x1; // Highest slots for branches and stores used to keep their original order. - unsigned slotJump = slotFirstJump; + //unsigned slotJump = slotFirstJump; unsigned slotLoadStore = slotFirstLoadStore; // Number of branches, solo branches, indirect branches. unsigned jumps = 0, jump1 = 0; @@ -188,36 +287,41 @@ bool HexagonShuffler::check() { unsigned onlyNo1 = 0; unsigned xtypeFloat = 0; unsigned pSlot3Cnt = 0; + unsigned memops = 0; + unsigned deallocs = 0; iterator slot3ISJ = end(); + std::vector<iterator> foundBranches; + unsigned reservedSlots = 0; // Collect information from the insns in the packet. for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { - MCInst const *ID = ISJ->getDesc(); - - if (HexagonMCInstrInfo::isSolo(MCII, *ID)) - solo += !ISJ->isSoloException(); - else if (HexagonMCInstrInfo::isSoloAX(MCII, *ID)) - onlyAX += !ISJ->isSoloException(); - else if (HexagonMCInstrInfo::isSoloAin1(MCII, *ID)) - onlyAin1 += !ISJ->isSoloException(); - if (HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeALU32 && - HexagonMCInstrInfo::getType(MCII, *ID) != HexagonII::TypeXTYPE) - ++neitherAnorX; - if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) { + MCInst const &ID = ISJ->getDesc(); + + if (HexagonMCInstrInfo::isSolo(MCII, ID)) + solo++; + else if (HexagonMCInstrInfo::isSoloAX(MCII, ID)) + onlyAX++; + else if (HexagonMCInstrInfo::isSoloAin1(MCII, ID)) + onlyAin1++; + neitherAnorX += countNeitherAnorX(MCII, ID); + if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) { ++pSlot3Cnt; slot3ISJ = ISJ; } - if (HexagonMCInstrInfo::isCofMax1(MCII, *ID)) + reservedSlots |= HexagonMCInstrInfo::getOtherReservedSlots(MCII, STI, ID); + if (HexagonMCInstrInfo::isCofMax1(MCII, ID)) ++jump1; - switch (HexagonMCInstrInfo::getType(MCII, *ID)) { - case HexagonII::TypeXTYPE: - if (HexagonMCInstrInfo::isFloat(MCII, *ID)) + switch (HexagonMCInstrInfo::getType(MCII, ID)) { + case HexagonII::TypeS_2op: + case HexagonII::TypeS_3op: + case HexagonII::TypeALU64: + if (HexagonMCInstrInfo::isFloat(MCII, ID)) ++xtypeFloat; break; - case HexagonII::TypeJR: case HexagonII::TypeJ: ++jumps; + foundBranches.push_back(ISJ); break; case HexagonII::TypeCVI_VM_VP_LDU: ++onlyNo1; @@ -228,10 +332,14 @@ bool HexagonShuffler::check() { case HexagonII::TypeLD: ++loads; ++memory; - if (ISJ->Core.getUnits() == slotSingleLoad) + if (ISJ->Core.getUnits() == slotSingleLoad || + HexagonMCInstrInfo::getType(MCII, ID) == + HexagonII::TypeCVI_VM_VP_LDU) ++load0; - if (HexagonMCInstrInfo::getDesc(MCII, *ID).isReturn()) - ++jumps, ++jump1; // DEALLOC_RETURN is of type LD. + if (HexagonMCInstrInfo::getDesc(MCII, ID).isReturn()) { + ++deallocs, ++jumps, ++jump1; // DEALLOC_RETURN is of type LD. + foundBranches.push_back(ISJ); + } break; case HexagonII::TypeCVI_VM_STU: ++onlyNo1; @@ -241,27 +349,66 @@ bool HexagonShuffler::check() { case HexagonII::TypeST: ++stores; ++memory; - if (ISJ->Core.getUnits() == slotSingleStore) + if (ISJ->Core.getUnits() == slotSingleStore || + HexagonMCInstrInfo::getType(MCII, ID) == HexagonII::TypeCVI_VM_STU) ++store0; break; case HexagonII::TypeV4LDST: ++loads; ++stores; ++store1; + ++memops; ++memory; break; - case HexagonII::TypeNV: + case HexagonII::TypeNCJ: ++memory; // NV insns are memory-like. - if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch()) + if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) { ++jumps, ++jump1; + foundBranches.push_back(ISJ); + } + break; + case HexagonII::TypeV2LDST: + if(HexagonMCInstrInfo::getDesc(MCII, ID).mayLoad()) { + ++loads; + ++memory; + if (ISJ->Core.getUnits() == slotSingleLoad || + HexagonMCInstrInfo::getType(MCII,ID) == + HexagonII::TypeCVI_VM_VP_LDU) + ++load0; + } + else { + assert(HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()); + ++memory; + ++stores; + } break; case HexagonII::TypeCR: // Legacy conditional branch predicated on a register. - case HexagonII::TypeSYSTEM: - if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) - ++loads; + case HexagonII::TypeCJ: + if (HexagonMCInstrInfo::getDesc(MCII, ID).isBranch()) { + ++jumps; + 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; + foundBranches.push_back(ISJ); + } + if (HexagonMCInstrInfo::getDesc(MCII, Inst1).isBranch()) { + ++jumps; + foundBranches.push_back(ISJ); + } break; } + } } // Check if the packet is legal. @@ -277,12 +424,20 @@ bool HexagonShuffler::check() { Error = SHUFFLE_ERROR_BRANCHES; return false; } + if (memops && stores > 1) { + Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT; + return false; + } + if (deallocs && stores) { + Error = SHUFFLE_ERROR_STORE_LOAD_CONFLICT; + return false; + } // Modify packet accordingly. // TODO: need to reserve slots #0 and #1 for duplex insns. bool bOnlySlot3 = false; for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { - MCInst const *ID = ISJ->getDesc(); + MCInst const &ID = ISJ->getDesc(); if (!ISJ->Core.getUnits()) { // Error if insn may not be executed in any slot. @@ -291,40 +446,26 @@ bool HexagonShuffler::check() { } // Exclude from slot #1 any insn but A2_nop. - if (HexagonMCInstrInfo::getDesc(MCII, *ID).getOpcode() != Hexagon::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) + 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); - // Branches must keep the original order. - if (HexagonMCInstrInfo::getDesc(MCII, *ID).isBranch() || - HexagonMCInstrInfo::getDesc(MCII, *ID).isCall()) - if (jumps > 1) { - if (slotJump < slotLastJump) { - // Error if indirect branch with another branch or - // no more slots available for branches. - Error = SHUFFLE_ERROR_BRANCHES; - return false; - } - // Pin the branch to the highest slot available to it. - ISJ->Core.setUnits(ISJ->Core.getUnits() & slotJump); - // Update next highest slot available to branches. - slotJump >>= 1; - } - // A single load must use slot #0. - if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayLoad()) { - if (loads == 1 && loads == memory) + 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); } // A single store must use slot #0. - if (HexagonMCInstrInfo::getDesc(MCII, *ID).mayStore()) { + if (HexagonMCInstrInfo::getDesc(MCII, ID).mayStore()) { if (!store0) { if (stores == 1) ISJ->Core.setUnits(ISJ->Core.getUnits() & slotSingleStore); @@ -347,7 +488,7 @@ bool HexagonShuffler::check() { } } - // flag if an instruction can only be executed in slot 3 + // flag if an instruction requires to be in slot 3 if (ISJ->Core.getUnits() == slotThree) bOnlySlot3 = true; @@ -358,14 +499,61 @@ bool HexagonShuffler::check() { } } + // preserve branch order bool validateSlots = true; - if (bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) { + if (jumps > 1) { + if (foundBranches.size() > 2) { + Error = SHUFFLE_ERROR_BRANCHES; + return false; + } + + // try all possible choices + for (unsigned int i = 0 ; i < MAX_JUMP_SLOTS ; ++i) { + // validate first jump with this slot rule + if (!(jumpSlots[i].first & foundBranches[0]->Core.getUnits())) + continue; + + // validate second jump with this slot rule + if (!(jumpSlots[i].second & foundBranches[1]->Core.getUnits())) + continue; + + // both valid for this configuration, set new slot rules + PacketSave = Packet; + foundBranches[0]->Core.setUnits(jumpSlots[i].first); + foundBranches[1]->Core.setUnits(jumpSlots[i].second); + + HexagonUnitAuction AuctionCore(reservedSlots); + std::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) + if (!AuctionCore.bid(I->Core.getUnits())) + bFail = true; + + // if yes, great, if not then restore original slot mask + if (!bFail) { + validateSlots = false; // all good, no need to re-do auction + break; + } + else + // restore original values + Packet = PacketSave; + } + if (validateSlots == true) { + Error = SHUFFLE_ERROR_NOSLOTS; + return false; + } + } + + if (jumps <= 1 && bOnlySlot3 == false && pSlot3Cnt == 1 && slot3ISJ != end()) { + validateSlots = true; // save off slot mask of instruction marked with A_PREFER_SLOT3 // and then pin it to slot #3 unsigned saveUnits = slot3ISJ->Core.getUnits(); slot3ISJ->Core.setUnits(saveUnits & slotThree); - HexagonUnitAuction AuctionCore; + HexagonUnitAuction AuctionCore(reservedSlots); std::sort(begin(), end(), HexagonInstr::lessCore); // see if things ok with that instruction being pinned to slot #3 @@ -379,16 +567,16 @@ bool HexagonShuffler::check() { validateSlots = false; // all good, no need to re-do auction else for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { - MCInst const *ID = ISJ->getDesc(); - if (HexagonMCInstrInfo::prefersSlot3(MCII, *ID)) + MCInst const &ID = ISJ->getDesc(); + if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) ISJ->Core.setUnits(saveUnits); } } - // Check if any slot, core, is over-subscribed. + // Check if any slot, core or CVI, is over-subscribed. // Verify the core slot subscriptions. if (validateSlots) { - HexagonUnitAuction AuctionCore; + HexagonUnitAuction AuctionCore(reservedSlots); std::sort(begin(), end(), HexagonInstr::lessCore); @@ -399,17 +587,27 @@ bool HexagonShuffler::check() { } } // Verify the CVI slot subscriptions. - { - HexagonUnitAuction AuctionCVI; - - std::sort(begin(), end(), HexagonInstr::lessCVI); - - for (iterator I = begin(); I != end(); ++I) - for (unsigned i = 0; i < I->CVI.getLanes(); ++i) // TODO: I->CVI.isValid? - if (!AuctionCVI.bid(I->CVI.getUnits() << i)) { - Error = SHUFFLE_ERROR_SLOTS; - return false; - } + std::sort(begin(), end(), HexagonInstr::lessCVI); + // create vector of hvx instructions to check + HVXInstsT hvxInsts; + hvxInsts.clear(); + for (iterator I = begin(); I != end(); ++I) { + struct CVIUnits inst; + inst.Units = I->CVI.getUnits(); + inst.Lanes = I->CVI.getLanes(); + if (inst.Units == 0) + continue; // not an hvx inst or an hvx inst that doesn't uses any pipes + hvxInsts.push_back(inst); + } + // if there are any hvx instructions in this packet, check pipe usage + if (hvxInsts.size() > 0) { + unsigned startIdx, usedUnits; + startIdx = usedUnits = 0x0; + if (checkHVXPipes(hvxInsts, startIdx, usedUnits) == false) { + // too many pipes used to be valid + Error = SHUFFLE_ERROR_SLOTS; + return false; + } } Error = SHUFFLE_SUCCESS; @@ -452,10 +650,12 @@ bool HexagonShuffler::shuffle() { } for (iterator ISJ = begin(); ISJ != end(); ++ISJ) - DEBUG(dbgs().write_hex(ISJ->Core.getUnits()); - dbgs() << ':' - << HexagonMCInstrInfo::getDesc(MCII, *ISJ->getDesc()) - .getOpcode(); + DEBUG(dbgs().write_hex(ISJ->Core.getUnits()); if (ISJ->CVI.isValid()) { + dbgs() << '/'; + dbgs().write_hex(ISJ->CVI.getUnits()) << '|'; + dbgs() << ISJ->CVI.getLanes(); + } dbgs() << ':' + << HexagonMCInstrInfo::getDesc(MCII, ISJ->getDesc()).getOpcode(); dbgs() << '\n'); DEBUG(dbgs() << '\n'); |