Skip to content

[GlobalMerge] Update the GlobalMerge pass to merge private global variables. #101222

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 13, 2024

Conversation

amy-kwan
Copy link
Contributor

This patch updates the GlobalMerge pass to be able to handle private global variables, which is required for a follow-up PowerPC specific GlobalMerge patch to merge internal and private globals.

A new LIT test is also added to exhibit the ability to merge private globals.

…iables.

This patch updates the GlobalMerge pass to be able to handle private global
variables, which is required for a follow-up PowerPC specific GlobalMerge patch
to merge internal and private globals.

A new LIT test is also added to exhibit the ability to merge private globals.
@llvmbot
Copy link
Member

llvmbot commented Jul 30, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Amy Kwan (amy-kwan)

Changes

This patch updates the GlobalMerge pass to be able to handle private global variables, which is required for a follow-up PowerPC specific GlobalMerge patch to merge internal and private globals.

A new LIT test is also added to exhibit the ability to merge private globals.


Full diff: https://github.com/llvm/llvm-project/pull/101222.diff

2 Files Affected:

  • (modified) llvm/lib/CodeGen/GlobalMerge.cpp (+1-1)
  • (added) llvm/test/Transforms/GlobalMerge/private-global.ll (+31)
diff --git a/llvm/lib/CodeGen/GlobalMerge.cpp b/llvm/lib/CodeGen/GlobalMerge.cpp
index 65bf7161441ba..e420c2bb7a25e 100644
--- a/llvm/lib/CodeGen/GlobalMerge.cpp
+++ b/llvm/lib/CodeGen/GlobalMerge.cpp
@@ -664,7 +664,7 @@ bool GlobalMergeImpl::run(Module &M) {
       continue;
 
     if (!(Opt.MergeExternal && GV.hasExternalLinkage()) &&
-        !GV.hasInternalLinkage())
+        !GV.hasInternalLinkage() && !GV.hasPrivateLinkage())
       continue;
 
     PointerType *PT = dyn_cast<PointerType>(GV.getType());
diff --git a/llvm/test/Transforms/GlobalMerge/private-global.ll b/llvm/test/Transforms/GlobalMerge/private-global.ll
new file mode 100644
index 0000000000000..f0ff89061f07c
--- /dev/null
+++ b/llvm/test/Transforms/GlobalMerge/private-global.ll
@@ -0,0 +1,31 @@
+; RUN: opt -global-merge -global-merge-max-offset=100 -S -o - %s | FileCheck %s
+; RUN: opt -passes='global-merge<max-offset=100>' -S -o - %s | FileCheck %s
+
+; NOTE: This is a copy of the llvm/test/Transforms/GlobalMerge/used.ll test,
+; using `private` global variables instead of `internal`. This is to show that
+; that private globals can be merged in the GlobalMerge pass.
+
+target datalayout = "e-p:64:64"
+target triple = "x86_64-unknown-linux-gnu"
+
+; CHECK: @_MergedGlobals = private global <{ i32, i32 }> <{ i32 3, i32 3 }>, align 4
+
+@a = private global i32 1
+@b = private global i32 2
+@c = private global i32 3
+@d = private global i32 3
+
+@llvm.used = appending global [1 x ptr] [ptr @a], section "llvm.metadata"
+@llvm.compiler.used = appending global [1 x ptr] [ptr @b], section "llvm.metadata"
+
+define void @use_private() {
+  ; CHECK: load i32, ptr @a
+  %x = load i32, ptr @a
+  ; CHECK: load i32, ptr @b
+  %y = load i32, ptr @b
+  ; CHECK: load i32, ptr @_MergedGlobals
+  %z1 = load i32, ptr @c
+  ; CHECK: load i32, ptr getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1)
+  %z2 = load i32, ptr @d
+  ret void
+}

@amy-kwan amy-kwan requested a review from nikic August 1, 2024 18:40
Copy link
Collaborator

@chenzheng1030 chenzheng1030 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but I think it would make more sense to base your test on basic.ll rather than used.ll, as the latter tests specific interaction with llvm.used globals, which is orthogonal to private visibility.

@amy-kwan
Copy link
Contributor Author

amy-kwan commented Aug 2, 2024

LGTM, but I think it would make more sense to base your test on basic.ll rather than used.ll, as the latter tests specific interaction with llvm.used globals, which is orthogonal to private visibility.

Thanks for the good suggestion. I've updated the LIT test.

