[llvm] [X86] Don't fold offsets that are too closer to INT32_MIN in non-large code models (PR #98438)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 10 23:39:50 PDT 2024
https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/98438
When `Sym` is a local function symbol, `leaq Sym+Offset(%rip), %rax` in
non-large code models generates a relocation that references the section
symbol. An offset that is too closer to INT32_MIN could cause an
underflow addend (https://discourse.llvm.org/t/arithmetic-referencing-dso-local-function-causes-compilation-error-on-linux-x64/80033):
```
leaq Sym-0x80000000(%rip), %rax
=>
leaq .text-0x80000001(%rip), %rax # if Sym=.text+1
```
Don't fold such offsets. For simplicity, we don't check whether Sym is a
function symbol.
>From 698da3bebcb2e78d258f96ea7f3feb07c06f040e Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 10 Jul 2024 23:39:41 -0700
Subject: [PATCH] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20initia?=
=?UTF-8?q?l=20version?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5-bogner
---
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 7 ++
llvm/test/CodeGen/X86/fold-add.ll | 98 ++++++++++++++++++++++++-
2 files changed, 103 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index c91bd576dc9f6..e06de1c4276a3 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -1795,6 +1795,13 @@ bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t Offset,
!X86::isOffsetSuitableForCodeModel(Val, M,
AM.hasSymbolicDisplacement()))
return true;
+ // When Sym is a local symbol in ELF, leaq Sym+Offset(%rip) in non-large
+ // code models generates a relocation referencing the section symbol. Don't
+ // fold offsets that are too closer to INT32_MIN, as the addend could
+ // underflow.
+ if (Val < INT32_MIN + 256 * 1024 * 1024 && M != CodeModel::Large &&
+ AM.hasSymbolicDisplacement())
+ return true;
// In addition to the checks required for a register base, check that
// we do not try to use an unsafe Disp with a frame index.
if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
diff --git a/llvm/test/CodeGen/X86/fold-add.ll b/llvm/test/CodeGen/X86/fold-add.ll
index 8c28d66597fb3..f7659c9cf0653 100644
--- a/llvm/test/CodeGen/X86/fold-add.ll
+++ b/llvm/test/CodeGen/X86/fold-add.ll
@@ -118,17 +118,46 @@ entry:
ret i64 add (i64 ptrtoint (ptr @foo to i64), i64 -1)
}
+define dso_local i64 @neg_0x70000000() #0 {
+; STATIC-LABEL: neg_0x70000000:
+; STATIC: # %bb.0: # %entry
+; STATIC-NEXT: leaq foo-1879048192(%rip), %rax
+; STATIC-NEXT: retq
+;
+; PIC-LABEL: neg_0x70000000:
+; PIC: # %bb.0: # %entry
+; PIC-NEXT: leaq foo-1879048192(%rip), %rax
+; PIC-NEXT: retq
+;
+; MSTATIC-LABEL: neg_0x70000000:
+; MSTATIC: # %bb.0: # %entry
+; MSTATIC-NEXT: movabsq $foo, %rax
+; MSTATIC-NEXT: addq $-1879048192, %rax # imm = 0x90000000
+; MSTATIC-NEXT: retq
+;
+; MPIC-LABEL: neg_0x70000000:
+; MPIC: # %bb.0: # %entry
+; MPIC-NEXT: leaq _GLOBAL_OFFSET_TABLE_(%rip), %rax
+; MPIC-NEXT: movabsq $foo at GOTOFF, %rcx
+; MPIC-NEXT: leaq -1879048192(%rax,%rcx), %rax
+; MPIC-NEXT: retq
+entry:
+ ret i64 add (i64 ptrtoint (ptr @foo to i64), i64 -1879048192)
+}
+
;; Test we don't emit movl foo-2147483648, %eax. ELF R_X86_64_32 does not allow
;; a negative value.
define dso_local i64 @neg_0x80000000() #0 {
; STATIC-LABEL: neg_0x80000000:
; STATIC: # %bb.0: # %entry
-; STATIC-NEXT: leaq foo-2147483648(%rip), %rax
+; STATIC-NEXT: movq $-2147483648, %rax # imm = 0x80000000
+; STATIC-NEXT: leaq foo(%rax), %rax
; STATIC-NEXT: retq
;
; PIC-LABEL: neg_0x80000000:
; PIC: # %bb.0: # %entry
-; PIC-NEXT: leaq foo-2147483648(%rip), %rax
+; PIC-NEXT: leaq foo(%rip), %rax
+; PIC-NEXT: addq $-2147483648, %rax # imm = 0x80000000
; PIC-NEXT: retq
;
; MSTATIC-LABEL: neg_0x80000000:
@@ -180,4 +209,69 @@ entry:
ret i64 add (i64 ptrtoint (ptr @foo to i64), i64 -2147483649)
}
+define internal void @bar() #0 {
+; STATIC-LABEL: bar:
+; STATIC: # %bb.0:
+; STATIC-NEXT: retq
+;
+; PIC-LABEL: bar:
+; PIC: # %bb.0:
+; PIC-NEXT: retq
+;
+; MSTATIC-LABEL: bar:
+; MSTATIC: # %bb.0:
+; MSTATIC-NEXT: retq
+;
+; MPIC-LABEL: bar:
+; MPIC: # %bb.0:
+; MPIC-NEXT: retq
+ ret void
+}
+
+define dso_local i64 @fun_neg_0x6fffffff() #0 {
+; STATIC-LABEL: fun_neg_0x6fffffff:
+; STATIC: # %bb.0:
+; STATIC-NEXT: leaq bar-1879048191(%rip), %rax
+; STATIC-NEXT: retq
+;
+; PIC-LABEL: fun_neg_0x6fffffff:
+; PIC: # %bb.0:
+; PIC-NEXT: leaq bar-1879048191(%rip), %rax
+; PIC-NEXT: retq
+;
+; MSTATIC-LABEL: fun_neg_0x6fffffff:
+; MSTATIC: # %bb.0:
+; MSTATIC-NEXT: leaq bar-1879048191(%rip), %rax
+; MSTATIC-NEXT: retq
+;
+; MPIC-LABEL: fun_neg_0x6fffffff:
+; MPIC: # %bb.0:
+; MPIC-NEXT: leaq bar-1879048191(%rip), %rax
+; MPIC-NEXT: retq
+ ret i64 add (i64 ptrtoint (ptr @bar to i64), i64 -1879048191)
+}
+
+define dso_local i64 @fun_neg_0x70000000() #0 {
+; STATIC-LABEL: fun_neg_0x70000000:
+; STATIC: # %bb.0:
+; STATIC-NEXT: leaq bar-1879048192(%rip), %rax
+; STATIC-NEXT: retq
+;
+; PIC-LABEL: fun_neg_0x70000000:
+; PIC: # %bb.0:
+; PIC-NEXT: leaq bar-1879048192(%rip), %rax
+; PIC-NEXT: retq
+;
+; MSTATIC-LABEL: fun_neg_0x70000000:
+; MSTATIC: # %bb.0:
+; MSTATIC-NEXT: leaq bar-1879048192(%rip), %rax
+; MSTATIC-NEXT: retq
+;
+; MPIC-LABEL: fun_neg_0x70000000:
+; MPIC: # %bb.0:
+; MPIC-NEXT: leaq bar-1879048192(%rip), %rax
+; MPIC-NEXT: retq
+ ret i64 add (i64 ptrtoint (ptr @bar to i64), i64 -1879048192)
+}
+
attributes #0 = { nounwind }
More information about the llvm-commits
mailing list