[llvm][IR] Do not place constants with static relocations in a mergeable section

This patch provides two major changes:

1. Add getRelocationInfo to check if a constant will have static, dynamic, or
   no relocations. (Also rename the original needsRelocation to needsDynamicRelocation.)
2. Only allow a constant with no relocations (static or dynamic) to be placed
   in a mergeable section.

This will allow unused symbols that contain static relocations and happen to
fit in mergeable constant sections (.rodata.cstN) to instead be placed in
unique-named sections if -fdata-sections is used and subsequently garbage collected
by --gc-sections.

See https://lists.llvm.org/pipermail/llvm-dev/2021-February/148281.html.

Differential Revision: https://reviews.llvm.org/D95960
This commit is contained in:
Leonard Chan 2021-02-10 09:59:36 -08:00
parent afdfdc4bcf
commit c77659e549
8 changed files with 46 additions and 15 deletions

View File

@ -130,11 +130,13 @@ public:
bool isConstantUsed() const; bool isConstantUsed() const;
/// This method classifies the entry according to whether or not it may /// This method classifies the entry according to whether or not it may
/// generate a relocation entry. This must be conservative, so if it might /// generate a relocation entry (either static or dynamic). This must be
/// codegen to a relocatable entry, it should say so. /// conservative, so if it might codegen to a relocatable entry, it should say
/// so.
/// ///
/// FIXME: This really should not be in IR. /// FIXME: This really should not be in IR.
bool needsRelocation() const; bool needsRelocation() const;
bool needsDynamicRelocation() const;
/// For aggregates (struct/array/vector) return the constant that corresponds /// For aggregates (struct/array/vector) return the constant that corresponds
/// to the specified element if possible, or null if not. This can return null /// to the specified element if possible, or null if not. This can return null
@ -214,6 +216,24 @@ public:
/// both must either be scalars or vectors with the same element count. If no /// both must either be scalars or vectors with the same element count. If no
/// changes are made, the constant C is returned. /// changes are made, the constant C is returned.
static Constant *mergeUndefsWith(Constant *C, Constant *Other); static Constant *mergeUndefsWith(Constant *C, Constant *Other);
private:
enum PossibleRelocationsTy {
/// This constant requires no relocations. That is, it holds simple
/// constants (like integrals).
NoRelocation = 0,
/// This constant holds static relocations that can be resolved by the
/// static linker.
LocalRelocation = 1,
/// This constant holds dynamic relocations that the dynamic linker will
/// need to resolve.
GlobalRelocation = 2,
};
/// Determine what potential relocations may be needed by this constant.
PossibleRelocationsTy getRelocationInfo() const;
}; };
} // end namespace llvm } // end namespace llvm

View File

@ -1119,7 +1119,7 @@ unsigned MachineConstantPoolEntry::getSizeInBytes(const DataLayout &DL) const {
bool MachineConstantPoolEntry::needsRelocation() const { bool MachineConstantPoolEntry::needsRelocation() const {
if (isMachineConstantPoolEntry()) if (isMachineConstantPoolEntry())
return true; return true;
return Val.ConstVal->needsRelocation(); return Val.ConstVal->needsDynamicRelocation();
} }
SectionKind SectionKind

View File

@ -652,12 +652,20 @@ bool Constant::isConstantUsed() const {
return false; return false;
} }
bool Constant::needsDynamicRelocation() const {
return getRelocationInfo() == GlobalRelocation;
}
bool Constant::needsRelocation() const { bool Constant::needsRelocation() const {
return getRelocationInfo() != NoRelocation;
}
Constant::PossibleRelocationsTy Constant::getRelocationInfo() const {
if (isa<GlobalValue>(this)) if (isa<GlobalValue>(this))
return true; // Global reference. return GlobalRelocation; // Global reference.
if (const BlockAddress *BA = dyn_cast<BlockAddress>(this)) if (const BlockAddress *BA = dyn_cast<BlockAddress>(this))
return BA->getFunction()->needsRelocation(); return BA->getFunction()->getRelocationInfo();
if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(this)) { if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(this)) {
if (CE->getOpcode() == Instruction::Sub) { if (CE->getOpcode() == Instruction::Sub) {
@ -675,7 +683,7 @@ bool Constant::needsRelocation() const {
if (isa<BlockAddress>(LHSOp0) && isa<BlockAddress>(RHSOp0) && if (isa<BlockAddress>(LHSOp0) && isa<BlockAddress>(RHSOp0) &&
cast<BlockAddress>(LHSOp0)->getFunction() == cast<BlockAddress>(LHSOp0)->getFunction() ==
cast<BlockAddress>(RHSOp0)->getFunction()) cast<BlockAddress>(RHSOp0)->getFunction())
return false; return NoRelocation;
// Relative pointers do not need to be dynamically relocated. // Relative pointers do not need to be dynamically relocated.
if (auto *RHSGV = if (auto *RHSGV =
@ -683,19 +691,20 @@ bool Constant::needsRelocation() const {
auto *LHS = LHSOp0->stripInBoundsConstantOffsets(); auto *LHS = LHSOp0->stripInBoundsConstantOffsets();
if (auto *LHSGV = dyn_cast<GlobalValue>(LHS)) { if (auto *LHSGV = dyn_cast<GlobalValue>(LHS)) {
if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal()) if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal())
return false; return LocalRelocation;
} else if (isa<DSOLocalEquivalent>(LHS)) { } else if (isa<DSOLocalEquivalent>(LHS)) {
if (RHSGV->isDSOLocal()) if (RHSGV->isDSOLocal())
return false; return LocalRelocation;
} }
} }
} }
} }
} }
bool Result = false; PossibleRelocationsTy Result = NoRelocation;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
Result |= cast<Constant>(getOperand(i))->needsRelocation(); Result =
std::max(cast<Constant>(getOperand(i))->getRelocationInfo(), Result);
return Result; return Result;
} }

