[mips][mc] Emit R_{MICRO}MIPS_JALR when expanding jal to jalr
When replacing jal with jalr, also emit '.reloc R_MIPS_JALR' (R_MICROMIPS_JALR
for micromips). The linker might then be able to turn jalr into a direct
call.
Add '-mips-jalr-reloc' to enable/disable this feature (default is true).
Differential revision: https://reviews.llvm.org/D55292
llvm-svn: 348760
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 79e0c00..78dfed6 100644
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -39,6 +39,7 @@
#include "llvm/MC/MCValue.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -64,6 +65,11 @@
} // end namespace llvm
+static cl::opt<bool>
+EmitJalrReloc("mips-jalr-reloc", cl::Hidden,
+ cl::desc("MIPS: Emit R_{MICRO}MIPS_JALR relocation with jalr"),
+ cl::init(true));
+
namespace {
class MipsAssemblerOptions {
@@ -2065,9 +2071,21 @@
JalrInst.addOperand(MCOperand::createReg(Mips::RA));
JalrInst.addOperand(MCOperand::createReg(Mips::T9));
- // FIXME: Add an R_(MICRO)MIPS_JALR relocation after the JALR.
- // This relocation is supposed to be an optimization hint for the linker
- // and is not necessary for correctness.
+ if (EmitJalrReloc) {
+ // As an optimization hint for the linker, before the JALR we add:
+ // .reloc tmplabel, R_{MICRO}MIPS_JALR, symbol
+ // tmplabel:
+ MCSymbol *TmpLabel = getContext().createTempSymbol();
+ const MCExpr *TmpExpr = MCSymbolRefExpr::create(TmpLabel, getContext());
+ const MCExpr *RelocJalrExpr =
+ MCSymbolRefExpr::create(JalSym, MCSymbolRefExpr::VK_None,
+ getContext(), IDLoc);
+
+ TOut.getStreamer().EmitRelocDirective(*TmpExpr,
+ inMicroMipsMode() ? "R_MICROMIPS_JALR" : "R_MIPS_JALR",
+ RelocJalrExpr, IDLoc, *STI);
+ TOut.getStreamer().EmitLabel(TmpLabel);
+ }
Inst = JalrInst;
ExpandedJalSym = true;