| //===- HexagonMCInstrInfo.cpp - Hexagon sub-class of MCInst ---------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This class extends MCInstrInfo to allow Hexagon specific MCInstr queries |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "MCTargetDesc/HexagonMCInstrInfo.h" |
| #include "MCTargetDesc/HexagonBaseInfo.h" |
| #include "MCTargetDesc/HexagonMCChecker.h" |
| #include "MCTargetDesc/HexagonMCExpr.h" |
| #include "MCTargetDesc/HexagonMCShuffler.h" |
| #include "MCTargetDesc/HexagonMCTargetDesc.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/MC/MCContext.h" |
| #include "llvm/MC/MCExpr.h" |
| #include "llvm/MC/MCInst.h" |
| #include "llvm/MC/MCInstrInfo.h" |
| #include "llvm/MC/MCInstrItineraries.h" |
| #include "llvm/MC/MCSubtargetInfo.h" |
| #include "llvm/Support/Casting.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include <cassert> |
| #include <cstdint> |
| #include <limits> |
| |
| using namespace llvm; |
| |
| bool HexagonMCInstrInfo::PredicateInfo::isPredicated() const { |
| return Register != Hexagon::NoRegister; |
| } |
| |
| Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII, |
| MCInst const &Inst) |
| : MCII(MCII), BundleCurrent(Inst.begin() + |
| HexagonMCInstrInfo::bundleInstructionsOffset), |
| BundleEnd(Inst.end()), DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {} |
| |
| Hexagon::PacketIterator::PacketIterator(MCInstrInfo const &MCII, |
| MCInst const &Inst, std::nullptr_t) |
| : MCII(MCII), BundleCurrent(Inst.end()), BundleEnd(Inst.end()), |
| DuplexCurrent(Inst.end()), DuplexEnd(Inst.end()) {} |
| |
| Hexagon::PacketIterator &Hexagon::PacketIterator::operator++() { |
| if (DuplexCurrent != DuplexEnd) { |
| ++DuplexCurrent; |
| if (DuplexCurrent == DuplexEnd) { |
| DuplexCurrent = BundleEnd; |
| DuplexEnd = BundleEnd; |
| ++BundleCurrent; |
| } |
| return *this; |
| } |
| ++BundleCurrent; |
| if (BundleCurrent != BundleEnd) { |
| MCInst const &Inst = *BundleCurrent->getInst(); |
| if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) { |
| DuplexCurrent = Inst.begin(); |
| DuplexEnd = Inst.end(); |
| } |
| } |
| return *this; |
| } |
| |
| MCInst const &Hexagon::PacketIterator::operator*() const { |
| if (DuplexCurrent != DuplexEnd) |
| return *DuplexCurrent->getInst(); |
| return *BundleCurrent->getInst(); |
| } |
| |
| bool Hexagon::PacketIterator::operator==(PacketIterator const &Other) const { |
| return BundleCurrent == Other.BundleCurrent && BundleEnd == Other.BundleEnd && |
| DuplexCurrent == Other.DuplexCurrent && DuplexEnd == Other.DuplexEnd; |
| } |
| |
| void HexagonMCInstrInfo::addConstant(MCInst &MI, uint64_t Value, |
| MCContext &Context) { |
| MI.addOperand(MCOperand::createExpr(MCConstantExpr::create(Value, Context))); |
| } |
| |
| void HexagonMCInstrInfo::addConstExtender(MCContext &Context, |
| MCInstrInfo const &MCII, MCInst &MCB, |
| MCInst const &MCI) { |
| assert(HexagonMCInstrInfo::isBundle(MCB)); |
| MCOperand const &exOp = |
| MCI.getOperand(HexagonMCInstrInfo::getExtendableOp(MCII, MCI)); |
| |
| // Create the extender. |
| MCInst *XMCI = |
| new (Context) MCInst(HexagonMCInstrInfo::deriveExtender(MCII, MCI, exOp)); |
| XMCI->setLoc(MCI.getLoc()); |
| |
| MCB.addOperand(MCOperand::createInst(XMCI)); |
| } |
| |
| iterator_range<Hexagon::PacketIterator> |
| HexagonMCInstrInfo::bundleInstructions(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| assert(isBundle(MCI)); |
| return make_range(Hexagon::PacketIterator(MCII, MCI), |
| Hexagon::PacketIterator(MCII, MCI, nullptr)); |
| } |
| |
| iterator_range<MCInst::const_iterator> |
| HexagonMCInstrInfo::bundleInstructions(MCInst const &MCI) { |
| assert(isBundle(MCI)); |
| return make_range(MCI.begin() + bundleInstructionsOffset, MCI.end()); |
| } |
| |
| size_t HexagonMCInstrInfo::bundleSize(MCInst const &MCI) { |
| if (HexagonMCInstrInfo::isBundle(MCI)) |
| return (MCI.size() - bundleInstructionsOffset); |
| else |
| return (1); |
| } |
| |
| bool HexagonMCInstrInfo::canonicalizePacket(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) |
| return false; |
| // Examine the packet and convert pairs of instructions to compound |
| // instructions when possible. |
| 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 = |
| HexagonMCInstrInfo::getDuplexPossibilties(MCII, STI, MCB); |
| HexagonMCShuffle(Context, MCII, STI, MCB, possibleDuplexes); |
| } |
| // Examines packet and pad the packet, if needed, when an |
| // end-loop is in the bundle. |
| 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) |
| return false; |
| // Check the bundle for errors. |
| CheckOk = Check ? Check->check(true) : true; |
| if (!CheckOk) |
| return false; |
| HexagonMCShuffle(Context, true, MCII, STI, MCB); |
| return true; |
| } |
| |
| MCInst HexagonMCInstrInfo::deriveExtender(MCInstrInfo const &MCII, |
| MCInst const &Inst, |
| MCOperand const &MO) { |
| assert(HexagonMCInstrInfo::isExtendable(MCII, Inst) || |
| HexagonMCInstrInfo::isExtended(MCII, Inst)); |
| |
| MCInst XMI; |
| XMI.setOpcode(Hexagon::A4_ext); |
| if (MO.isImm()) |
| XMI.addOperand(MCOperand::createImm(MO.getImm() & (~0x3f))); |
| else if (MO.isExpr()) |
| XMI.addOperand(MCOperand::createExpr(MO.getExpr())); |
| else |
| llvm_unreachable("invalid extendable operand"); |
| return XMI; |
| } |
| |
| MCInst *HexagonMCInstrInfo::deriveDuplex(MCContext &Context, unsigned iClass, |
| MCInst const &inst0, |
| MCInst const &inst1) { |
| assert((iClass <= 0xf) && "iClass must have range of 0 to 0xf"); |
| MCInst *duplexInst = new (Context) MCInst; |
| duplexInst->setOpcode(Hexagon::DuplexIClass0 + iClass); |
| |
| MCInst *SubInst0 = new (Context) MCInst(deriveSubInst(inst0)); |
| MCInst *SubInst1 = new (Context) MCInst(deriveSubInst(inst1)); |
| duplexInst->addOperand(MCOperand::createInst(SubInst0)); |
| duplexInst->addOperand(MCOperand::createInst(SubInst1)); |
| return duplexInst; |
| } |
| |
| MCInst const *HexagonMCInstrInfo::extenderForIndex(MCInst const &MCB, |
| size_t Index) { |
| assert(Index <= bundleSize(MCB)); |
| if (Index == 0) |
| return nullptr; |
| MCInst const *Inst = |
| MCB.getOperand(Index + bundleInstructionsOffset - 1).getInst(); |
| if (isImmext(*Inst)) |
| return Inst; |
| return nullptr; |
| } |
| |
| void HexagonMCInstrInfo::extendIfNeeded(MCContext &Context, |
| MCInstrInfo const &MCII, MCInst &MCB, |
| MCInst const &MCI) { |
| if (isConstExtended(MCII, MCI)) |
| addConstExtender(Context, MCII, MCB, MCI); |
| } |
| |
| unsigned HexagonMCInstrInfo::getMemAccessSize(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| unsigned S = (F >> HexagonII::MemAccessSizePos) & HexagonII::MemAccesSizeMask; |
| return HexagonII::getMemAccessSizeInBytes(HexagonII::MemAccessSize(S)); |
| } |
| |
| unsigned HexagonMCInstrInfo::getAddrMode(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return static_cast<unsigned>((F >> HexagonII::AddrModePos) & |
| HexagonII::AddrModeMask); |
| } |
| |
| MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| return MCII.get(MCI.getOpcode()); |
| } |
| |
| unsigned HexagonMCInstrInfo::getDuplexRegisterNumbering(unsigned Reg) { |
| using namespace Hexagon; |
| |
| switch (Reg) { |
| default: |
| llvm_unreachable("unknown duplex register"); |
| // Rs Rss |
| case R0: |
| case D0: |
| return 0; |
| case R1: |
| case D1: |
| return 1; |
| case R2: |
| case D2: |
| return 2; |
| case R3: |
| case D3: |
| return 3; |
| case R4: |
| case D8: |
| return 4; |
| case R5: |
| case D9: |
| return 5; |
| case R6: |
| case D10: |
| return 6; |
| case R7: |
| case D11: |
| return 7; |
| case R16: |
| return 8; |
| case R17: |
| return 9; |
| case R18: |
| return 10; |
| case R19: |
| return 11; |
| case R20: |
| return 12; |
| case R21: |
| return 13; |
| case R22: |
| return 14; |
| case R23: |
| return 15; |
| } |
| } |
| |
| MCExpr const &HexagonMCInstrInfo::getExpr(MCExpr const &Expr) { |
| const auto &HExpr = cast<HexagonMCExpr>(Expr); |
| assert(HExpr.getExpr()); |
| return *HExpr.getExpr(); |
| } |
| |
| unsigned short HexagonMCInstrInfo::getExtendableOp(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::ExtendableOpPos) & HexagonII::ExtendableOpMask); |
| } |
| |
| MCOperand const & |
| HexagonMCInstrInfo::getExtendableOperand(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| unsigned O = HexagonMCInstrInfo::getExtendableOp(MCII, MCI); |
| MCOperand const &MO = MCI.getOperand(O); |
| |
| assert((HexagonMCInstrInfo::isExtendable(MCII, MCI) || |
| HexagonMCInstrInfo::isExtended(MCII, MCI)) && |
| (MO.isImm() || MO.isExpr())); |
| return (MO); |
| } |
| |
| unsigned HexagonMCInstrInfo::getExtentAlignment(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::ExtentAlignPos) & HexagonII::ExtentAlignMask); |
| } |
| |
| unsigned HexagonMCInstrInfo::getExtentBits(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::ExtentBitsPos) & HexagonII::ExtentBitsMask); |
| } |
| |
| bool HexagonMCInstrInfo::isExtentSigned(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return (F >> HexagonII::ExtentSignedPos) & HexagonII::ExtentSignedMask; |
| } |
| |
| /// Return the maximum value of an extendable operand. |
| int HexagonMCInstrInfo::getMaxValue(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) || |
| HexagonMCInstrInfo::isExtended(MCII, MCI)); |
| |
| if (HexagonMCInstrInfo::isExtentSigned(MCII, MCI)) // if value is signed |
| return (1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1)) - 1; |
| return (1 << HexagonMCInstrInfo::getExtentBits(MCII, MCI)) - 1; |
| } |
| |
| /// Return the minimum value of an extendable operand. |
| int HexagonMCInstrInfo::getMinValue(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| assert(HexagonMCInstrInfo::isExtendable(MCII, MCI) || |
| HexagonMCInstrInfo::isExtended(MCII, MCI)); |
| |
| if (HexagonMCInstrInfo::isExtentSigned(MCII, MCI)) // if value is signed |
| return -(1 << (HexagonMCInstrInfo::getExtentBits(MCII, MCI) - 1)); |
| return 0; |
| } |
| |
| StringRef HexagonMCInstrInfo::getName(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| return MCII.getName(MCI.getOpcode()); |
| } |
| |
| unsigned short HexagonMCInstrInfo::getNewValueOp(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::NewValueOpPos) & HexagonII::NewValueOpMask); |
| } |
| |
| MCOperand const &HexagonMCInstrInfo::getNewValueOperand(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| if (HexagonMCInstrInfo::hasTmpDst(MCII, MCI)) { |
| // VTMP doesn't actually exist in the encodings for these 184 |
| // 3 instructions so go ahead and create it here. |
| static MCOperand MCO = MCOperand::createReg(Hexagon::VTMP); |
| return (MCO); |
| } else { |
| unsigned O = HexagonMCInstrInfo::getNewValueOp(MCII, MCI); |
| MCOperand const &MCO = MCI.getOperand(O); |
| |
| assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) || |
| HexagonMCInstrInfo::hasNewValue(MCII, MCI)) && |
| MCO.isReg()); |
| return (MCO); |
| } |
| } |
| |
| /// Return the new value or the newly produced value. |
| unsigned short HexagonMCInstrInfo::getNewValueOp2(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::NewValueOpPos2) & HexagonII::NewValueOpMask2); |
| } |
| |
| MCOperand const & |
| HexagonMCInstrInfo::getNewValueOperand2(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| unsigned O = HexagonMCInstrInfo::getNewValueOp2(MCII, MCI); |
| MCOperand const &MCO = MCI.getOperand(O); |
| |
| assert((HexagonMCInstrInfo::isNewValue(MCII, MCI) || |
| HexagonMCInstrInfo::hasNewValue2(MCII, MCI)) && |
| MCO.isReg()); |
| return (MCO); |
| } |
| |
| /// Return the Hexagon ISA class for the insn. |
| unsigned HexagonMCInstrInfo::getType(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags; |
| return ((F >> HexagonII::TypePos) & HexagonII::TypeMask); |
| } |
| |
| /// Return the slots this instruction can execute out of |
| unsigned HexagonMCInstrInfo::getUnits(MCInstrInfo const &MCII, |
| MCSubtargetInfo const &STI, |
| MCInst const &MCI) { |
| const InstrItinerary *II = STI.getSchedModel().InstrItineraries; |
| int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass(); |
| return ((II[SchedClass].FirstStage + HexagonStages)->getUnits()); |
| } |
| |
| /// Return the slots this instruction consumes in addition to |
| /// the slot(s) it can execute out of |
| |
| unsigned HexagonMCInstrInfo::getOtherReservedSlots(MCInstrInfo const &MCII, |
| MCSubtargetInfo const &STI, |
| MCInst const &MCI) { |
| const InstrItinerary *II = STI.getSchedModel().InstrItineraries; |
| int SchedClass = HexagonMCInstrInfo::getDesc(MCII, MCI).getSchedClass(); |
| unsigned Slots = 0; |
| |
| // FirstStage are slots that this instruction can execute in. |
| // FirstStage+1 are slots that are also consumed by this instruction. |
| // For example: vmemu can only execute in slot 0 but also consumes slot 1. |
| for (unsigned Stage = II[SchedClass].FirstStage + 1; |
| Stage < II[SchedClass].LastStage; ++Stage) { |
| unsigned Units = (Stage + HexagonStages)->getUnits(); |
| if (Units > HexagonGetLastSlot()) |
| break; |
| // fyi: getUnits() will return 0x1, 0x2, 0x4 or 0x8 |
| Slots |= Units; |
| } |
| |
| // if 0 is returned, then no additional slots are consumed by this inst. |
| return Slots; |
| } |
| |
| bool HexagonMCInstrInfo::hasDuplex(MCInstrInfo const &MCII, MCInst const &MCI) { |
| if (!HexagonMCInstrInfo::isBundle(MCI)) |
| return false; |
| |
| for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCI)) { |
| if (HexagonMCInstrInfo::isDuplex(MCII, *I.getInst())) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool HexagonMCInstrInfo::hasExtenderForIndex(MCInst const &MCB, size_t Index) { |
| return extenderForIndex(MCB, Index) != nullptr; |
| } |
| |
| bool HexagonMCInstrInfo::hasImmExt(MCInst const &MCI) { |
| if (!HexagonMCInstrInfo::isBundle(MCI)) |
| return false; |
| |
| for (const auto &I : HexagonMCInstrInfo::bundleInstructions(MCI)) { |
| if (isImmext(*I.getInst())) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| /// Return whether the insn produces a value. |
| bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); |
| } |
| |
| /// Return whether the insn produces a second value. |
| bool HexagonMCInstrInfo::hasNewValue2(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::hasNewValuePos2) & HexagonII::hasNewValueMask2); |
| } |
| |
| MCInst const &HexagonMCInstrInfo::instruction(MCInst const &MCB, size_t Index) { |
| assert(isBundle(MCB)); |
| assert(Index < HEXAGON_PACKET_SIZE); |
| return *MCB.getOperand(bundleInstructionsOffset + Index).getInst(); |
| } |
| |
| /// Return where the instruction is an accumulator. |
| bool HexagonMCInstrInfo::isAccumulator(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::AccumulatorPos) & HexagonII::AccumulatorMask); |
| } |
| |
| bool HexagonMCInstrInfo::isBundle(MCInst const &MCI) { |
| auto Result = Hexagon::BUNDLE == MCI.getOpcode(); |
| assert(!Result || (MCI.size() > 0 && MCI.getOperand(0).isImm())); |
| return Result; |
| } |
| |
| bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| if (HexagonMCInstrInfo::isExtended(MCII, MCI)) |
| return true; |
| if (!HexagonMCInstrInfo::isExtendable(MCII, MCI)) |
| return false; |
| MCOperand const &MO = HexagonMCInstrInfo::getExtendableOperand(MCII, MCI); |
| if (isa<HexagonMCExpr>(MO.getExpr()) && |
| HexagonMCInstrInfo::mustExtend(*MO.getExpr())) |
| return true; |
| // Branch insns are handled as necessary by relaxation. |
| if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeJ) || |
| (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCJ && |
| HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch()) || |
| (HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeNCJ && |
| HexagonMCInstrInfo::getDesc(MCII, MCI).isBranch())) |
| return false; |
| // Otherwise loop instructions and other CR insts are handled by relaxation |
| else if ((HexagonMCInstrInfo::getType(MCII, MCI) == HexagonII::TypeCR) && |
| (MCI.getOpcode() != Hexagon::C4_addipc)) |
| return false; |
| |
| assert(!MO.isImm()); |
| if (isa<HexagonMCExpr>(MO.getExpr()) && |
| HexagonMCInstrInfo::mustNotExtend(*MO.getExpr())) |
| return false; |
| int64_t Value; |
| if (!MO.getExpr()->evaluateAsAbsolute(Value)) |
| return true; |
| int MinValue = HexagonMCInstrInfo::getMinValue(MCII, MCI); |
| int MaxValue = HexagonMCInstrInfo::getMaxValue(MCII, MCI); |
| return (MinValue > Value || Value > MaxValue); |
| } |
| |
| bool HexagonMCInstrInfo::isCanon(MCInstrInfo const &MCII, MCInst const &MCI) { |
| return !HexagonMCInstrInfo::getDesc(MCII, MCI).isPseudo() && |
| !HexagonMCInstrInfo::isPrefix(MCII, MCI); |
| } |
| |
| bool HexagonMCInstrInfo::isCofMax1(MCInstrInfo const &MCII, MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::CofMax1Pos) & HexagonII::CofMax1Mask); |
| } |
| |
| bool HexagonMCInstrInfo::isCofRelax1(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::CofRelax1Pos) & HexagonII::CofRelax1Mask); |
| } |
| |
| bool HexagonMCInstrInfo::isCofRelax2(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::CofRelax2Pos) & HexagonII::CofRelax2Mask); |
| } |
| |
| bool HexagonMCInstrInfo::isCompound(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| return (getType(MCII, MCI) == HexagonII::TypeCJ); |
| } |
| |
| bool HexagonMCInstrInfo::isCVINew(MCInstrInfo const &MCII, MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::CVINewPos) & HexagonII::CVINewMask); |
| } |
| |
| bool HexagonMCInstrInfo::isDblRegForSubInst(unsigned Reg) { |
| return ((Reg >= Hexagon::D0 && Reg <= Hexagon::D3) || |
| (Reg >= Hexagon::D8 && Reg <= Hexagon::D11)); |
| } |
| |
| bool HexagonMCInstrInfo::isDuplex(MCInstrInfo const &MCII, MCInst const &MCI) { |
| return HexagonII::TypeDUPLEX == HexagonMCInstrInfo::getType(MCII, MCI); |
| } |
| |
| bool HexagonMCInstrInfo::isExtendable(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return (F >> HexagonII::ExtendablePos) & HexagonII::ExtendableMask; |
| } |
| |
| bool HexagonMCInstrInfo::isExtended(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| uint64_t const F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return (F >> HexagonII::ExtendedPos) & HexagonII::ExtendedMask; |
| } |
| |
| bool HexagonMCInstrInfo::isFloat(MCInstrInfo const &MCII, MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::FPPos) & HexagonII::FPMask); |
| } |
| |
| bool HexagonMCInstrInfo::isHVX(MCInstrInfo const &MCII, MCInst const &MCI) { |
| const uint64_t V = getType(MCII, MCI); |
| return HexagonII::TypeCVI_FIRST <= V && V <= HexagonII::TypeCVI_LAST; |
| } |
| |
| bool HexagonMCInstrInfo::isImmext(MCInst const &MCI) { |
| return MCI.getOpcode() == Hexagon::A4_ext; |
| } |
| |
| bool HexagonMCInstrInfo::isInnerLoop(MCInst const &MCI) { |
| assert(isBundle(MCI)); |
| int64_t Flags = MCI.getOperand(0).getImm(); |
| return (Flags & innerLoopMask) != 0; |
| } |
| |
| bool HexagonMCInstrInfo::isIntReg(unsigned Reg) { |
| return (Reg >= Hexagon::R0 && Reg <= Hexagon::R31); |
| } |
| |
| bool HexagonMCInstrInfo::isIntRegForSubInst(unsigned Reg) { |
| return ((Reg >= Hexagon::R0 && Reg <= Hexagon::R7) || |
| (Reg >= Hexagon::R16 && Reg <= Hexagon::R23)); |
| } |
| |
| /// Return whether the insn expects newly produced value. |
| bool HexagonMCInstrInfo::isNewValue(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::NewValuePos) & HexagonII::NewValueMask); |
| } |
| |
| /// Return whether the operand is extendable. |
| bool HexagonMCInstrInfo::isOpExtendable(MCInstrInfo const &MCII, |
| MCInst const &MCI, unsigned short O) { |
| return (O == HexagonMCInstrInfo::getExtendableOp(MCII, MCI)); |
| } |
| |
| bool HexagonMCInstrInfo::isOuterLoop(MCInst const &MCI) { |
| assert(isBundle(MCI)); |
| int64_t Flags = MCI.getOperand(0).getImm(); |
| return (Flags & outerLoopMask) != 0; |
| } |
| |
| bool HexagonMCInstrInfo::isPredicated(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::PredicatedPos) & HexagonII::PredicatedMask); |
| } |
| |
| bool HexagonMCInstrInfo::isPrefix(MCInstrInfo const &MCII, MCInst const &MCI) { |
| return HexagonII::TypeEXTENDER == HexagonMCInstrInfo::getType(MCII, MCI); |
| } |
| |
| bool HexagonMCInstrInfo::isPredicateLate(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return (F >> HexagonII::PredicateLatePos & HexagonII::PredicateLateMask); |
| } |
| |
| /// Return whether the insn is newly predicated. |
| bool HexagonMCInstrInfo::isPredicatedNew(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::PredicatedNewPos) & HexagonII::PredicatedNewMask); |
| } |
| |
| bool HexagonMCInstrInfo::isPredicatedTrue(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ( |
| !((F >> HexagonII::PredicatedFalsePos) & HexagonII::PredicatedFalseMask)); |
| } |
| |
| bool HexagonMCInstrInfo::isPredReg(unsigned Reg) { |
| return (Reg >= Hexagon::P0 && Reg <= Hexagon::P3_0); |
| } |
| |
| /// Return whether the insn can be packaged only with A and X-type insns. |
| bool HexagonMCInstrInfo::isSoloAX(MCInstrInfo const &MCII, MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::SoloAXPos) & HexagonII::SoloAXMask); |
| } |
| |
| /// Return whether the insn can be packaged only with an A-type insn in slot #1. |
| bool HexagonMCInstrInfo::isRestrictSlot1AOK(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::RestrictSlot1AOKPos) & |
| HexagonII::RestrictSlot1AOKMask); |
| } |
| |
| bool HexagonMCInstrInfo::isRestrictNoSlot1Store(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return ((F >> HexagonII::RestrictNoSlot1StorePos) & |
| HexagonII::RestrictNoSlot1StoreMask); |
| } |
| |
| /// Return whether the insn is solo, i.e., cannot be in a packet. |
| bool HexagonMCInstrInfo::isSolo(MCInstrInfo const &MCII, MCInst const &MCI) { |
| const uint64_t F = MCII.get(MCI.getOpcode()).TSFlags; |
| return ((F >> HexagonII::SoloPos) & HexagonII::SoloMask); |
| } |
| |
| bool HexagonMCInstrInfo::isMemReorderDisabled(MCInst const &MCI) { |
| assert(isBundle(MCI)); |
| auto Flags = MCI.getOperand(0).getImm(); |
| return (Flags & memReorderDisabledMask) != 0; |
| } |
| |
| bool HexagonMCInstrInfo::isSubInstruction(MCInst const &MCI) { |
| switch (MCI.getOpcode()) { |
| default: |
| return false; |
| 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: |
| case Hexagon::SL1_loadri_io: |
| case Hexagon::SL1_loadrub_io: |
| case Hexagon::SL2_deallocframe: |
| case Hexagon::SL2_jumpr31: |
| case Hexagon::SL2_jumpr31_f: |
| case Hexagon::SL2_jumpr31_fnew: |
| case Hexagon::SL2_jumpr31_t: |
| case Hexagon::SL2_jumpr31_tnew: |
| case Hexagon::SL2_loadrb_io: |
| case Hexagon::SL2_loadrd_sp: |
| case Hexagon::SL2_loadrh_io: |
| case Hexagon::SL2_loadri_sp: |
| case Hexagon::SL2_loadruh_io: |
| case Hexagon::SL2_return: |
| case Hexagon::SL2_return_f: |
| case Hexagon::SL2_return_fnew: |
| case Hexagon::SL2_return_t: |
| case Hexagon::SL2_return_tnew: |
| case Hexagon::SS1_storeb_io: |
| case Hexagon::SS1_storew_io: |
| case Hexagon::SS2_allocframe: |
| case Hexagon::SS2_storebi0: |
| case Hexagon::SS2_storebi1: |
| case Hexagon::SS2_stored_sp: |
| case Hexagon::SS2_storeh_io: |
| case Hexagon::SS2_storew_sp: |
| case Hexagon::SS2_storewi0: |
| case Hexagon::SS2_storewi1: |
| return true; |
| } |
| } |
| |
| 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; |
| } |
| |
| int64_t HexagonMCInstrInfo::minConstant(MCInst const &MCI, size_t Index) { |
| auto Sentinal = static_cast<int64_t>(std::numeric_limits<uint32_t>::max()) |
| << 8; |
| if (MCI.size() <= Index) |
| return Sentinal; |
| MCOperand const &MCO = MCI.getOperand(Index); |
| if (!MCO.isExpr()) |
| return Sentinal; |
| int64_t Value; |
| if (!MCO.getExpr()->evaluateAsAbsolute(Value)) |
| return Sentinal; |
| return Value; |
| } |
| |
| void HexagonMCInstrInfo::setMustExtend(MCExpr const &Expr, bool Val) { |
| HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr)); |
| HExpr.setMustExtend(Val); |
| } |
| |
| bool HexagonMCInstrInfo::mustExtend(MCExpr const &Expr) { |
| HexagonMCExpr const &HExpr = cast<HexagonMCExpr>(Expr); |
| return HExpr.mustExtend(); |
| } |
| void HexagonMCInstrInfo::setMustNotExtend(MCExpr const &Expr, bool Val) { |
| HexagonMCExpr &HExpr = const_cast<HexagonMCExpr &>(cast<HexagonMCExpr>(Expr)); |
| HExpr.setMustNotExtend(Val); |
| } |
| bool HexagonMCInstrInfo::mustNotExtend(MCExpr const &Expr) { |
| HexagonMCExpr const &HExpr = cast<HexagonMCExpr>(Expr); |
| return HExpr.mustNotExtend(); |
| } |
| void HexagonMCInstrInfo::setS27_2_reloc(MCExpr const &Expr, bool Val) { |
| HexagonMCExpr &HExpr = |
| const_cast<HexagonMCExpr &>(*cast<HexagonMCExpr>(&Expr)); |
| HExpr.setS27_2_reloc(Val); |
| } |
| bool HexagonMCInstrInfo::s27_2_reloc(MCExpr const &Expr) { |
| HexagonMCExpr const *HExpr = dyn_cast<HexagonMCExpr>(&Expr); |
| if (!HExpr) |
| return false; |
| return HExpr->s27_2_reloc(); |
| } |
| |
| void HexagonMCInstrInfo::padEndloop(MCInst &MCB, MCContext &Context) { |
| MCInst Nop; |
| Nop.setOpcode(Hexagon::A2_nop); |
| assert(isBundle(MCB)); |
| while ((HexagonMCInstrInfo::isInnerLoop(MCB) && |
| (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_INNER_SIZE)) || |
| ((HexagonMCInstrInfo::isOuterLoop(MCB) && |
| (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_OUTER_SIZE)))) |
| MCB.addOperand(MCOperand::createInst(new (Context) MCInst(Nop))); |
| } |
| |
| HexagonMCInstrInfo::PredicateInfo |
| HexagonMCInstrInfo::predicateInfo(MCInstrInfo const &MCII, MCInst const &MCI) { |
| if (!isPredicated(MCII, MCI)) |
| return {0, 0, false}; |
| MCInstrDesc const &Desc = getDesc(MCII, MCI); |
| for (auto I = Desc.getNumDefs(), N = Desc.getNumOperands(); I != N; ++I) |
| if (Desc.OpInfo[I].RegClass == Hexagon::PredRegsRegClassID) |
| return {MCI.getOperand(I).getReg(), I, isPredicatedTrue(MCII, MCI)}; |
| return {0, 0, false}; |
| } |
| |
| bool HexagonMCInstrInfo::prefersSlot3(MCInstrInfo const &MCII, |
| MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return (F >> HexagonII::PrefersSlot3Pos) & HexagonII::PrefersSlot3Mask; |
| } |
| |
| /// return true if instruction has hasTmpDst attribute. |
| bool HexagonMCInstrInfo::hasTmpDst(MCInstrInfo const &MCII, MCInst const &MCI) { |
| const uint64_t F = HexagonMCInstrInfo::getDesc(MCII, MCI).TSFlags; |
| return (F >> HexagonII::HasTmpDstPos) & HexagonII::HasTmpDstMask; |
| } |
| |
| void HexagonMCInstrInfo::replaceDuplex(MCContext &Context, MCInst &MCB, |
| DuplexCandidate Candidate) { |
| assert(Candidate.packetIndexI < MCB.size()); |
| assert(Candidate.packetIndexJ < MCB.size()); |
| assert(isBundle(MCB)); |
| MCInst *Duplex = |
| deriveDuplex(Context, Candidate.iClass, |
| *MCB.getOperand(Candidate.packetIndexJ).getInst(), |
| *MCB.getOperand(Candidate.packetIndexI).getInst()); |
| assert(Duplex != nullptr); |
| MCB.getOperand(Candidate.packetIndexI).setInst(Duplex); |
| MCB.erase(MCB.begin() + Candidate.packetIndexJ); |
| } |
| |
| void HexagonMCInstrInfo::setInnerLoop(MCInst &MCI) { |
| assert(isBundle(MCI)); |
| MCOperand &Operand = MCI.getOperand(0); |
| Operand.setImm(Operand.getImm() | innerLoopMask); |
| } |
| |
| void HexagonMCInstrInfo::setMemReorderDisabled(MCInst &MCI) { |
| assert(isBundle(MCI)); |
| MCOperand &Operand = MCI.getOperand(0); |
| Operand.setImm(Operand.getImm() | memReorderDisabledMask); |
| assert(isMemReorderDisabled(MCI)); |
| } |
| |
| void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) { |
| assert(isBundle(MCI)); |
| MCOperand &Operand = MCI.getOperand(0); |
| Operand.setImm(Operand.getImm() | outerLoopMask); |
| } |
| |
| unsigned HexagonMCInstrInfo::SubregisterBit(unsigned Consumer, |
| unsigned Producer, |
| 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 (Producer2 != Hexagon::NoRegister) |
| return Consumer == Producer; |
| return 0; |
| } |