aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur Eubanks <aeubanks@google.com>2023-12-21 10:40:56 -0800
committerGitHub <noreply@github.com>2023-12-21 10:40:56 -0800
commit2366d53d8d8726b73408597b534d2f910c3d3e6d (patch)
tree942d4a3c21945f6573025c2780ad8e4e8b7baa95
parent7bd17212ef23a72ea224a037126d33d3e02553fe (diff)
downloadllvm-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.cpp31
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp29
-rw-r--r--llvm/test/CodeGen/X86/code-model-elf.ll66
-rw-r--r--llvm/test/CodeGen/X86/fast-isel-large-object.ll5
-rw-r--r--llvm/test/CodeGen/X86/fold-add.ll3
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: