diff options
author | Nirav Dave <niravd@google.com> | 2016-07-11 14:23:53 +0000 |
---|---|---|
committer | Nirav Dave <niravd@google.com> | 2016-07-11 14:23:53 +0000 |
commit | 6b00c9f9a956644c9e85657e605be954e8d0fdf8 (patch) | |
tree | 3e305698d6320f14888c71822a0506dec2ffab86 | |
parent | 064f863be2287a44d993ff7400ac6ba5febb2c84 (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.h | 4 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 2 | ||||
-rw-r--r-- | lib/MC/MCObjectStreamer.cpp | 4 | ||||
-rw-r--r-- | lib/Target/AArch64/MCTargetDesc/AArch64AsmBackend.cpp | 4 | ||||
-rw-r--r-- | lib/Target/AMDGPU/MCTargetDesc/AMDGPUAsmBackend.cpp | 3 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 4 | ||||
-rw-r--r-- | lib/Target/ARM/MCTargetDesc/ARMAsmBackend.h | 3 | ||||
-rw-r--r-- | lib/Target/BPF/MCTargetDesc/BPFAsmBackend.cpp | 3 | ||||
-rw-r--r-- | lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp | 4 | ||||
-rw-r--r-- | lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp | 3 | ||||
-rw-r--r-- | lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h | 3 | ||||
-rw-r--r-- | lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp | 4 | ||||
-rw-r--r-- | lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp | 3 | ||||
-rw-r--r-- | lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp | 3 | ||||
-rw-r--r-- | lib/Target/WebAssembly/MCTargetDesc/WebAssemblyAsmBackend.cpp | 3 | ||||
-rw-r--r-- | lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 82 | ||||
-rw-r--r-- | test/MC/X86/x86-branch-relaxation.s | 31 |
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> + + |