[llvm] [AsmPrinter] Always emit global equivalents if there is non-global uses (PR #145648)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 25 00:31:30 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: dianqk (dianqk)
<details>
<summary>Changes</summary>
A case found from https://github.com/rust-lang/rust/issues/142752: https://llvm.godbolt.org/z/T7ce9saWh.
We should emit `@<!-- -->bar_0` for the following code:
```llvm
target triple = "x86_64-unknown-linux-gnu"
@<!-- -->rel_0 = private unnamed_addr constant [1 x i32] [
i32 trunc (i64 sub (i64 ptrtoint (ptr @<!-- -->bar_0 to i64), i64 ptrtoint (ptr @<!-- -->rel_0 to i64)) to i32)]
@<!-- -->bar_0 = internal unnamed_addr constant ptr @<!-- -->foo_0, align 8
@<!-- -->foo_0 = external global ptr, align 8
define void @<!-- -->foo(ptr %arg0) {
store ptr @<!-- -->bar_0, ptr %arg0, align 8
ret void
}
```
---
Full diff: https://github.com/llvm/llvm-project/pull/145648.diff
3 Files Affected:
- (modified) llvm/include/llvm/CodeGen/AsmPrinter.h (+6-2)
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+29-17)
- (added) llvm/test/MC/X86/gotpcrel-non-globals.ll (+28)
``````````diff
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 6ad54fcd6d0e5..22764409d0c54 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -151,8 +151,12 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
/// Map global GOT equivalent MCSymbols to GlobalVariables and keep track of
/// its number of uses by other globals.
- using GOTEquivUsePair = std::pair<const GlobalVariable *, unsigned>;
- MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs;
+ struct GOTEquivUse {
+ const GlobalVariable *GV;
+ unsigned NumUses;
+ bool HasNonGlobalUsers;
+ };
+ MapVector<const MCSymbol *, GOTEquivUse> GlobalGOTEquivs;
// Flags representing which CFI section is required for a function/module.
enum class CFISection : unsigned {
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3b96225236cd6..4ee05423aa96d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -740,9 +740,11 @@ void AsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
if (emitSpecialLLVMGlobal(GV))
return;
- // Skip the emission of global equivalents. The symbol can be emitted later
- // on by emitGlobalGOTEquivs in case it turns out to be needed.
- if (GlobalGOTEquivs.count(getSymbol(GV)))
+ // Skip the emission of global equivalents if they are only used by global
+ // values. The symbol can be emitted later on by emitGlobalGOTEquivs in case
+ // it turns out to be needed.
+ if (GlobalGOTEquivs.contains(getSymbol(GV)) &&
+ !GlobalGOTEquivs[getSymbol(GV)].HasNonGlobalUsers)
return;
if (isVerbose()) {
@@ -2142,16 +2144,20 @@ void AsmPrinter::emitFunctionBody() {
}
/// Compute the number of Global Variables that uses a Constant.
-static unsigned getNumGlobalVariableUses(const Constant *C) {
- if (!C)
+static unsigned getNumGlobalVariableUses(const Constant *C,
+ bool &HasNonGlobalUsers) {
+ if (!C) {
+ HasNonGlobalUsers = true;
return 0;
+ }
if (isa<GlobalVariable>(C))
return 1;
unsigned NumUses = 0;
for (const auto *CU : C->users())
- NumUses += getNumGlobalVariableUses(dyn_cast<Constant>(CU));
+ NumUses +=
+ getNumGlobalVariableUses(dyn_cast<Constant>(CU), HasNonGlobalUsers);
return NumUses;
}
@@ -2162,7 +2168,8 @@ static unsigned getNumGlobalVariableUses(const Constant *C) {
/// candidates are skipped and are emitted later in case at least one cstexpr
/// isn't replaced by a PC relative GOT entry access.
static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
- unsigned &NumGOTEquivUsers) {
+ unsigned &NumGOTEquivUsers,
+ bool &HasNonGlobalUsers) {
// Global GOT equivalents are unnamed private globals with a constant
// pointer initializer to another global symbol. They must point to a
// GlobalVariable or Function, i.e., as GlobalValue.
@@ -2174,7 +2181,8 @@ static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
// To be a got equivalent, at least one of its users need to be a constant
// expression used by another global variable.
for (const auto *U : GV->users())
- NumGOTEquivUsers += getNumGlobalVariableUses(dyn_cast<Constant>(U));
+ NumGOTEquivUsers +=
+ getNumGlobalVariableUses(dyn_cast<Constant>(U), HasNonGlobalUsers);
return NumGOTEquivUsers > 0;
}
@@ -2192,11 +2200,13 @@ void AsmPrinter::computeGlobalGOTEquivs(Module &M) {
for (const auto &G : M.globals()) {
unsigned NumGOTEquivUsers = 0;
- if (!isGOTEquivalentCandidate(&G, NumGOTEquivUsers))
+ bool HasNonGlobalUsers = false;
+ if (!isGOTEquivalentCandidate(&G, NumGOTEquivUsers, HasNonGlobalUsers))
continue;
const MCSymbol *GOTEquivSym = getSymbol(&G);
- GlobalGOTEquivs[GOTEquivSym] = std::make_pair(&G, NumGOTEquivUsers);
+ GlobalGOTEquivs[GOTEquivSym] =
+ AsmPrinter::GOTEquivUse{&G, NumGOTEquivUsers, HasNonGlobalUsers};
}
}
@@ -2209,9 +2219,9 @@ void AsmPrinter::emitGlobalGOTEquivs() {
SmallVector<const GlobalVariable *, 8> FailedCandidates;
for (auto &I : GlobalGOTEquivs) {
- const GlobalVariable *GV = I.second.first;
- unsigned Cnt = I.second.second;
- if (Cnt)
+ const GlobalVariable *GV = I.second.GV;
+ unsigned Cnt = I.second.NumUses;
+ if (Cnt > 0 && !I.second.HasNonGlobalUsers)
FailedCandidates.push_back(GV);
}
GlobalGOTEquivs.clear();
@@ -3992,9 +4002,10 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
// .long 42
// foo:
// .long bar at GOTPCREL+<gotpcrelcst>
- AsmPrinter::GOTEquivUsePair Result = AP.GlobalGOTEquivs[GOTEquivSym];
- const GlobalVariable *GV = Result.first;
- int NumUses = (int)Result.second;
+ AsmPrinter::GOTEquivUse Result = AP.GlobalGOTEquivs[GOTEquivSym];
+ const GlobalVariable *GV = Result.GV;
+ bool HasNonGlobalUsers = Result.HasNonGlobalUsers;
+ int NumUses = (int)Result.NumUses;
const GlobalValue *FinalGV = dyn_cast<GlobalValue>(GV->getOperand(0));
const MCSymbol *FinalSym = AP.getSymbol(FinalGV);
*ME = AP.getObjFileLowering().getIndirectSymViaGOTPCRel(
@@ -4003,7 +4014,8 @@ static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
// Update GOT equivalent usage information
--NumUses;
if (NumUses >= 0)
- AP.GlobalGOTEquivs[GOTEquivSym] = std::make_pair(GV, NumUses);
+ AP.GlobalGOTEquivs[GOTEquivSym] =
+ AsmPrinter::GOTEquivUse{GV, (unsigned)NumUses, HasNonGlobalUsers};
}
static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *CV,
diff --git a/llvm/test/MC/X86/gotpcrel-non-globals.ll b/llvm/test/MC/X86/gotpcrel-non-globals.ll
new file mode 100644
index 0000000000000..cbf22cd1e4ac0
--- /dev/null
+++ b/llvm/test/MC/X86/gotpcrel-non-globals.ll
@@ -0,0 +1,28 @@
+; RUN: llc < %s | FileCheck %s
+
+target triple = "x86_64-unknown-linux-gnu"
+
+; Check that we submit the `@bar_*` symbols, and that we don't submit multiple symbols.
+
+; CHECK-LABEL: .Lrel_0:
+; CHECK: .long foo_0 at GOTPCREL+0
+; CHECK-LABEL: .Lrel_1_failed:
+; CHECK: .long bar_1-foo_0
+
+; CHECK: bar_0:
+; CHECK: bar_1:
+
+ at rel_0 = private unnamed_addr constant [1 x i32] [
+ i32 trunc (i64 sub (i64 ptrtoint (ptr @bar_0 to i64), i64 ptrtoint (ptr @rel_0 to i64)) to i32)]
+ at rel_1_failed = private unnamed_addr constant [1 x i32] [
+ i32 trunc (i64 sub (i64 ptrtoint (ptr @bar_1 to i64), i64 ptrtoint (ptr @foo_0 to i64)) to i32)]
+ at bar_0 = internal unnamed_addr constant ptr @foo_0, align 8
+ at bar_1 = internal unnamed_addr constant ptr @foo_1, align 8
+ at foo_0 = external global ptr, align 8
+ at foo_1 = external global ptr, align 8
+
+define void @foo(ptr %arg0, ptr %arg1) {
+ store ptr @bar_0, ptr %arg0, align 8
+ store ptr @bar_1, ptr %arg1, align 8
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/145648
More information about the llvm-commits
mailing list