[llvm] [X86] Don't fold offsets that are too closer to INT32_MIN in non-large code models (PR #98438)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 10 23:40:23 PDT 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Fangrui Song (MaskRay)

<details>
<summary>Changes</summary>

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.


---
Full diff: https://github.com/llvm/llvm-project/pull/98438.diff


2 Files Affected:

- (modified) llvm/lib/Target/X86/X86ISelDAGToDAG.cpp (+7) 
- (modified) llvm/test/CodeGen/X86/fold-add.ll (+96-2) 


``````````diff
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 }

``````````

</details>


https://github.com/llvm/llvm-project/pull/98438


More information about the llvm-commits mailing list