[X86] Don't convert local function foo in the same section to foo(%rip) when the offset is near INT32_MIN by MaskRay · Pull Request #98438 · llvm/llvm-project (original) (raw)
@llvm/pr-subscribers-backend-x86
Author: Fangrui Song (MaskRay)
Changes
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 --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())
// 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) }return true;
+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@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 }