diff options
Diffstat (limited to 'llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp')
-rw-r--r-- | llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp | 167 |
1 files changed, 151 insertions, 16 deletions
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp index 0750bfe74f76..f9f342a07f6d 100644 --- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp +++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp @@ -17,6 +17,7 @@ #include "MCTargetDesc/HexagonMCShuffler.h" #include "MCTargetDesc/HexagonMCTargetDesc.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" @@ -119,10 +120,10 @@ size_t HexagonMCInstrInfo::bundleSize(MCInst const &MCI) { return (1); } -bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII, - MCSubtargetInfo const &STI, - MCContext &Context, MCInst &MCB, - HexagonMCChecker *Check) { +namespace { +bool canonicalizePacketImpl(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, + MCContext &Context, MCInst &MCB, + HexagonMCChecker *Check) { // Check the bundle for errors. bool CheckOk = Check ? Check->check(false) : true; if (!CheckOk) @@ -132,9 +133,9 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII, if (!HexagonDisableCompound) HexagonMCInstrInfo::tryCompound(MCII, STI, Context, MCB); HexagonMCShuffle(Context, false, MCII, STI, MCB); + // Examine the packet and convert pairs of instructions to duplex // instructions when possible. - MCInst InstBundlePreDuplex = MCInst(MCB); if (STI.getFeatureBits() [Hexagon::FeatureDuplex]) { SmallVector<DuplexCandidate, 8> possibleDuplexes; possibleDuplexes = @@ -146,8 +147,11 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII, HexagonMCInstrInfo::padEndloop(MCB, Context); // If compounding and duplexing didn't reduce the size below // 4 or less we have a packet that is too big. - if (HexagonMCInstrInfo::bundleSize(MCB) > HEXAGON_PACKET_SIZE) + if (HexagonMCInstrInfo::bundleSize(MCB) > HEXAGON_PACKET_SIZE) { + if (Check) + Check->reportError("invalid instruction packet: out of slots"); return false; + } // Check the bundle for errors. CheckOk = Check ? Check->check(true) : true; if (!CheckOk) @@ -155,6 +159,27 @@ bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII, HexagonMCShuffle(Context, true, MCII, STI, MCB); return true; } +} // namespace + +bool HexagonMCInstrInfo::canonicalizePacket(MCInstrInfo const &MCII, + MCSubtargetInfo const &STI, + MCContext &Context, MCInst &MCB, + HexagonMCChecker *Check, + bool AttemptCompatibility) { + auto ArchSTI = Hexagon_MC::getArchSubtarget(&STI); + if (!AttemptCompatibility || ArchSTI == nullptr) + return canonicalizePacketImpl(MCII, STI, Context, MCB, Check); + + const MCRegisterInfo *RI = Context.getRegisterInfo(); + HexagonMCChecker DefaultCheck(Context, MCII, STI, MCB, *RI, false); + HexagonMCChecker *BaseCheck = (Check == nullptr) ? &DefaultCheck : Check; + HexagonMCChecker PerfCheck(*BaseCheck, STI, false); + if (canonicalizePacketImpl(MCII, STI, Context, MCB, &PerfCheck)) + return true; + + HexagonMCChecker ArchCheck(*BaseCheck, *ArchSTI, true); + return canonicalizePacketImpl(MCII, *ArchSTI, Context, MCB, &ArchCheck); +} MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII, MCInst const &Inst, @@ -394,6 +419,26 @@ unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII, return ((F >> HexagonII::TypePos) & HexagonII::TypeMask); } +/// Return the resources used by this instruction +unsigned HexagonMCInstrInfo::getCVIResources(MCInstrInfo const &MCII, + MCSubtargetInfo const &STI, + MCInst const &MCI) { + + const InstrItinerary *II = STI.getSchedModel().InstrItineraries; + int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass(); + int Size = II[SchedClass].LastStage - II[SchedClass].FirstStage; + + // HVX resources used are currenty located at the second to last stage. + // This could also be done with a linear search of the stages looking for: + // CVI_ALL, CVI_MPY01, CVI_XLSHF, CVI_MPY0, CVI_MPY1, CVI_SHIFT, CVI_XLANE, + // CVI_ZW + unsigned Stage = II[SchedClass].LastStage - 1; + + if (Size < 2) + return 0; + return ((Stage + HexagonStages)->getUnits()); +} + /// Return the slots this instruction can execute out of unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, @@ -473,7 +518,7 @@ bool HexagonMCInstrInfo::hasNewValue2(MCInstrInfo const &MCII, MCInst const &HexagonMCInstrInfo::instruction(MCInst const &MCB, size_t Index) { assert(isBundle(MCB)); - assert(Index < HEXAGON_PACKET_SIZE); + assert(Index < HEXAGON_PRESHUFFLE_PACKET_SIZE); return *MCB.getOperand(bundleInstructionsOffset + Index).getInst(); } @@ -613,6 +658,12 @@ bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII, return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); } +bool HexagonMCInstrInfo::isNewValueStore(MCInstrInfo const &MCII, + MCInst const &MCI) { + const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; + return (F >> HexagonII::NVStorePos) & HexagonII::NVStoreMask; +} + /// Return whether the operand is extendable. bool HexagonMCInstrInfo::isOpExtendable(MCInstrInfo const &MCII, MCInst const &MCI, unsigned short O) { @@ -625,6 +676,45 @@ bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) { return (Flags & outerLoopMask) != 0; } +bool HexagonMCInstrInfo::IsVecRegPair(unsigned VecReg) { + return (VecReg >= Hexagon::W0 && VecReg <= Hexagon::W15) || + (VecReg >= Hexagon::WR0 && VecReg <= Hexagon::WR15); +} + +bool HexagonMCInstrInfo::IsReverseVecRegPair(unsigned VecReg) { + return (VecReg >= Hexagon::WR0 && VecReg <= Hexagon::WR15); +} + +bool HexagonMCInstrInfo::IsVecRegSingle(unsigned VecReg) { + return (VecReg >= Hexagon::V0 && VecReg <= Hexagon::V31); +} + +std::pair<unsigned, unsigned> +HexagonMCInstrInfo::GetVecRegPairIndices(unsigned VecRegPair) { + assert(IsVecRegPair(VecRegPair) && + "VecRegPair must be a vector register pair"); + + const bool IsRev = IsReverseVecRegPair(VecRegPair); + const unsigned PairIndex = + 2 * (IsRev ? VecRegPair - Hexagon::WR0 : VecRegPair - Hexagon::W0); + + return IsRev ? std::make_pair(PairIndex, PairIndex + 1) + : std::make_pair(PairIndex + 1, PairIndex); +} + +bool HexagonMCInstrInfo::IsSingleConsumerRefPairProducer(unsigned Producer, + unsigned Consumer) { + if (IsVecRegPair(Producer) && IsVecRegSingle(Consumer)) { + const unsigned ProdPairIndex = IsReverseVecRegPair(Producer) + ? Producer - Hexagon::WR0 + : Producer - Hexagon::W0; + const unsigned ConsumerSingleIndex = (Consumer - Hexagon::V0) >> 1; + + return ConsumerSingleIndex == ProdPairIndex; + } + return false; +} + bool HexagonMCInstrInfo::isPredicated(MCInstrInfo const &MCII, MCInst const &MCI) { const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; @@ -655,8 +745,17 @@ bool HexagonMCInstrInfo::isPredicatedTrue(MCInstrInfo const &MCII, !((F >> HexagonII::PredicatedFalsePos) & HexagonII::PredicatedFalseMask)); } -bool HexagonMCInstrInfo::isPredReg(unsigned Reg) { - return (Reg >= Hexagon::P0 && Reg <= Hexagon::P3_0); +bool HexagonMCInstrInfo::isPredReg(MCRegisterInfo const &MRI, unsigned Reg) { + auto &PredRegClass = MRI.getRegClass(Hexagon::PredRegsRegClassID); + return PredRegClass.contains(Reg); +} + +bool HexagonMCInstrInfo::isPredRegister(MCInstrInfo const &MCII, + MCInst const &Inst, unsigned I) { + MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, Inst); + + return Inst.getOperand(I).isReg() && + Desc.OpInfo[I].RegClass == Hexagon::PredRegsRegClassID; } /// Return whether the insn can be packaged only with A and X-type insns. @@ -753,10 +852,8 @@ bool HexagonMCInstrInfo::isSubInstruction(MCInst const &MCI) { } bool HexagonMCInstrInfo::isVector(MCInstrInfo const &MCII, MCInst const &MCI) { - if ((getType(MCII, MCI) <= HexagonII::TypeCVI_LAST) && - (getType(MCII, MCI) >= HexagonII::TypeCVI_FIRST)) - return true; - return false; + const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; + return (F >> HexagonII::isCVIPos) & HexagonII::isCVIMask; } int64_t HexagonMCInstrInfo::minConstant(MCInst const &MCI, size_t Index) { @@ -802,6 +899,18 @@ bool HexagonMCInstrInfo::s27_2_reloc(MCExpr const &Expr) { return HExpr->s27_2_reloc(); } +unsigned HexagonMCInstrInfo::packetSizeSlots(MCSubtargetInfo const &STI) { + const bool IsTiny = STI.getFeatureBits()[Hexagon::ProcTinyCore]; + + return IsTiny ? (HEXAGON_PACKET_SIZE - 1) : HEXAGON_PACKET_SIZE; +} + +unsigned HexagonMCInstrInfo::packetSize(StringRef CPU) { + return llvm::StringSwitch<unsigned>(CPU) + .Case("hexagonv67t", 3) + .Default(4); +} + void HexagonMCInstrInfo::padEndloop(MCInst &MCB, MCContext &Context) { MCInst Nop; Nop.setOpcode(Hexagon::A2_nop); @@ -836,6 +945,33 @@ bool HexagonMCInstrInfo::hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI) { return (F >> HexagonII::HasTmpDstPos) & HexagonII::HasTmpDstMask; } +bool HexagonMCInstrInfo::requiresSlot(MCSubtargetInfo const &STI, + MCInst const &MCI) { + const unsigned OpCode = MCI.getOpcode(); + const bool IsTiny = STI.getFeatureBits() [Hexagon::ProcTinyCore]; + const bool NoSlotReqd = Hexagon::A4_ext == OpCode || + (IsTiny && Hexagon::A2_nop == OpCode) || + (IsTiny && Hexagon::J4_hintjumpr == OpCode); + + return !NoSlotReqd; +} + +unsigned HexagonMCInstrInfo::slotsConsumed(MCInstrInfo const &MCII, + MCSubtargetInfo const &STI, + MCInst const &MCI) { + unsigned slotsUsed = 0; + for (auto HMI : bundleInstructions(MCI)) { + MCInst const &MCI = *HMI.getInst(); + if (!requiresSlot(STI, MCI)) + continue; + if (isDuplex(MCII, MCI)) + slotsUsed += 2; + else + ++slotsUsed; + } + return slotsUsed; +} + void HexagonMCInstrInfo::replaceDuplex(MCContext &Context, MCInst &MCB, DuplexCandidate Candidate) { assert(Candidate.packetIndexI < MCB.size()); @@ -874,9 +1010,8 @@ unsigned HexagonMCInstrInfo::SubregisterBit(unsigned Consumer, unsigned Producer2) { // If we're a single vector consumer of a double producer, set subreg bit // based on if we're accessing the lower or upper register component - if (Producer >= Hexagon::W0 && Producer <= Hexagon::W15) - if (Consumer >= Hexagon::V0 && Consumer <= Hexagon::V31) - return (Consumer - Hexagon::V0) & 0x1; + if (IsVecRegPair(Producer) && IsVecRegSingle(Consumer)) + return (Consumer - Hexagon::V0) & 0x1; if (Producer2 != Hexagon::NoRegister) return Consumer == Producer; return 0; |