[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
GitOrigin-RevId: c77659e5494e4aa942bf0bc709b1779931dd30a8
diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h
index 0190aca..959d0e7 100644
--- a/include/llvm/IR/Constant.h
+++ b/include/llvm/IR/Constant.h
@@ -130,11 +130,13 @@
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 @@
/// 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/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp
index 3f90df1..0140738 100644
--- a/lib/CodeGen/MachineFunction.cpp
+++ b/lib/CodeGen/MachineFunction.cpp
@@ -1119,7 +1119,7 @@
bool MachineConstantPoolEntry::needsRelocation() const {
if (isMachineConstantPoolEntry())
return true;
- return Val.ConstVal->needsRelocation();
+ return Val.ConstVal->needsDynamicRelocation();
}
SectionKind
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 6fd205c..ef0e5f6 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -652,12 +652,20 @@
return false;
}
+bool Constant::needsDynamicRelocation() const {
+ return getRelocationInfo() == GlobalRelocation;
+}
+
bool Constant::needsRelocation() const {
+ return getRelocationInfo() != NoRelocation;
+}
+
+Constant::PossibleRelocationsTy Constant::getRelocationInfo() const {
if (isa<GlobalValue>(this))
- return true; // Global reference.
+ return GlobalRelocation; // Global reference.
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 (CE->getOpcode() == Instruction::Sub) {
@@ -675,7 +683,7 @@
if (isa<BlockAddress>(LHSOp0) && isa<BlockAddress>(RHSOp0) &&
cast<BlockAddress>(LHSOp0)->getFunction() ==
cast<BlockAddress>(RHSOp0)->getFunction())
- return false;
+ return NoRelocation;
// Relative pointers do not need to be dynamically relocated.
if (auto *RHSGV =
@@ -683,19 +691,20 @@
auto *LHS = LHSOp0->stripInBoundsConstantOffsets();
if (auto *LHSGV = dyn_cast<GlobalValue>(LHS)) {
if (LHSGV->isDSOLocal() && RHSGV->isDSOLocal())
- return false;
+ return LocalRelocation;
} else if (isa<DSOLocalEquivalent>(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<Constant>(getOperand(i))->needsRelocation();
+ Result =
+ std::max(cast<Constant>(getOperand(i))->getRelocationInfo(), Result);
return Result;
}
diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp
index 338eb5c..cc326b9 100644
--- a/lib/Target/ARM/ARMISelLowering.cpp
+++ b/lib/Target/ARM/ARMISelLowering.cpp
@@ -3601,7 +3601,7 @@
// 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/lib/Target/ARM/ARMTargetTransformInfo.h b/lib/Target/ARM/ARMTargetTransformInfo.h
index 8081289..cb9c48e 100644
--- a/lib/Target/ARM/ARMTargetTransformInfo.h
+++ b/lib/Target/ARM/ARMTargetTransformInfo.h
@@ -275,7 +275,7 @@
// 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/lib/Target/PowerPC/PPCTargetObjectFile.cpp b/lib/Target/PowerPC/PPCTargetObjectFile.cpp
index d52c9f9..736150f 100644
--- a/lib/Target/PowerPC/PPCTargetObjectFile.cpp
+++ b/lib/Target/PowerPC/PPCTargetObjectFile.cpp
@@ -40,7 +40,8 @@
if (Kind.isReadOnly()) {
const auto *GVar = dyn_cast<GlobalVariable>(GO);
- if (GVar && GVar->isConstant() && GVar->getInitializer()->needsRelocation())
+ if (GVar && GVar->isConstant() &&
+ GVar->getInitializer()->needsDynamicRelocation())
Kind = SectionKind::getReadOnlyWithRel();
}
diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp
index 239f12c..4efac23 100644
--- a/lib/Target/TargetLoweringObjectFile.cpp
+++ b/lib/Target/TargetLoweringObjectFile.cpp
@@ -290,7 +290,8 @@
// 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/test/CodeGen/X86/relptr-rodata.ll b/test/CodeGen/X86/relptr-rodata.ll
index 6dc2ed9..5bf08e3 100644
--- a/test/CodeGen/X86/relptr-rodata.ll
+++ b/test/CodeGen/X86/relptr-rodata.ll
@@ -20,7 +20,7 @@
; 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