[llvm] 570871e - [X86] Don't convert local function foo in the same section to foo(%rip) when the offset is near INT32_MIN
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 30 22:46:13 PDT 2024
Author: Fangrui Song
Date: 2024-09-30T22:46:08-07:00
New Revision: 570871eab530524e98781238a48897a881834211
URL: https://github.com/llvm/llvm-project/commit/570871eab530524e98781238a48897a881834211
DIFF: https://github.com/llvm/llvm-project/commit/570871eab530524e98781238a48897a881834211.diff
LOG: [X86] Don't convert local function foo in the same section to foo(%rip) when the offset is near INT32_MIN
```
define internal void @foo() {
ret void
}
define i64 @main() {
ret i64 add (i64 ptrtoint (ptr @foo to i64), i64 -2147483626)
}
```
When `foo` is a local symbol, `foo` and `main` are in the same section,
and `offset` is near INT32_MIN, referencing `foo+offset` in `main` with
RIP-relative addressing needs `leaq .text+offset1(%rip), %rax` where
`offset1 < offset`, and `offset1` might underflow.
(https://discourse.llvm.org/t/arithmetic-referencing-dso-local-function-causes-compilation-error-on-linux-x64/80033):
Don't use RIP-relative addressing if the negative offset is near
INT32_MIN. Arbitrarily reuse the magic number in isOffsetSuitableForCodeModel to
guard against the edge case when `address(current_instruction)-foo < 4GiB-16MiB`.
If the difference is larger than 4GiB-16MiB, `ret i64 add (i64 ptrtoint
(ptr @foo to i64), i64 -2**32+256MiB)` would still cause the assembly
issue, such cases are unrealistic.
Pull Request: https://github.com/llvm/llvm-project/pull/98438
Added:
Modified:
llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
llvm/test/CodeGen/X86/fold-add.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 564bfd63f3c276..70e4c199190d63 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -1975,6 +1975,16 @@ bool X86DAGToDAGISel::matchAddress(SDValue N, X86ISelAddressMode &AM) {
AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
AM.Base_Reg.getNode() == nullptr && AM.IndexReg.getNode() == nullptr &&
AM.SymbolFlags == X86II::MO_NO_FLAG && AM.hasSymbolicDisplacement()) {
+ // However, when GV is a local function symbol and in the same section as
+ // the current instruction, and AM.Disp is negative and near INT32_MIN,
+ // referencing GV+Disp generates a relocation referencing the section symbol
+ // with an even smaller offset, which might underflow. We should bail out if
+ // the negative offset is too close to INT32_MIN. Actually, we are more
+ // conservative here, using a smaller magic number also used by
+ // isOffsetSuitableForCodeModel.
+ if (isa_and_nonnull<Function>(AM.GV) && AM.Disp < -16 * 1024 * 1024)
+ return true;
+
AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
}
diff --git a/llvm/test/CodeGen/X86/fold-add.ll b/llvm/test/CodeGen/X86/fold-add.ll
index 8c28d66597fb3b..3a4b1e6fcf77f8 100644
--- a/llvm/test/CodeGen/X86/fold-add.ll
+++ b/llvm/test/CodeGen/X86/fold-add.ll
@@ -180,4 +180,71 @@ 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_0xfeffffff() #0 {
+; STATIC-LABEL: fun_neg_0xfeffffff:
+; STATIC: # %bb.0:
+; STATIC-NEXT: movl $bar, %eax
+; STATIC-NEXT: addq $-16777217, %rax # imm = 0xFEFFFFFF
+; STATIC-NEXT: retq
+;
+; PIC-LABEL: fun_neg_0xfeffffff:
+; PIC: # %bb.0:
+; PIC-NEXT: leaq bar-16777217(%rip), %rax
+; PIC-NEXT: retq
+;
+; MSTATIC-LABEL: fun_neg_0xfeffffff:
+; MSTATIC: # %bb.0:
+; MSTATIC-NEXT: movl $bar, %eax
+; MSTATIC-NEXT: addq $-16777217, %rax # imm = 0xFEFFFFFF
+; MSTATIC-NEXT: retq
+;
+; MPIC-LABEL: fun_neg_0xfeffffff:
+; MPIC: # %bb.0:
+; MPIC-NEXT: leaq bar-16777217(%rip), %rax
+; MPIC-NEXT: retq
+ ret i64 add (i64 ptrtoint (ptr @bar to i64), i64 -16777217)
+}
+
+define dso_local i64 @fun_neg_ff000000() #0 {
+; STATIC-LABEL: fun_neg_ff000000:
+; STATIC: # %bb.0:
+; STATIC-NEXT: leaq bar-16777216(%rip), %rax
+; STATIC-NEXT: retq
+;
+; PIC-LABEL: fun_neg_ff000000:
+; PIC: # %bb.0:
+; PIC-NEXT: leaq bar-16777216(%rip), %rax
+; PIC-NEXT: retq
+;
+; MSTATIC-LABEL: fun_neg_ff000000:
+; MSTATIC: # %bb.0:
+; MSTATIC-NEXT: leaq bar-16777216(%rip), %rax
+; MSTATIC-NEXT: retq
+;
+; MPIC-LABEL: fun_neg_ff000000:
+; MPIC: # %bb.0:
+; MPIC-NEXT: leaq bar-16777216(%rip), %rax
+; MPIC-NEXT: retq
+ ret i64 add (i64 ptrtoint (ptr @bar to i64), i64 -16777216)
+}
+
attributes #0 = { nounwind }
More information about the llvm-commits
mailing list