diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -20826,7 +20826,12 @@ // 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)) + // For PIC global variables, MO_NO_FLAG also means it can be referenced + // RIP-relatively, e.g. for data smaller than the large data threshold. + if (M == CodeModel::Medium && + (isa_and_nonnull(GV) || + (GV != nullptr && OpFlags == X86II::MO_NO_FLAG && + Subtarget.isPICStyleRIPRel()))) return X86ISD::WrapperRIP; // GOTPCREL references must always use RIP. diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp --- a/llvm/lib/Target/X86/X86Subtarget.cpp +++ b/llvm/lib/Target/X86/X86Subtarget.cpp @@ -95,12 +95,17 @@ case CodeModel::Large: return X86II::MO_GOTOFF; - // Medium is a hybrid: RIP-rel for code, GOTOFF for DSO local data. + // Medium is a hybrid: RIP-rel for code and non-large data, GOTOFF for + // remaining DSO local data. case CodeModel::Medium: // Constant pool and jump table handling pass a nullptr to this // function so we need to use isa_and_nonnull. if (isa_and_nonnull(GV)) return X86II::MO_NO_FLAG; // All code is RIP-relative + if (auto *GVar = dyn_cast_or_null(GV)) { + if (!TM.isLargeData(GVar)) + return X86II::MO_NO_FLAG; + } return X86II::MO_GOTOFF; // Local symbols use GOTOFF. } llvm_unreachable("invalid code model"); diff --git a/llvm/test/CodeGen/X86/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll --- a/llvm/test/CodeGen/X86/code-model-elf.ll +++ b/llvm/test/CodeGen/X86/code-model-elf.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --no_x86_scrub_sp ; Run with --no_x86_scrub_rip because we care a lot about how globals are ; accessed in the code model. @@ -6,9 +6,12 @@ ; RUN: llc -verify-machineinstrs < %s -relocation-model=static -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-STATIC ; RUN: llc -verify-machineinstrs < %s -relocation-model=static -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-STATIC ; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=small | FileCheck %s --check-prefix=CHECK --check-prefix=SMALL-PIC +; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium -large-data-threshold=1000 | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-SMALL-DATA-PIC ; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium | FileCheck %s --check-prefix=CHECK --check-prefix=MEDIUM-PIC ; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC +; FIXME: small pic and medium pic w/ big enough large data threshold should be equivalent + ; Generated from this C source: ; ; static int static_data[10]; @@ -61,6 +64,11 @@ ; SMALL-PIC-NEXT: leaq static_data(%rip), %rax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: lea_static_data: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: leaq static_data(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: lea_static_data: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx @@ -101,6 +109,11 @@ ; SMALL-PIC-NEXT: leaq global_data(%rip), %rax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: lea_global_data: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: leaq global_data(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: lea_global_data: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx @@ -141,6 +154,11 @@ ; SMALL-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: lea_extern_data: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: lea_extern_data: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax @@ -181,6 +199,12 @@ ; SMALL-PIC-NEXT: movl global_data+8(%rip), %eax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: load_global_data: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: leaq global_data(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: movl 8(%rax), %eax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: load_global_data: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax @@ -226,6 +250,12 @@ ; SMALL-PIC-NEXT: movl 8(%rax), %eax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: load_extern_data: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: movl 8(%rax), %eax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: load_extern_data: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: movq extern_data@GOTPCREL(%rip), %rax @@ -283,6 +313,11 @@ ; SMALL-PIC-NEXT: leaq static_fn(%rip), %rax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: lea_static_fn: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: leaq static_fn(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: lea_static_fn: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: leaq static_fn(%rip), %rax @@ -321,6 +356,11 @@ ; SMALL-PIC-NEXT: leaq global_fn(%rip), %rax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: lea_global_fn: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: leaq global_fn(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: lea_global_fn: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: leaq global_fn(%rip), %rax @@ -359,6 +399,11 @@ ; SMALL-PIC-NEXT: movq extern_fn@GOTPCREL(%rip), %rax ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: lea_extern_fn: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: movq extern_fn@GOTPCREL(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: lea_extern_fn: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: movq extern_fn@GOTPCREL(%rip), %rax @@ -432,6 +477,13 @@ ; SMALL-PIC-NEXT: addss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; SMALL-PIC-NEXT: retq ; +; MEDIUM-SMALL-DATA-PIC-LABEL: load_constant_pool: +; MEDIUM-SMALL-DATA-PIC: # %bb.0: +; MEDIUM-SMALL-DATA-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax +; MEDIUM-SMALL-DATA-PIC-NEXT: movabsq ${{\.?LCPI[0-9]+_[0-9]+}}@GOTOFF, %rcx +; MEDIUM-SMALL-DATA-PIC-NEXT: addss (%rax,%rcx), %xmm0 +; MEDIUM-SMALL-DATA-PIC-NEXT: retq +; ; MEDIUM-PIC-LABEL: load_constant_pool: ; MEDIUM-PIC: # %bb.0: ; MEDIUM-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax