[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:
Colin LeMahieu 2015-05-30 18:55:47 +00:00
parent 32de7d791e
commit 27420dd231
3 changed files with 157 additions and 6 deletions

View File

@ -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*/,

View File

@ -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()));

View File

@ -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);