diff options
author | Arthur Eubanks <aeubanks@google.com> | 2023-12-21 10:40:56 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-21 10:40:56 -0800 |
commit | 2366d53d8d8726b73408597b534d2f910c3d3e6d (patch) | |
tree | 942d4a3c21945f6573025c2780ad8e4e8b7baa95 | |
parent | 7bd17212ef23a72ea224a037126d33d3e02553fe (diff) | |
download | llvm-2366d53d8d8726b73408597b534d2f910c3d3e6d.zip llvm-2366d53d8d8726b73408597b534d2f910c3d3e6d.tar.gz llvm-2366d53d8d8726b73408597b534d2f910c3d3e6d.tar.bz2 |
[X86] Fix more medium code model addressing modes (#75641)
By looking at whether a global is large instead of looking at the code
model.
This also fixes references to large data in the small code model.
We now always fold any 32-bit offset into the addressing mode with the
large code model since it uses 64-bit relocations.
-rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 29 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/code-model-elf.ll | 66 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/fast-isel-large-object.ll | 5 | ||||
-rw-r--r-- | llvm/test/CodeGen/X86/fold-add.ll | 3 |
5 files changed, 68 insertions, 66 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 7ec59c7..77a9975 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -1828,9 +1828,7 @@ bool X86DAGToDAGISel::matchWrapper(SDValue N, X86ISelAddressMode &AM) { // That signifies access to globals that are known to be "near", // such as the GOT itself. CodeModel::Model M = TM.getCodeModel(); - if (Subtarget->is64Bit() && - ((M == CodeModel::Large && !IsRIPRelTLS) || - (M == CodeModel::Medium && !IsRIPRel))) + if (Subtarget->is64Bit() && M == CodeModel::Large && !IsRIPRelTLS) return true; // Base and index reg must be 0 in order to use %rip as base. @@ -1866,6 +1864,13 @@ bool X86DAGToDAGISel::matchWrapper(SDValue N, X86ISelAddressMode &AM) { } else llvm_unreachable("Unhandled symbol reference node."); + // Can't use an addressing mode with large globals. + if (Subtarget->is64Bit() && !IsRIPRel && AM.GV && + TM.isLargeGlobalValue(AM.GV)) { + AM = Backup; + return true; + } + if (foldOffsetIntoAddress(Offset, AM)) { AM = Backup; return true; @@ -1910,20 +1915,12 @@ bool X86DAGToDAGISel::matchAddress(SDValue N, X86ISelAddressMode &AM) { // Post-processing: Convert foo to foo(%rip), even in non-PIC mode, // because it has a smaller encoding. - // TODO: Which other code models can use this? - switch (TM.getCodeModel()) { - default: break; - case CodeModel::Small: - case CodeModel::Kernel: - if (Subtarget->is64Bit() && - AM.Scale == 1 && - AM.BaseType == X86ISelAddressMode::RegBase && - AM.Base_Reg.getNode() == nullptr && - AM.IndexReg.getNode() == nullptr && - AM.SymbolFlags == X86II::MO_NO_FLAG && - AM.hasSymbolicDisplacement()) - AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64); - break; + if (TM.getCodeModel() != CodeModel::Large && + (!AM.GV || !TM.isLargeGlobalValue(AM.GV)) && Subtarget->is64Bit() && + AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase && + AM.Base_Reg.getNode() == nullptr && AM.IndexReg.getNode() == nullptr && + AM.SymbolFlags == X86II::MO_NO_FLAG && AM.hasSymbolicDisplacement()) { + AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64); } return false; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index db5e4fe..4911286 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -2674,34 +2674,33 @@ SDValue X86TargetLowering::getReturnAddressFrameIndex(SelectionDAG &DAG) const { return DAG.getFrameIndex(ReturnAddrIndex, getPointerTy(DAG.getDataLayout())); } -bool X86::isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, - bool hasSymbolicDisplacement) { +bool X86::isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model CM, + bool HasSymbolicDisplacement) { // Offset should fit into 32 bit immediate field. if (!isInt<32>(Offset)) return false; // If we don't have a symbolic displacement - we don't have any extra // restrictions. - if (!hasSymbolicDisplacement) + if (!HasSymbolicDisplacement) return true; - // FIXME: Some tweaks might be needed for medium code model. - if (M != CodeModel::Small && M != CodeModel::Kernel) - return false; - - // For small code model we assume that latest object is 16MB before end of 31 - // bits boundary. We may also accept pretty large negative constants knowing - // that all objects are in the positive half of address space. - if (M == CodeModel::Small && Offset < 16*1024*1024) + // We can fold large offsets in the large code model because we always use + // 64-bit offsets. + if (CM == CodeModel::Large) return true; // For kernel code model we know that all object resist in the negative half // of 32bits address space. We may not accept negative offsets, since they may // be just off and we may accept pretty large positive ones. - if (M == CodeModel::Kernel && Offset >= 0) - return true; - - return false; + if (CM == CodeModel::Kernel) + return Offset >= 0; + + // For other non-large code models we assume that latest small object is 16MB + // before end of 31 bits boundary. We may also accept pretty large negative + // constants knowing that all objects are in the positive half of address + // space. + return Offset < 16 * 1024 * 1024; } /// Return true if the condition is an signed comparison operation. diff --git a/llvm/test/CodeGen/X86/code-model-elf.ll b/llvm/test/CodeGen/X86/code-model-elf.ll index 6112f2a..afcffb3 100644 --- a/llvm/test/CodeGen/X86/code-model-elf.ll +++ b/llvm/test/CodeGen/X86/code-model-elf.ll @@ -11,6 +11,16 @@ ; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-PIC ; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large -large-data-threshold=1000 | FileCheck %s --check-prefix=CHECK --check-prefix=LARGE-SMALL-DATA-PIC +; Check that the relocations we emit are valid. +; RUN: llc -verify-machineinstrs < %s -relocation-model=static -code-model=small -filetype=obj -o /dev/null +; RUN: llc -verify-machineinstrs < %s -relocation-model=static -code-model=medium -filetype=obj -o /dev/null +; RUN: llc -verify-machineinstrs < %s -relocation-model=static -code-model=large -filetype=obj -o /dev/null +; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=small -filetype=obj -o /dev/null +; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium -large-data-threshold=1000 -filetype=obj -o /dev/null +; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=medium -filetype=obj -o /dev/null +; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large -filetype=obj -o /dev/null +; RUN: llc -verify-machineinstrs < %s -relocation-model=pic -code-model=large -large-data-threshold=1000 -filetype=obj -o /dev/null + ; Generated from this C source: ; ; static int static_data[10]; @@ -376,7 +386,6 @@ define dso_local ptr @lea_forced_small_data() #0 { ret ptr @forced_small_data } -; TODO: make small and medium instruction sequence the same define dso_local i32 @load_forced_small_data() #0 { ; SMALL-STATIC-LABEL: load_forced_small_data: ; SMALL-STATIC: # %bb.0: @@ -385,14 +394,13 @@ define dso_local i32 @load_forced_small_data() #0 { ; ; MEDIUM-STATIC-LABEL: load_forced_small_data: ; MEDIUM-STATIC: # %bb.0: -; MEDIUM-STATIC-NEXT: movl $forced_small_data, %eax -; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax +; MEDIUM-STATIC-NEXT: movl forced_small_data+8(%rip), %eax ; MEDIUM-STATIC-NEXT: retq ; ; LARGE-STATIC-LABEL: load_forced_small_data: ; LARGE-STATIC: # %bb.0: -; LARGE-STATIC-NEXT: movl $forced_small_data, %eax -; LARGE-STATIC-NEXT: movl 8(%rax), %eax +; LARGE-STATIC-NEXT: movl $forced_small_data+8, %eax +; LARGE-STATIC-NEXT: movl (%rax), %eax ; LARGE-STATIC-NEXT: retq ; ; SMALL-PIC-LABEL: load_forced_small_data: @@ -402,14 +410,12 @@ define dso_local i32 @load_forced_small_data() #0 { ; ; MEDIUM-SMALL-DATA-PIC-LABEL: load_forced_small_data: ; MEDIUM-SMALL-DATA-PIC: # %bb.0: -; MEDIUM-SMALL-DATA-PIC-NEXT: leaq forced_small_data(%rip), %rax -; MEDIUM-SMALL-DATA-PIC-NEXT: movl 8(%rax), %eax +; MEDIUM-SMALL-DATA-PIC-NEXT: movl forced_small_data+8(%rip), %eax ; MEDIUM-SMALL-DATA-PIC-NEXT: retq ; ; MEDIUM-PIC-LABEL: load_forced_small_data: ; MEDIUM-PIC: # %bb.0: -; MEDIUM-PIC-NEXT: leaq forced_small_data(%rip), %rax -; MEDIUM-PIC-NEXT: movl 8(%rax), %eax +; MEDIUM-PIC-NEXT: movl forced_small_data+8(%rip), %eax ; MEDIUM-PIC-NEXT: retq ; ; LARGE-PIC-LABEL: load_forced_small_data: @@ -435,7 +441,6 @@ define dso_local i32 @load_forced_small_data() #0 { ret i32 %rv } -; TODO: fix small code model instruction sequences to use 64-bit constants define dso_local ptr @lea_forced_large_data() #0 { ; SMALL-STATIC-LABEL: lea_forced_large_data: ; SMALL-STATIC: # %bb.0: @@ -454,8 +459,9 @@ define dso_local ptr @lea_forced_large_data() #0 { ; ; SMALL-PIC-LABEL: lea_forced_large_data: ; SMALL-PIC: # %bb.0: -; SMALL-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax -; SMALL-PIC-NEXT: leaq forced_large_data@GOTOFF(%rax), %rax +; SMALL-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx +; SMALL-PIC-NEXT: movabsq $forced_large_data@GOTOFF, %rax +; SMALL-PIC-NEXT: addq %rcx, %rax ; SMALL-PIC-NEXT: retq ; ; MEDIUM-SMALL-DATA-PIC-LABEL: lea_forced_large_data: @@ -497,25 +503,27 @@ define dso_local ptr @lea_forced_large_data() #0 { define dso_local i32 @load_forced_large_data() #0 { ; SMALL-STATIC-LABEL: load_forced_large_data: ; SMALL-STATIC: # %bb.0: -; SMALL-STATIC-NEXT: movl forced_large_data+8(%rip), %eax +; SMALL-STATIC-NEXT: movabsq $forced_large_data+8, %rax +; SMALL-STATIC-NEXT: movl (%rax), %eax ; SMALL-STATIC-NEXT: retq ; ; MEDIUM-STATIC-LABEL: load_forced_large_data: ; MEDIUM-STATIC: # %bb.0: -; MEDIUM-STATIC-NEXT: movabsq $forced_large_data, %rax -; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax +; MEDIUM-STATIC-NEXT: movabsq $forced_large_data+8, %rax +; MEDIUM-STATIC-NEXT: movl (%rax), %eax ; MEDIUM-STATIC-NEXT: retq ; ; LARGE-STATIC-LABEL: load_forced_large_data: ; LARGE-STATIC: # %bb.0: -; LARGE-STATIC-NEXT: movabsq $forced_large_data, %rax -; LARGE-STATIC-NEXT: movl 8(%rax), %eax +; LARGE-STATIC-NEXT: movabsq $forced_large_data+8, %rax +; LARGE-STATIC-NEXT: movl (%rax), %eax ; LARGE-STATIC-NEXT: retq ; ; SMALL-PIC-LABEL: load_forced_large_data: ; SMALL-PIC: # %bb.0: ; SMALL-PIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax -; SMALL-PIC-NEXT: movl forced_large_data@GOTOFF+8(%rax), %eax +; SMALL-PIC-NEXT: movabsq $forced_large_data@GOTOFF, %rcx +; SMALL-PIC-NEXT: movl 8(%rax,%rcx), %eax ; SMALL-PIC-NEXT: retq ; ; MEDIUM-SMALL-DATA-PIC-LABEL: load_forced_large_data: @@ -563,14 +571,14 @@ define dso_local i32 @load_global_data() #0 { ; ; MEDIUM-STATIC-LABEL: load_global_data: ; MEDIUM-STATIC: # %bb.0: -; MEDIUM-STATIC-NEXT: movabsq $global_data, %rax -; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax +; MEDIUM-STATIC-NEXT: movabsq $global_data+8, %rax +; MEDIUM-STATIC-NEXT: movl (%rax), %eax ; MEDIUM-STATIC-NEXT: retq ; ; LARGE-STATIC-LABEL: load_global_data: ; LARGE-STATIC: # %bb.0: -; LARGE-STATIC-NEXT: movabsq $global_data, %rax -; LARGE-STATIC-NEXT: movl 8(%rax), %eax +; LARGE-STATIC-NEXT: movabsq $global_data+8, %rax +; LARGE-STATIC-NEXT: movl (%rax), %eax ; LARGE-STATIC-NEXT: retq ; ; SMALL-PIC-LABEL: load_global_data: @@ -580,8 +588,7 @@ define dso_local i32 @load_global_data() #0 { ; ; 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: movl global_data+8(%rip), %eax ; MEDIUM-SMALL-DATA-PIC-NEXT: retq ; ; MEDIUM-PIC-LABEL: load_global_data: @@ -684,14 +691,14 @@ define dso_local i32 @load_unknown_size_data() #0 { ; ; MEDIUM-STATIC-LABEL: load_unknown_size_data: ; MEDIUM-STATIC: # %bb.0: -; MEDIUM-STATIC-NEXT: movabsq $unknown_size_data, %rax -; MEDIUM-STATIC-NEXT: movl 8(%rax), %eax +; MEDIUM-STATIC-NEXT: movabsq $unknown_size_data+8, %rax +; MEDIUM-STATIC-NEXT: movl (%rax), %eax ; MEDIUM-STATIC-NEXT: retq ; ; LARGE-STATIC-LABEL: load_unknown_size_data: ; LARGE-STATIC: # %bb.0: -; LARGE-STATIC-NEXT: movabsq $unknown_size_data, %rax -; LARGE-STATIC-NEXT: movl 8(%rax), %eax +; LARGE-STATIC-NEXT: movabsq $unknown_size_data+8, %rax +; LARGE-STATIC-NEXT: movl (%rax), %eax ; LARGE-STATIC-NEXT: retq ; ; SMALL-PIC-LABEL: load_unknown_size_data: @@ -1127,8 +1134,7 @@ define dso_local float @load_constant_pool(float %x) #0 { ; ; MEDIUM-STATIC-LABEL: load_constant_pool: ; MEDIUM-STATIC: # %bb.0: -; MEDIUM-STATIC-NEXT: movl ${{\.?LCPI[0-9]+_[0-9]+}}, %eax -; MEDIUM-STATIC-NEXT: addss (%rax), %xmm0 +; MEDIUM-STATIC-NEXT: addss {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0 ; MEDIUM-STATIC-NEXT: retq ; ; LARGE-STATIC-LABEL: load_constant_pool: diff --git a/llvm/test/CodeGen/X86/fast-isel-large-object.ll b/llvm/test/CodeGen/X86/fast-isel-large-object.ll index 6ca2c42..9acdfde 100644 --- a/llvm/test/CodeGen/X86/fast-isel-large-object.ll +++ b/llvm/test/CodeGen/X86/fast-isel-large-object.ll @@ -6,8 +6,9 @@ define ptr @f() { ; CHECK-LABEL: f: ; CHECK: # %bb.0: -; CHECK-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax -; CHECK-NEXT: leaq g@GOTOFF(%rax), %rax +; CHECK-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rcx +; CHECK-NEXT: movabsq $g@GOTOFF, %rax +; CHECK-NEXT: addq %rcx, %rax ; CHECK-NEXT: retq ret ptr @g } diff --git a/llvm/test/CodeGen/X86/fold-add.ll b/llvm/test/CodeGen/X86/fold-add.ll index 597e51d..8c28d66 100644 --- a/llvm/test/CodeGen/X86/fold-add.ll +++ b/llvm/test/CodeGen/X86/fold-add.ll @@ -45,8 +45,7 @@ define dso_local i64 @one() #0 { ; ; MSTATIC-LABEL: one: ; MSTATIC: # %bb.0: # %entry -; MSTATIC-NEXT: movabsq $foo, %rax -; MSTATIC-NEXT: incq %rax +; MSTATIC-NEXT: movabsq $foo+1, %rax ; MSTATIC-NEXT: retq ; ; MPIC-LABEL: one: |