Skip to content

Commit 570871e

Browse files
authored
[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: #98438
1 parent eea5e7e commit 570871e

File tree

2 files changed

+77
-0
lines changed

2 files changed

+77
-0
lines changed

llvm/lib/Target/X86/X86ISelDAGToDAG.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,6 +1975,16 @@ bool X86DAGToDAGISel::matchAddress(SDValue N, X86ISelAddressMode &AM) {
19751975
AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
19761976
AM.Base_Reg.getNode() == nullptr && AM.IndexReg.getNode() == nullptr &&
19771977
AM.SymbolFlags == X86II::MO_NO_FLAG && AM.hasSymbolicDisplacement()) {
1978+
// However, when GV is a local function symbol and in the same section as
1979+
// the current instruction, and AM.Disp is negative and near INT32_MIN,
1980+
// referencing GV+Disp generates a relocation referencing the section symbol
1981+
// with an even smaller offset, which might underflow. We should bail out if
1982+
// the negative offset is too close to INT32_MIN. Actually, we are more
1983+
// conservative here, using a smaller magic number also used by
1984+
// isOffsetSuitableForCodeModel.
1985+
if (isa_and_nonnull<Function>(AM.GV) && AM.Disp < -16 * 1024 * 1024)
1986+
return true;
1987+
19781988
AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
19791989
}
19801990

llvm/test/CodeGen/X86/fold-add.ll

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,4 +180,71 @@ entry:
180180
ret i64 add (i64 ptrtoint (ptr @foo to i64), i64 -2147483649)
181181
}
182182

183+
define internal void @bar() #0 {
184+
; STATIC-LABEL: bar:
185+
; STATIC: # %bb.0:
186+
; STATIC-NEXT: retq
187+
;
188+
; PIC-LABEL: bar:
189+
; PIC: # %bb.0:
190+
; PIC-NEXT: retq
191+
;
192+
; MSTATIC-LABEL: bar:
193+
; MSTATIC: # %bb.0:
194+
; MSTATIC-NEXT: retq
195+
;
196+
; MPIC-LABEL: bar:
197+
; MPIC: # %bb.0:
198+
; MPIC-NEXT: retq
199+
ret void
200+
}
201+
202+
define dso_local i64 @fun_neg_0xfeffffff() #0 {
203+
; STATIC-LABEL: fun_neg_0xfeffffff:
204+
; STATIC: # %bb.0:
205+
; STATIC-NEXT: movl $bar, %eax
206+
; STATIC-NEXT: addq $-16777217, %rax # imm = 0xFEFFFFFF
207+
; STATIC-NEXT: retq
208+
;
209+
; PIC-LABEL: fun_neg_0xfeffffff:
210+
; PIC: # %bb.0:
211+
; PIC-NEXT: leaq bar-16777217(%rip), %rax
212+
; PIC-NEXT: retq
213+
;
214+
; MSTATIC-LABEL: fun_neg_0xfeffffff:
215+
; MSTATIC: # %bb.0:
216+
; MSTATIC-NEXT: movl $bar, %eax
217+
; MSTATIC-NEXT: addq $-16777217, %rax # imm = 0xFEFFFFFF
218+
; MSTATIC-NEXT: retq
219+
;
220+
; MPIC-LABEL: fun_neg_0xfeffffff:
221+
; MPIC: # %bb.0:
222+
; MPIC-NEXT: leaq bar-16777217(%rip), %rax
223+
; MPIC-NEXT: retq
224+
ret i64 add (i64 ptrtoint (ptr @bar to i64), i64 -16777217)
225+
}
226+
227+
define dso_local i64 @fun_neg_ff000000() #0 {
228+
; STATIC-LABEL: fun_neg_ff000000:
229+
; STATIC: # %bb.0:
230+
; STATIC-NEXT: leaq bar-16777216(%rip), %rax
231+
; STATIC-NEXT: retq
232+
;
233+
; PIC-LABEL: fun_neg_ff000000:
234+
; PIC: # %bb.0:
235+
; PIC-NEXT: leaq bar-16777216(%rip), %rax
236+
; PIC-NEXT: retq
237+
;
238+
; MSTATIC-LABEL: fun_neg_ff000000:
239+
; MSTATIC: # %bb.0:
240+
; MSTATIC-NEXT: leaq bar-16777216(%rip), %rax
241+
; MSTATIC-NEXT: retq
242+
;
243+
; MPIC-LABEL: fun_neg_ff000000:
244+
; MPIC: # %bb.0:
245+
; MPIC-NEXT: leaq bar-16777216(%rip), %rax
246+
; MPIC-NEXT: retq
247+
ret i64 add (i64 ptrtoint (ptr @bar to i64), i64 -16777216)
248+
}
249+
183250
attributes #0 = { nounwind }

0 commit comments

Comments
 (0)