diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -646,10 +646,25 @@ return false; // Relative pointers do not need to be dynamically relocated. - if (auto *LHSGV = dyn_cast(LHSOp0->stripPointerCasts())) - if (auto *RHSGV = dyn_cast(RHSOp0->stripPointerCasts())) + if (auto *LHSGV = + dyn_cast(LHSOp0->stripInBoundsConstantOffsets())) { + if (auto *RHSGV = dyn_cast( + RHSOp0->stripInBoundsConstantOffsets())) { if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal()) return false; + + // On AArch64 and x86_64, if the first operand is a function, we can + // guarantee that a PC relative relocation will be emitted between + // the PLT entry for that function and this global even if the the + // function is not dso_local. + const auto *M = LHSGV->getParent(); + llvm::Triple TargetTriple(M->getTargetTriple()); + auto Arch = TargetTriple.getArch(); + if (isa(LHSGV) && + (Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::x86_64)) + return false; + } + } } } } diff --git a/llvm/test/CodeGen/X86/relptr-rodata.ll b/llvm/test/CodeGen/X86/relptr-rodata.ll --- a/llvm/test/CodeGen/X86/relptr-rodata.ll +++ b/llvm/test/CodeGen/X86/relptr-rodata.ll @@ -19,3 +19,27 @@ ; CHECK: relro2: ; CHECK: .long hidden-relro2 @relro2 = constant i32 trunc (i64 sub (i64 ptrtoint (i8* @hidden to i64), i64 ptrtoint (i32* @relro2 to i64)) to i32) + +; CHECK: .section .rodata.cst8 +; CHECK-NEXT: .globl obj +; CHECK: obj: +; CHECK: .long 0 +; CHECK: .long (hidden_func-obj)-4 + +declare hidden void @hidden_func() + +; Ensure that inbound GEPs with constant offsets are also resolved. +@obj = dso_local unnamed_addr constant { { i32, i32 } } { + { i32, i32 } { + i32 0, + i32 trunc (i64 sub (i64 ptrtoint (void ()* @hidden_func to i64), i64 ptrtoint (i32* getelementptr inbounds ({ { i32, i32 } }, { { i32, i32 } }* @obj, i32 0, i32 0, i32 1) to i64)) to i32) + } }, align 4 + +; CHECK: .section .rodata.rodata2 +; CHECK-NEXT: .globl rodata2 +; CHECK: rodata2: +; CHECK: .long extern_func@PLT-rodata2 + +declare void @extern_func() unnamed_addr + +@rodata2 = hidden constant i32 trunc (i64 sub (i64 ptrtoint (void ()* @extern_func to i64), i64 ptrtoint (i32* @rodata2 to i64)) to i32)