From 27420dd23190e027724bfd01c331f220ff159453 Mon Sep 17 00:00:00 2001 From: Colin LeMahieu Date: Sat, 30 May 2015 18:55:47 +0000 Subject: [PATCH] [Hexagon] Adding basic relaxation functionality. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238660 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../MCTargetDesc/HexagonAsmBackend.cpp | 129 +++++++++++++++++- .../MCTargetDesc/HexagonMCInstrInfo.cpp | 24 ++++ .../Hexagon/MCTargetDesc/HexagonMCInstrInfo.h | 10 ++ 3 files changed, 157 insertions(+), 6 deletions(-) diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp index 155aa9ef955..270c3a19dca 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp @@ -7,17 +7,27 @@ // //===----------------------------------------------------------------------===// +#include "Hexagon.h" +#include "HexagonFixupKinds.h" #include "HexagonMCTargetDesc.h" +#include "MCTargetDesc/HexagonBaseInfo.h" +#include "MCTargetDesc/HexagonMCInstrInfo.h" #include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCELFObjectWriter.h" using namespace llvm; +using namespace Hexagon; namespace { class HexagonAsmBackend : public MCAsmBackend { + mutable uint64_t relaxedCnt; + std::unique_ptr MCII; + std::unique_ptr RelaxTarget; public: - HexagonAsmBackend(Target const & /*T*/) {} + HexagonAsmBackend(Target const & /*T*/) : + MCII (createHexagonMCInstrInfo()), RelaxTarget(new MCInst *){} unsigned getNumFixupKinds() const override { return 0; } @@ -27,14 +37,121 @@ public: return; } - bool mayNeedRelaxation(MCInst const & /*Inst*/) const override { + bool isInstRelaxable(MCInst const &HMI) const { + const MCInstrDesc &MCID = HexagonMCInstrInfo::getDesc(*MCII, HMI); + assert(&MCID && "invalid instruction"); + + bool Relaxable = false; + // Branches and loop-setup insns are handled as necessary by relaxation. + if (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeJ || + (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeNV && + MCID.isBranch()) || + (llvm::HexagonMCInstrInfo::getType(*MCII, HMI) == HexagonII::TypeCR && + HMI.getOpcode() != Hexagon::C4_addipc)) + if (HexagonMCInstrInfo::isExtendable(*MCII, HMI)) + Relaxable = true; + + return Relaxable; + } + + /// MayNeedRelaxation - Check whether the given instruction may need + /// relaxation. + /// + /// \param Inst - The instruction to test. + bool mayNeedRelaxation(MCInst const &Inst) const { + assert(HexagonMCInstrInfo::isBundle(Inst)); + bool PreviousIsExtender = false; + for (auto const &I : HexagonMCInstrInfo::bundleInstructions(Inst)) { + auto const &Inst = *I.getInst(); + if (!PreviousIsExtender) { + if (isInstRelaxable(Inst)) + return true; + } + PreviousIsExtender = HexagonMCInstrInfo::isImmext(Inst); + } + return false; + } + + /// fixupNeedsRelaxation - Target specific predicate for whether a given + /// fixup requires the associated instruction to be relaxed. + bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, + uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const { + MCInst const &MCB = DF->getInst(); + assert(HexagonMCInstrInfo::isBundle(MCB)); + + *RelaxTarget = nullptr; + MCInst &MCI = const_cast(HexagonMCInstrInfo::instruction( + MCB, Fixup.getOffset() / HEXAGON_INSTR_SIZE)); + // If we cannot resolve the fixup value, it requires relaxation. + if (!Resolved) { + switch ((unsigned)Fixup.getKind()) { + case fixup_Hexagon_B22_PCREL: + // GetFixupCount assumes B22 won't relax + // Fallthrough + default: + return false; + break; + case fixup_Hexagon_B13_PCREL: + case fixup_Hexagon_B15_PCREL: + case fixup_Hexagon_B9_PCREL: + case fixup_Hexagon_B7_PCREL: { + if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) { + ++relaxedCnt; + *RelaxTarget = &MCI; + return true; + } else { + return false; + } + break; + } + } + } + bool Relaxable = isInstRelaxable(MCI); + if (Relaxable == false) + return false; + + MCFixupKind Kind = Fixup.getKind(); + int64_t sValue = Value; + int64_t maxValue; + + switch ((unsigned)Kind) { + case fixup_Hexagon_B7_PCREL: + maxValue = 1 << 8; + break; + case fixup_Hexagon_B9_PCREL: + maxValue = 1 << 10; + break; + case fixup_Hexagon_B15_PCREL: + maxValue = 1 << 16; + break; + case fixup_Hexagon_B22_PCREL: + maxValue = 1 << 23; + break; + default: + maxValue = INT64_MAX; + break; + } + + bool isFarAway = -maxValue > sValue || sValue > maxValue - 1; + + if (isFarAway) { + if (HexagonMCInstrInfo::bundleSize(MCB) < HEXAGON_PACKET_SIZE) { + ++relaxedCnt; + *RelaxTarget = &MCI; + return true; + } + } + return false; } - bool fixupNeedsRelaxation(MCFixup const & /*Fixup*/, uint64_t /*Value*/, - MCRelaxableFragment const * /*DF*/, - MCAsmLayout const & /*Layout*/) const override { - llvm_unreachable("fixupNeedsRelaxation() unimplemented"); + /// Simple predicate for targets where !Resolved implies requiring relaxation + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced"); } void relaxInstruction(MCInst const & /*Inst*/, diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp index 88bbe76472b..5ea00d36e5a 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp @@ -56,6 +56,24 @@ MCInstrDesc const &HexagonMCInstrInfo::getDesc(MCInstrInfo const &MCII, return (MCII.get(MCI.getOpcode())); } +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; @@ -137,6 +155,12 @@ bool HexagonMCInstrInfo::hasNewValue(MCInstrInfo const &MCII, return ((F >> HexagonII::hasNewValuePos) & HexagonII::hasNewValueMask); } +MCInst const &HexagonMCInstrInfo::instruction(MCInst const &MCB, size_t Index) { + assert(isBundle(MCB)); + assert(Index < HEXAGON_PACKET_SIZE); + return *MCB.getOperand(bundleInstructionsOffset + Index).getInst(); +} + bool HexagonMCInstrInfo::isBundle(MCInst const &MCI) { auto Result = Hexagon::BUNDLE == MCI.getOpcode(); assert(!Result || (MCI.size() > 0 && MCI.getOperand(0).isImm())); diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h index 0301e4814c6..5522a03a1b7 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h @@ -54,6 +54,13 @@ unsigned short getCExtOpNum(MCInstrInfo const &MCII, MCInst const &MCI); MCInstrDesc const &getDesc(MCInstrInfo const &MCII, MCInst const &MCI); +// Return the index of the extendable operand +unsigned short getExtendableOp(MCInstrInfo const &MCII, MCInst const &MCI); + +// Return a reference to the extendable operand +MCOperand const &getExtendableOperand(MCInstrInfo const &MCII, + MCInst const &MCI); + // Return the implicit alignment of the extendable operand unsigned getExtentAlignment(MCInstrInfo const &MCII, MCInst const &MCI); @@ -83,6 +90,9 @@ unsigned getType(MCInstrInfo const &MCII, MCInst const &MCI); // Return whether the instruction is a legal new-value producer. bool hasNewValue(MCInstrInfo const &MCII, MCInst const &MCI); +// Return the instruction at Index +MCInst const &instruction(MCInst const &MCB, size_t Index); + // Returns whether this MCInst is a wellformed bundle bool isBundle(MCInst const &MCI); -- 2.34.1