summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirav Dave <niravd@google.com>2016-07-11 14:23:53 +0000
committerNirav Dave <niravd@google.com>2016-07-11 14:23:53 +0000
commit6b00c9f9a956644c9e85657e605be954e8d0fdf8 (patch)
tree3e305698d6320f14888c71822a0506dec2ffab86
parent064f863be2287a44d993ff7400ac6ba5febb2c84 (diff)
Fix branch relaxation in 16-bit mode.
Thread through MCSubtargetInfo to relaxInstruction function allowing relaxation to generate jumps with 16-bit sized immediates in 16-bit mode. This fixes PR22097. Reviewers: dwmw2, tstellarAMD, craig.topper, jyknight Subscribers: jfb, arsenm, jyknight, llvm-commits, dsanders Differential Revision: http://reviews.llvm.org/D20830 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275068 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCAsmBackend.h4
-rw-r--r--lib/MC/MCAssembler.cpp2
-rw-r--r--lib/MC/MCObjectStreamer.cpp4
-rw-r--r--lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp4
-rw-r--r--lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp3
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp4
-rw-r--r--lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h3
-rw-r--r--lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp3
-rw-r--r--lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp4
-rw-r--r--lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp3
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h3
-rw-r--r--lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp4
-rw-r--r--lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp3
-rw-r--r--lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp3
-rw-r--r--lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp3
-rw-r--r--lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp82
-rw-r--r--test/MC/X86/x86-branch-relaxation.s31
17 files changed, 115 insertions, 48 deletions
diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h
index 7921822ced5..ce17a2a0675 100644
--- a/include/llvm/MC/MCAsmBackend.h
+++ b/include/llvm/MC/MCAsmBackend.h
@@ -102,8 +102,10 @@ public:
///
/// \param Inst The instruction to relax, which may be the same as the
/// output.
+ /// \param STI the subtarget information for the associated instruction.
/// \param [out] Res On return, the relaxed instruction.
- virtual void relaxInstruction(const MCInst &Inst, MCInst &Res) const = 0;
+ virtual void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const = 0;
/// @}
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index fdcd8c7d511..7a42108ceaf 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -765,7 +765,7 @@ bool MCAssembler::relaxInstruction(MCAsmLayout &Layout,
// Relax the fragment.
MCInst Relaxed;
- getBackend().relaxInstruction(F.getInst(), Relaxed);
+ getBackend().relaxInstruction(F.getInst(), F.getSubtargetInfo(), Relaxed);
// Encode the new instruction.
//
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index 05357984781..d2ac0f50261 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -252,9 +252,9 @@ void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
if (Assembler.getRelaxAll() ||
(Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
MCInst Relaxed;
- getAssembler().getBackend().relaxInstruction(Inst, Relaxed);
+ getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed);
while (getAssembler().getBackend().mayNeedRelaxation(Relaxed))
- getAssembler().getBackend().relaxInstruction(Relaxed, Relaxed);
+ getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed);
EmitInstToData(Relaxed, STI);
return;
}
diff --git a/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp b/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
index d88ec99f7d9..27993246eb0 100644
--- a/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
+++ b/lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp
@@ -78,7 +78,8 @@ public:
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const override;
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override;
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override;
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
void HandleAssemblerFlag(MCAssemblerFlag Flag) {}
@@ -313,6 +314,7 @@ bool AArch64AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
}
void AArch64AsmBackend::relaxInstruction(const MCInst &Inst,
+ const MCSubtargetInfo &STI,
MCInst &Res) const {
llvm_unreachable("AArch64AsmBackend::relaxInstruction() unimplemented");
}
diff --git a/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp b/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp
index 98843c97b79..1cb9d21408c 100644
--- a/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp
+++ b/lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp
@@ -53,7 +53,8 @@ public:
const MCAsmLayout &Layout) const override {
return false;
}
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {
assert(!"Not implemented");
}
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
index 2f6a4497f46..0fc758201d4 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp
@@ -258,7 +258,9 @@ bool ARMAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
return reasonForFixupRelaxation(Fixup, Value);
}
-void ARMAsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
+void ARMAsmBackend::relaxInstruction(const MCInst &Inst,
+ const MCSubtargetInfo &STI,
+ MCInst &Res) const {
unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
// Sanity check w/ diagnostic if we get here w/ a bogus instruction.
diff --git a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
index a63cf538e5e..84caaacc47d 100644
--- a/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
+++ b/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h
@@ -63,7 +63,8 @@ public:
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const override;
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override;
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override;
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
diff --git a/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp b/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
index 8c358cab62e..2de40aab3a7 100644
--- a/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
+++ b/lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp
@@ -47,7 +47,8 @@ public:
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
};
diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
index 25fce72019b..2898b056a03 100644
--- a/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
+++ b/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp
@@ -634,8 +634,8 @@ public:
llvm_unreachable("Handled by fixupNeedsRelaxationAdvanced");
}
- void relaxInstruction(MCInst const & Inst,
- MCInst & Res) const override {
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {
assert(HexagonMCInstrInfo::isBundle(Inst) &&
"Hexagon relaxInstruction only works on bundles");
diff --git a/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp b/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp
index d3a075cef16..daf542f41cd 100644
--- a/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp
+++ b/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp
@@ -69,7 +69,8 @@ public:
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
};
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
index 3b65a4b0edd..f260cfa566c 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
@@ -75,7 +75,8 @@ public:
/// \param Inst - The instruction to relax, which may be the same
/// as the output.
/// \param [out] Res On return, the relaxed instruction.
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
/// @}
diff --git a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
index b6dd595ffb0..9100ecb4aa3 100644
--- a/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
+++ b/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
@@ -168,8 +168,8 @@ public:
llvm_unreachable("relaxInstruction() unimplemented");
}
-
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {
// FIXME.
llvm_unreachable("relaxInstruction() unimplemented");
}
diff --git a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
index d1d7aaa07ea..14a70d862f1 100644
--- a/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
+++ b/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
@@ -248,7 +248,8 @@ namespace {
llvm_unreachable("fixupNeedsRelaxation() unimplemented");
return false;
}
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {
// FIXME.
llvm_unreachable("relaxInstruction() unimplemented");
}
diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp
index 57eebe19c04..c4d546cb7df 100644
--- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp
+++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp
@@ -58,7 +58,8 @@ public:
const MCAsmLayout &Layout) const override {
return false;
}
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {
llvm_unreachable("SystemZ does do not have assembler relaxation");
}
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp
index ae3bb327274..df6fb8968d5 100644
--- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp
+++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp
@@ -55,7 +55,8 @@ public:
bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
};
diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
index 5728728dc33..16d721ace97 100644
--- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
+++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp
@@ -131,38 +131,57 @@ public:
const MCRelaxableFragment *DF,
const MCAsmLayout &Layout) const override;
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override;
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override;
bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
};
} // end anonymous namespace
-static unsigned getRelaxedOpcodeBranch(unsigned Op) {
+static unsigned getRelaxedOpcodeBranch(const MCInst &Inst, bool is16BitMode) {
+ unsigned Op = Inst.getOpcode();
switch (Op) {
default:
return Op;
-
- case X86::JAE_1: return X86::JAE_4;
- case X86::JA_1: return X86::JA_4;
- case X86::JBE_1: return X86::JBE_4;
- case X86::JB_1: return X86::JB_4;
- case X86::JE_1: return X86::JE_4;
- case X86::JGE_1: return X86::JGE_4;
- case X86::JG_1: return X86::JG_4;
- case X86::JLE_1: return X86::JLE_4;
- case X86::JL_1: return X86::JL_4;
- case X86::JMP_1: return X86::JMP_4;
- case X86::JNE_1: return X86::JNE_4;
- case X86::JNO_1: return X86::JNO_4;
- case X86::JNP_1: return X86::JNP_4;
- case X86::JNS_1: return X86::JNS_4;
- case X86::JO_1: return X86::JO_4;
- case X86::JP_1: return X86::JP_4;
- case X86::JS_1: return X86::JS_4;
+ case X86::JAE_1:
+ return (is16BitMode) ? X86::JAE_2 : X86::JAE_4;
+ case X86::JA_1:
+ return (is16BitMode) ? X86::JA_2 : X86::JA_4;
+ case X86::JBE_1:
+ return (is16BitMode) ? X86::JBE_2 : X86::JBE_4;
+ case X86::JB_1:
+ return (is16BitMode) ? X86::JB_2 : X86::JB_4;
+ case X86::JE_1:
+ return (is16BitMode) ? X86::JE_2 : X86::JE_4;
+ case X86::JGE_1:
+ return (is16BitMode) ? X86::JGE_2 : X86::JGE_4;
+ case X86::JG_1:
+ return (is16BitMode) ? X86::JG_2 : X86::JG_4;
+ case X86::JLE_1:
+ return (is16BitMode) ? X86::JLE_2 : X86::JLE_4;
+ case X86::JL_1:
+ return (is16BitMode) ? X86::JL_2 : X86::JL_4;
+ case X86::JMP_1:
+ return (is16BitMode) ? X86::JMP_2 : X86::JMP_4;
+ case X86::JNE_1:
+ return (is16BitMode) ? X86::JNE_2 : X86::JNE_4;
+ case X86::JNO_1:
+ return (is16BitMode) ? X86::JNO_2 : X86::JNO_4;
+ case X86::JNP_1:
+ return (is16BitMode) ? X86::JNP_2 : X86::JNP_4;
+ case X86::JNS_1:
+ return (is16BitMode) ? X86::JNS_2 : X86::JNS_4;
+ case X86::JO_1:
+ return (is16BitMode) ? X86::JO_2 : X86::JO_4;
+ case X86::JP_1:
+ return (is16BitMode) ? X86::JP_2 : X86::JP_4;
+ case X86::JS_1:
+ return (is16BitMode) ? X86::JS_2 : X86::JS_4;
}
}
-static unsigned getRelaxedOpcodeArith(unsigned Op) {
+static unsigned getRelaxedOpcodeArith(const MCInst &Inst) {
+ unsigned Op = Inst.getOpcode();
switch (Op) {
default:
return Op;
@@ -246,20 +265,20 @@ static unsigned getRelaxedOpcodeArith(unsigned Op) {
}
}
-static unsigned getRelaxedOpcode(unsigned Op) {
- unsigned R = getRelaxedOpcodeArith(Op);
- if (R != Op)
+static unsigned getRelaxedOpcode(const MCInst &Inst, bool is16BitMode) {
+ unsigned R = getRelaxedOpcodeArith(Inst);
+ if (R != Inst.getOpcode())
return R;
- return getRelaxedOpcodeBranch(Op);
+ return getRelaxedOpcodeBranch(Inst, is16BitMode);
}
bool X86AsmBackend::mayNeedRelaxation(const MCInst &Inst) const {
- // Branches can always be relaxed.
- if (getRelaxedOpcodeBranch(Inst.getOpcode()) != Inst.getOpcode())
+ // Branches can always be relaxed in either mode.
+ if (getRelaxedOpcodeBranch(Inst, false) != Inst.getOpcode())
return true;
// Check if this instruction is ever relaxable.
- if (getRelaxedOpcodeArith(Inst.getOpcode()) == Inst.getOpcode())
+ if (getRelaxedOpcodeArith(Inst) == Inst.getOpcode())
return false;
@@ -282,9 +301,12 @@ bool X86AsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,
// FIXME: Can tblgen help at all here to verify there aren't other instructions
// we can relax?
-void X86AsmBackend::relaxInstruction(const MCInst &Inst, MCInst &Res) const {
+void X86AsmBackend::relaxInstruction(const MCInst &Inst,
+ const MCSubtargetInfo &STI,
+ MCInst &Res) const {
// The only relaxations X86 does is from a 1byte pcrel to a 4byte pcrel.
- unsigned RelaxedOp = getRelaxedOpcode(Inst.getOpcode());
+ bool is16BitMode = STI.getFeatureBits()[X86::Mode16Bit];
+ unsigned RelaxedOp = getRelaxedOpcode(Inst, is16BitMode);
if (RelaxedOp == Inst.getOpcode()) {
SmallString<256> Tmp;
diff --git a/test/MC/X86/x86-branch-relaxation.s b/test/MC/X86/x86-branch-relaxation.s
new file mode 100644
index 00000000000..870374e685f
--- /dev/null
+++ b/test/MC/X86/x86-branch-relaxation.s
@@ -0,0 +1,31 @@
+# RUN: llvm-mc -filetype=obj -triple=i386-unknown-unknown %s -o %t
+# RUN: llvm-objdump -r -D -section .text.bar -triple i386-unknown-unknown-code16 %t | FileCheck --check-prefix=CHECK16 %s
+# RUN: llvm-objdump -r -D -section .text.baz -triple i386-unknown-unknown %t | FileCheck --check-prefix=CHECK32 %s
+ .text
+ .section .text.foo,"",@progbits
+
+ .code16
+ .globl foo
+foo:
+ nop
+
+ .section .text.bar,"",@progbits
+ .globl bar16
+bar16:
+ jmp foo
+
+ .section .text.baz,"",@progbits
+ .code32
+ .globl baz32
+baz32:
+ jmp foo
+
+
+
+
+// CHECK16-LABEL: bar16
+// CHECK16-NEXT: e9 fe ff jmp -2 <bar16+0x1>
+// CHECK32-LABEL: baz32
+// CHECK32-NEXT: e9 fc ff ff ff jmp -4 <baz32+0x1>
+
+