(original) (raw)

diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index e8a9da1f17d96..7a4182701f47e 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(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 8c28d66597fb3..3a4b1e6fcf77f 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,bar, %eax +; STATIC-NEXT: addq bar,-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,bar, %eax +; MSTATIC-NEXT: addq bar,-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 }