From c77659e5494e4aa942bf0bc709b1779931dd30a8 Mon Sep 17 00:00:00 2001 From: Leonard Chan Date: Wed, 10 Feb 2021 09:59:36 -0800 Subject: [PATCH] [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 --- llvm/include/llvm/IR/Constant.h | 24 +++++++++++++++++-- llvm/lib/CodeGen/MachineFunction.cpp | 2 +- llvm/lib/IR/Constants.cpp | 23 ++++++++++++------ llvm/lib/Target/ARM/ARMISelLowering.cpp | 2 +- llvm/lib/Target/ARM/ARMTargetTransformInfo.h | 2 +- .../Target/PowerPC/PPCTargetObjectFile.cpp | 3 ++- llvm/lib/Target/TargetLoweringObjectFile.cpp | 3 ++- llvm/test/CodeGen/X86/relptr-rodata.ll | 2 +- 8 files changed, 46 insertions(+), 15 deletions(-) diff --git a/llvm/include/llvm/IR/Constant.h b/llvm/include/llvm/IR/Constant.h index 0190aca27b72..959d0e716d25 100644 --- a/llvm/include/llvm/IR/Constant.h +++ b/llvm/include/llvm/IR/Constant.h @@ -130,11 +130,13 @@ public: bool isConstantUsed() const; /// This method classifies the entry according to whether or not it may - /// generate a relocation entry. This must be conservative, so if it might - /// codegen to a relocatable entry, it should say so. + /// generate a relocation entry (either static or dynamic). This must be + /// conservative, so if it might codegen to a relocatable entry, it should say + /// so. /// /// FIXME: This really should not be in IR. bool needsRelocation() const; + bool needsDynamicRelocation() const; /// For aggregates (struct/array/vector) return the constant that corresponds /// 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 /// changes are made, the constant C is returned. 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 diff --git a/llvm/lib/CodeGen/MachineFunction.cpp b/llvm/lib/CodeGen/MachineFunction.cpp index 3f90df19f924..014073862d0d 100644 --- a/llvm/lib/CodeGen/MachineFunction.cpp +++ b/llvm/lib/CodeGen/MachineFunction.cpp @@ -1119,7 +1119,7 @@ unsigned MachineConstantPoolEntry::getSizeInBytes(const DataLayout &DL) const { bool MachineConstantPoolEntry::needsRelocation() const { if (isMachineConstantPoolEntry()) return true; - return Val.ConstVal->needsRelocation(); + return Val.ConstVal->needsDynamicRelocation(); } SectionKind diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 6fd205c654a8..ef0e5f6dd087 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -652,12 +652,20 @@ bool Constant::isConstantUsed() const { return false; } +bool Constant::needsDynamicRelocation() const { + return getRelocationInfo() == GlobalRelocation; +} + bool Constant::needsRelocation() const { + return getRelocationInfo() != NoRelocation; +} + +Constant::PossibleRelocationsTy Constant::getRelocationInfo() const { if (isa(this)) - return true; // Global reference. + return GlobalRelocation; // Global reference. if (const BlockAddress *BA = dyn_cast(this)) - return BA->getFunction()->needsRelocation(); + return BA->getFunction()->getRelocationInfo(); if (const ConstantExpr *CE = dyn_cast(this)) { if (CE->getOpcode() == Instruction::Sub) { @@ -675,7 +683,7 @@ bool Constant::needsRelocation() const { if (isa(LHSOp0) && isa(RHSOp0) && cast(LHSOp0)->getFunction() == cast(RHSOp0)->getFunction()) - return false; + return NoRelocation; // Relative pointers do not need to be dynamically relocated. if (auto *RHSGV = @@ -683,19 +691,20 @@ bool Constant::needsRelocation() const { auto *LHS = LHSOp0->stripInBoundsConstantOffsets(); if (auto *LHSGV = dyn_cast(LHS)) { if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal()) - return false; + return LocalRelocation; } else if (isa(LHS)) { if (RHSGV->isDSOLocal()) - return false; + return LocalRelocation; } } } } } - bool Result = false; + PossibleRelocationsTy Result = NoRelocation; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - Result |= cast(getOperand(i))->needsRelocation(); + Result = + std::max(cast(getOperand(i))->getRelocationInfo(), Result); return Result; } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 338eb5ce7e62..cc326b960a0c 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -3601,7 +3601,7 @@ static SDValue promoteToConstantPool(const ARMTargetLowering *TLI, // from .data to .text. This is not allowed in position-independent code. auto *Init = GVar->getInitializer(); if ((TLI->isPositionIndependent() || TLI->getSubtarget()->isROPI()) && - Init->needsRelocation()) + Init->needsDynamicRelocation()) return SDValue(); // The constant islands pass can only really deal with alignment requests diff --git a/llvm/lib/Target/ARM/ARMTargetTransformInfo.h b/llvm/lib/Target/ARM/ARMTargetTransformInfo.h index 808128929000..cb9c48e662ac 100644 --- a/llvm/lib/Target/ARM/ARMTargetTransformInfo.h +++ b/llvm/lib/Target/ARM/ARMTargetTransformInfo.h @@ -275,7 +275,7 @@ public: // variables or functions in constant data, so don't convert switches to // lookup tables if any of the values would need relocation. if (ST->isROPI() || ST->isRWPI()) - return !C->needsRelocation(); + return !C->needsDynamicRelocation(); return true; } diff --git a/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp b/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp index d52c9f92bd1d..736150fdbc0a 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetObjectFile.cpp @@ -40,7 +40,8 @@ MCSection *PPC64LinuxTargetObjectFile::SelectSectionForGlobal( if (Kind.isReadOnly()) { const auto *GVar = dyn_cast(GO); - if (GVar && GVar->isConstant() && GVar->getInitializer()->needsRelocation()) + if (GVar && GVar->isConstant() && + GVar->getInitializer()->needsDynamicRelocation()) Kind = SectionKind::getReadOnlyWithRel(); } diff --git a/llvm/lib/Target/TargetLoweringObjectFile.cpp b/llvm/lib/Target/TargetLoweringObjectFile.cpp index 239f12c4d6f7..4efac2303da6 100644 --- a/llvm/lib/Target/TargetLoweringObjectFile.cpp +++ b/llvm/lib/Target/TargetLoweringObjectFile.cpp @@ -290,7 +290,8 @@ SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalObject *GO, // consideration when it tries to merge entries in the section. Reloc::Model ReloModel = TM.getRelocationModel(); 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(); // Otherwise, the dynamic linker needs to fix it up, put it in the diff --git a/llvm/test/CodeGen/X86/relptr-rodata.ll b/llvm/test/CodeGen/X86/relptr-rodata.ll index 6dc2ed914a96..5bf08e3a316a 100644 --- a/llvm/test/CodeGen/X86/relptr-rodata.ll +++ b/llvm/test/CodeGen/X86/relptr-rodata.ll @@ -20,7 +20,7 @@ target triple = "x86_64-unknown-linux-gnu" ; 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: .section .rodata.obj ; CHECK-NEXT: .globl obj ; CHECK: obj: ; CHECK: .long 0