From 82be8a1d2b00f6e89096b86f670a8be894c7b9e6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Thomas=20K=C3=B6ppe?= Date: Wed, 28 Dec 2022 11:14:39 -0800 Subject: [PATCH] [X86] Emit RIP-relative access to local function in PIC medium code model Currently, the medium code model for x86_64 emits position-dependent relocations (R_X86_64_64) for local functions, regardless of PIC or no-PIC mode. (This means generically that code compiled with the medium model cannot be linked into a position-independent executable.) Example: ``` static int g(int n) { return 2 * n + 3; } void f(int(**p)(int)) { *p = g; } ``` This results in: ``` Disassembly of section .text: 0000000000000000 : 0: 48 b8 00 00 00 00 00 00 00 00 movabs rax, 0x0 a: 48 89 07 mov qword ptr [rdi], rax d: c3 ret ``` ``` Relocation section '.rela.text' at offset 0xf0 contains 1 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000002 0000000200000001 R_X86_64_64 0000000000000000 .text + 10 ``` This patch changes the behaviour to unconditionally emit a RIP-relative access, both in PIC and non-PIC mode. This fixes PIC mode, and is perhaps an improvement in non-PIC mode, too, since it results in a shorter instruction. A 32-bit relocation should suffice since the medium memory model demands that all code fit within 2GiB. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D140593 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 6 ++++++ llvm/test/CodeGen/X86/code-model-elf.ll | 8 ++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 119d96f..c0aeed8 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20493,6 +20493,12 @@ unsigned X86TargetLowering::getGlobalWrapperKind( (M == CodeModel::Small || M == CodeModel::Kernel)) return X86ISD::WrapperRIP; + // In the medium model, functions can always be referenced RIP-relatively, + // since they must be within 2GiB. This is also possible in non-PIC mode, and + // shorter than the 64-bit absolute immediate that would otherwise be emitted. + if (M == CodeModel::Medium && isa_and_nonnull(GV)) + return X86ISD::WrapperRIP; + // GOTPCREL references must always use RIP. if (OpFlags == X86II::MO_GOTPCREL || OpFlags == X86II::MO_GOTPCREL_NORELAX) return X86ISD::WrapperRIP; diff --git a/llvm/test/CodeGen/X86/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll index c3015f5..e727459 100644 --- a/llvm/test/CodeGen/X86/code-model-elf.ll +++ b/llvm/test/CodeGen/X86/code-model-elf.ll @@ -270,7 +270,7 @@ define dso_local ptr @lea_static_fn() #0 { ; ; MEDIUM-STATIC-LABEL: lea_static_fn: ; MEDIUM-STATIC: # %bb.0: -; MEDIUM-STATIC-NEXT: movabsq $static_fn, %rax +; MEDIUM-STATIC-NEXT: leaq static_fn(%rip), %rax ; MEDIUM-STATIC-NEXT: retq ; ; LARGE-STATIC-LABEL: lea_static_fn: @@ -285,7 +285,7 @@ define dso_local ptr @lea_static_fn() #0 { ; ; MEDIUM-PIC-LABEL: lea_static_fn: ; MEDIUM-PIC: # %bb.0: -; MEDIUM-PIC-NEXT: movabsq $static_fn, %rax +; MEDIUM-PIC-NEXT: leaq static_fn(%rip), %rax ; MEDIUM-PIC-NEXT: retq ; ; LARGE-PIC-LABEL: lea_static_fn: @@ -308,7 +308,7 @@ define dso_local ptr @lea_global_fn() #0 { ; ; MEDIUM-STATIC-LABEL: lea_global_fn: ; MEDIUM-STATIC: # %bb.0: -; MEDIUM-STATIC-NEXT: movabsq $global_fn, %rax +; MEDIUM-STATIC-NEXT: leaq global_fn(%rip), %rax ; MEDIUM-STATIC-NEXT: retq ; ; LARGE-STATIC-LABEL: lea_global_fn: @@ -323,7 +323,7 @@ define dso_local ptr @lea_global_fn() #0 { ; ; MEDIUM-PIC-LABEL: lea_global_fn: ; MEDIUM-PIC: # %bb.0: -; MEDIUM-PIC-NEXT: movabsq $global_fn, %rax +; MEDIUM-PIC-NEXT: leaq global_fn(%rip), %rax ; MEDIUM-PIC-NEXT: retq ; ; LARGE-PIC-LABEL: lea_global_fn: -- 2.7.4