View File

@ -3601,7 +3601,7 @@ static SDValue promoteToConstantPool(const ARMTargetLowering *TLI,
// from .data to .text. This is not allowed in position-independent code. // from .data to .text. This is not allowed in position-independent code.
auto *Init = GVar->getInitializer(); auto *Init = GVar->getInitializer();
if ((TLI->isPositionIndependent() || TLI->getSubtarget()->isROPI()) && if ((TLI->isPositionIndependent() || TLI->getSubtarget()->isROPI()) &&
Init->needsRelocation()) Init->needsDynamicRelocation())
return SDValue(); return SDValue();
// The constant islands pass can only really deal with alignment requests // The constant islands pass can only really deal with alignment requests

View File

@ -275,7 +275,7 @@ public:
// variables or functions in constant data, so don't convert switches to // variables or functions in constant data, so don't convert switches to
// lookup tables if any of the values would need relocation. // lookup tables if any of the values would need relocation.
if (ST->isROPI() || ST->isRWPI()) if (ST->isROPI() || ST->isRWPI())
return !C->needsRelocation(); return !C->needsDynamicRelocation();
return true; return true;
} }

View File

@ -40,7 +40,8 @@ MCSection *PPC64LinuxTargetObjectFile::SelectSectionForGlobal(
if (Kind.isReadOnly()) { if (Kind.isReadOnly()) {
const auto *GVar = dyn_cast<GlobalVariable>(GO); const auto *GVar = dyn_cast<GlobalVariable>(GO);
if (GVar && GVar->isConstant() && GVar->getInitializer()->needsRelocation()) if (GVar && GVar->isConstant() &&
GVar->getInitializer()->needsDynamicRelocation())
Kind = SectionKind::getReadOnlyWithRel(); Kind = SectionKind::getReadOnlyWithRel();
} }

View File

@ -290,7 +290,8 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO,
// consideration when it tries to merge entries in the section. // consideration when it tries to merge entries in the section.
Reloc::Model ReloModel = TM.getRelocationModel(); Reloc::Model ReloModel = TM.getRelocationModel();
if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI || if (ReloModel == Reloc::Static || ReloModel == Reloc::ROPI ||
ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI) ReloModel == Reloc::RWPI || ReloModel == Reloc::ROPI_RWPI ||
!C->needsDynamicRelocation())
return SectionKind::getReadOnly(); return SectionKind::getReadOnly();
// Otherwise, the dynamic linker needs to fix it up, put it in the // Otherwise, the dynamic linker needs to fix it up, put it in the

View File

@ -20,7 +20,7 @@ target triple = "x86_64-unknown-linux-gnu"
; CHECK: .long hidden-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) @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: .section .rodata.obj
; CHECK-NEXT: .globl obj ; CHECK-NEXT: .globl obj
; CHECK: obj: ; CHECK: obj:
; CHECK: .long 0 ; CHECK: .long 0