@amy-kwan amy-kwan merged commit 4089763 into main Aug 13, 2024
5 of 7 checks passed
@amy-kwan amy-kwan deleted the users/amy-kwan/update-globalmerge-private-condition branch August 13, 2024 14:13
jyknight added a commit to jyknight/llvm-project that referenced this pull request Sep 25, 2024
After PR llvm#101222, we GlobalMerge started making transforms which are unsafe on Mach-O platforms.

Two issues, in particular, are fixed here:

1. We must never merge symbols in the `__cfstring` section, as the linker assumes each object in this section is only ever referenced directly, and that it can split the section as it likes.

Previously, we avoded this problem because CFString literals are identified by private-linkage symbols.

This patch adds a list of section-names to avoid merging, under Mach-O.

2. When the code was originally written, it had to be careful about emitting symbol aliases, due to issues with Mach-O's subsection splitting in the linker with `-dead_strip` enabled. This issue was fixed in 2016, via creation of the `.alt_entry` assembler directive, which allows creation of a symbol also implying the start of a new subsection. Unfortunately, Apple's ld-prime's support for this is buggy.

Therefore, we must _continue_ to be careful not to emit such symbol aliases. The code already avoided it for InternalLinkage symbols, but after the triggering PR, we also need to avoid it for PrivateLinkage symbols.

I will file an Apple bug-report about this issue, so that it can be fixed in a future version of ld-prime.

Fixes llvm#104625
jyknight added a commit that referenced this pull request Sep 27, 2024
As a side-effect of PR #101222, GlobalMerge started making transforms
which are unsafe on Mach-O platforms.

Two issues, in particular, are fixed here:

1. We must never merge symbols in the `__cfstring` section, as the
linker assumes each object in this section is only ever referenced
directly, and that it can split the section as it likes.

Previously, we avoided this problem because CFString literals are
identified by private-linkage symbols. This patch adds a list of
section-names with special behavior, to avoid merging under Mach-O.

2. When GlobalMerge code was originally written, it had to be careful
about emitting symbol aliases, due to issues with Mach-O's subsection
splitting in the linker with `-dead_strip` enabled. The underlying cause
of this problem was fixed in 2016, via creation of the `.alt_entry`
assembler directive, which allows a symbol to not also imply the start
of a new subsection. GlobalMerge's workaround for that issue was never
removed.

In the meantime, Apple's new ld-prime linker was written, and has a bug
in `.alt_entry` handling. Therefore, even though the original issue was
fixed, we must _continue_ to be careful not to emit any such symbol
aliases. The existing workaround avoided it for InternalLinkage symbols,
but after the above-mentioned PR, we also must avoid emitting aliases
for PrivateLinkage symbols.

I will file an Apple bug-report about this issue, so that it can be
fixed in a future version of ld-prime. But, in the meantime, the
workaround is sufficient for GlobalMerge, unless
`-global-merge-on-externals` is enabled (which it is already not by
default, on MachO platforms, due to the original issue).

Fixes #104625
Sterling-Augustine pushed a commit to Sterling-Augustine/llvm-project that referenced this pull request Sep 27, 2024
As a side-effect of PR llvm#101222, GlobalMerge started making transforms
which are unsafe on Mach-O platforms.

Two issues, in particular, are fixed here:

1. We must never merge symbols in the `__cfstring` section, as the
linker assumes each object in this section is only ever referenced
directly, and that it can split the section as it likes.

Previously, we avoided this problem because CFString literals are
identified by private-linkage symbols. This patch adds a list of
section-names with special behavior, to avoid merging under Mach-O.

2. When GlobalMerge code was originally written, it had to be careful
about emitting symbol aliases, due to issues with Mach-O's subsection
splitting in the linker with `-dead_strip` enabled. The underlying cause
of this problem was fixed in 2016, via creation of the `.alt_entry`
assembler directive, which allows a symbol to not also imply the start
of a new subsection. GlobalMerge's workaround for that issue was never
removed.

In the meantime, Apple's new ld-prime linker was written, and has a bug
in `.alt_entry` handling. Therefore, even though the original issue was
fixed, we must _continue_ to be careful not to emit any such symbol
aliases. The existing workaround avoided it for InternalLinkage symbols,
but after the above-mentioned PR, we also must avoid emitting aliases
for PrivateLinkage symbols.

I will file an Apple bug-report about this issue, so that it can be
fixed in a future version of ld-prime. But, in the meantime, the
workaround is sufficient for GlobalMerge, unless
`-global-merge-on-externals` is enabled (which it is already not by
default, on MachO platforms, due to the original issue).

Fixes llvm#104625
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants