summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon/MCTargetDesc
diff options
context:
space:
mode:
authorColin LeMahieu <colinl@codeaurora.org>2016-02-16 20:38:17 +0000
committerColin LeMahieu <colinl@codeaurora.org>2016-02-16 20:38:17 +0000
commitecef1d9cbccf8b82f1282e9296af9277748a9169 (patch)
tree65715b41febc3588f887bc7e8750dd77ae443412 /llvm/lib/Target/Hexagon/MCTargetDesc
parent94f127e84a871c490db37f382e225508542a1dc1 (diff)
downloadbcm5719-llvm-ecef1d9cbccf8b82f1282e9296af9277748a9169.tar.gz
bcm5719-llvm-ecef1d9cbccf8b82f1282e9296af9277748a9169.zip
[Hexagon] Adding relocation for code size, cold path optimization allowing a 23-bit 4-byte aligned relocation to be a valid instruction encoding.
The usual way to get a 32-bit relocation is to use a constant extender which doubles the size of the instruction, 4 bytes to 8 bytes. Another way is to put a .word32 and mix code and data within a function. The disadvantage is it's not a valid instruction encoding and jumping over it causes prefetch stalls inside the hardware. This relocation packs a 23-bit value in to an "r0 = add(rX, #a)" instruction by overwriting the source register bits. Since r0 is the return value register, if this instruction is placed after a function call which return void, r0 will be filled with an undefined value, the prefetch won't be confused, and the callee can access the constant value by way of the link register. llvm-svn: 261006
Diffstat (limited to 'llvm/lib/Target/Hexagon/MCTargetDesc')
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp2
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h1
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp7
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp7
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h3
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp12
-rw-r--r--llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h2
7 files changed, 33 insertions, 1 deletions
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
index 4f03c970e2d..944e235e72f 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonELFObjectWriter.cpp
@@ -282,6 +282,8 @@ unsigned HexagonELFObjectWriter::getRelocType(MCContext &Ctx,
return ELF::R_HEX_TPREL_16_X;
case fixup_Hexagon_TPREL_11_X:
return ELF::R_HEX_TPREL_11_X;
+ case fixup_Hexagon_23_REG:
+ return ELF::R_HEX_23_REG;
}
}
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h
index 4bbfbec883c..4c97ebbdd34 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonFixupKinds.h
@@ -110,6 +110,7 @@ enum Fixups {
fixup_Hexagon_TPREL_32_6_X,
fixup_Hexagon_TPREL_16_X,
fixup_Hexagon_TPREL_11_X,
+ fixup_Hexagon_23_REG,
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
index fcc9fcd3e01..d4eb2fc420d 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCCodeEmitter.cpp
@@ -550,6 +550,13 @@ unsigned HexagonMCCodeEmitter::getExprOpValue(const MCInst &MI,
}
} else
switch (kind) {
+ case MCSymbolRefExpr::VK_None: {
+ if (HexagonMCInstrInfo::s23_2_reloc(*MO.getExpr()))
+ FixupKind = Hexagon::fixup_Hexagon_23_REG;
+ else
+ raise_relocation_error(bits, kind);
+ break;
+ }
case MCSymbolRefExpr::VK_DTPREL:
FixupKind = Hexagon::fixup_Hexagon_DTPREL_16;
break;
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp
index d3ee31434ea..8a83e7b1b9b 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.cpp
@@ -52,12 +52,17 @@ void HexagonMCExpr::setMustNotExtend(bool Val) {
}
bool HexagonMCExpr::mustNotExtend() const { return MustNotExtend; }
+bool HexagonMCExpr::s23_2_reloc() const { return S23_2_reloc; }
+void HexagonMCExpr::setS23_2_reloc(bool Val) {
+ S23_2_reloc = Val;
+}
+
bool HexagonMCExpr::classof(MCExpr const *E) {
return E->getKind() == MCExpr::Target;
}
HexagonMCExpr::HexagonMCExpr(MCExpr const *Expr)
- : Expr(Expr), MustNotExtend(false), MustExtend(false) {}
+ : Expr(Expr), MustNotExtend(false), MustExtend(false), S23_2_reloc(false) {}
void HexagonMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
Expr->print(OS, MAI);
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h
index e16d92609bd..1396f2df02e 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCExpr.h
@@ -29,12 +29,15 @@ public:
bool mustExtend() const;
void setMustNotExtend(bool Val = true);
bool mustNotExtend() const;
+ void setS23_2_reloc(bool Val = true);
+ bool s23_2_reloc() const;
private:
HexagonMCExpr(MCExpr const *Expr);
MCExpr const *Expr;
bool MustNotExtend;
bool MustExtend;
+ bool S23_2_reloc;
};
} // end namespace llvm
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
index 9b3d11a8fed..fb585b9fc77 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.cpp
@@ -431,6 +431,9 @@ bool HexagonMCInstrInfo::isConstExtended(MCInstrInfo const &MCII,
// object we are going to end up with here for now.
// In the future we probably should add isSymbol(), etc.
assert(!MO.isImm());
+ if (isa<HexagonMCExpr>(MO.getExpr()) &&
+ HexagonMCInstrInfo::mustNotExtend(*MO.getExpr()))
+ return false;
int64_t Value;
if (!MO.getExpr()->evaluateAsAbsolute(Value))
return true;
@@ -665,6 +668,15 @@ void HexagonMCInstrInfo::setMemStoreReorderEnabled(MCInst &MCI) {
Operand.setImm(Operand.getImm() | memStoreReorderEnabledMask);
assert(isMemStoreReorderEnabled(MCI));
}
+void HexagonMCInstrInfo::setS23_2_reloc(MCExpr const &Expr, bool Val) {
+ HexagonMCExpr &HExpr =
+ const_cast<HexagonMCExpr &>(*llvm::cast<HexagonMCExpr>(&Expr));
+ HExpr.setS23_2_reloc(Val);
+}
+bool HexagonMCInstrInfo::s23_2_reloc(MCExpr const &Expr) {
+ HexagonMCExpr const &HExpr = *llvm::cast<HexagonMCExpr>(&Expr);
+ return HExpr.s23_2_reloc();
+}
void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) {
assert(isBundle(MCI));
diff --git a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
index 6bfcabf45fc..c9162a6aa6a 100644
--- a/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
+++ b/llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCInstrInfo.h
@@ -274,12 +274,14 @@ bool prefersSlot3(MCInstrInfo const &MCII, MCInst const &MCI);
// Replace the instructions inside MCB, represented by Candidate
void replaceDuplex(MCContext &Context, MCInst &MCB, DuplexCandidate Candidate);
+bool s23_2_reloc(MCExpr const &Expr);
// Marks a bundle as endloop0
void setInnerLoop(MCInst &MCI);
void setMemReorderDisabled(MCInst &MCI);
void setMemStoreReorderEnabled(MCInst &MCI);
void setMustExtend(MCExpr &Expr, bool Val = true);
void setMustNotExtend(MCExpr const &Expr, bool Val = true);
+void setS23_2_reloc(MCExpr const &Expr, bool Val = true);
// Marks a bundle as endloop1
void setOuterLoop(MCInst &MCI);
OpenPOWER on IntegriCloud