mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-11 00:39:36 +00:00
[Hexagon] Adding basic relaxation functionality.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238660 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
32de7d791e
commit
27420dd231
@ -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 <MCInstrInfo> MCII;
|
||||
std::unique_ptr <MCInst *> 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;
|
||||
}
|
||||
|
||||
bool fixupNeedsRelaxation(MCFixup const & /*Fixup*/, uint64_t /*Value*/,
|
||||
MCRelaxableFragment const * /*DF*/,
|
||||
MCAsmLayout const & /*Layout*/) const override {
|
||||
llvm_unreachable("fixupNeedsRelaxation() unimplemented");
|
||||
/// 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<MCInst &>(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;
|
||||
}
|
||||
|
||||
/// 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*/,
|
||||
|
@ -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()));
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user