Index: llvm/trunk/lib/IR/Constants.cpp =================================================================== --- llvm/trunk/lib/IR/Constants.cpp +++ llvm/trunk/lib/IR/Constants.cpp @@ -502,22 +502,34 @@ if (const BlockAddress *BA = dyn_cast(this)) return BA->getFunction()->needsRelocation(); - // While raw uses of blockaddress need to be relocated, differences between - // two of them don't when they are for labels in the same function. This is a - // common idiom when creating a table for the indirect goto extension, so we - // handle it efficiently here. - if (const ConstantExpr *CE = dyn_cast(this)) + if (const ConstantExpr *CE = dyn_cast(this)) { if (CE->getOpcode() == Instruction::Sub) { ConstantExpr *LHS = dyn_cast(CE->getOperand(0)); ConstantExpr *RHS = dyn_cast(CE->getOperand(1)); if (LHS && RHS && LHS->getOpcode() == Instruction::PtrToInt && - RHS->getOpcode() == Instruction::PtrToInt && - isa(LHS->getOperand(0)) && - isa(RHS->getOperand(0)) && - cast(LHS->getOperand(0))->getFunction() == - cast(RHS->getOperand(0))->getFunction()) - return false; + RHS->getOpcode() == Instruction::PtrToInt) { + Constant *LHSOp0 = LHS->getOperand(0); + Constant *RHSOp0 = RHS->getOperand(0); + + // While raw uses of blockaddress need to be relocated, differences + // between two of them don't when they are for labels in the same + // function. This is a common idiom when creating a table for the + // indirect goto extension, so we handle it efficiently here. + if (isa(LHSOp0) && isa(LHSOp0) && + cast(LHSOp0)->getFunction() == + cast(RHSOp0)->getFunction()) + return false; + + // Relative pointers do not need to be dynamically relocated. + if (auto *LHSGV = dyn_cast( + LHSOp0->stripPointerCastsNoFollowAliases())) + if (auto *RHSGV = dyn_cast( + RHSOp0->stripPointerCastsNoFollowAliases())) + if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal()) + return false; + } } + } bool Result = false; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) Index: llvm/trunk/test/CodeGen/X86/relptr-rodata.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/relptr-rodata.ll +++ llvm/trunk/test/CodeGen/X86/relptr-rodata.ll @@ -0,0 +1,21 @@ +; RUN: llc -relocation-model=pic -data-sections -o - %s | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +@hidden = external hidden global i8 +@default = external global i8 + +; CHECK: .section .rodata.rodata +; CHECK: rodata: +; CHECK: .long hidden-rodata +@rodata = hidden constant i32 trunc (i64 sub (i64 ptrtoint (i8* @hidden to i64), i64 ptrtoint (i32* @rodata to i64)) to i32) + +; CHECK: .section .data.rel.ro.relro1 +; CHECK: relro1: +; CHECK: .long default-relro1 +@relro1 = hidden constant i32 trunc (i64 sub (i64 ptrtoint (i8* @default to i64), i64 ptrtoint (i32* @relro1 to i64)) to i32) + +; CHECK: .section .data.rel.ro.relro2 +; 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)