[llvm] [WIP][GlobalOpt] Don't replace aliasee with alias that has weak linkage (PR #91483)

via llvm-commits llvm-commits at lists.llvm.org
Thu May 9 06:33:13 PDT 2024


https://github.com/DianQK updated https://github.com/llvm/llvm-project/pull/91483

>From 937ab674ce246630600b0537336a1c4f890c079b Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Thu, 9 May 2024 21:23:06 +0800
Subject: [PATCH 1/3] Pre-commit test cases

---
 llvm/test/Transforms/GlobalOpt/alias-weak.ll | 52 ++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 llvm/test/Transforms/GlobalOpt/alias-weak.ll

diff --git a/llvm/test/Transforms/GlobalOpt/alias-weak.ll b/llvm/test/Transforms/GlobalOpt/alias-weak.ll
new file mode 100644
index 0000000000000..4b7d4f3e364eb
--- /dev/null
+++ b/llvm/test/Transforms/GlobalOpt/alias-weak.ll
@@ -0,0 +1,52 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 4
+; RUN: opt < %s -passes=globalopt -S | FileCheck %s
+
+ at f1_alias = linkonce_odr hidden alias void (), ptr @f1
+ at f2_alias = linkonce_odr hidden alias void (), ptr @f2
+
+define void @foo() {
+  call void @f1_alias()
+  ret void
+}
+
+define void @bar() {
+  call void @f1()
+  ret void
+}
+
+define void @baz() {
+  call void @f2_alias()
+  ret void
+}
+
+; FIXME: We cannot use `f1_alias` to replace `f1` because they are both in use
+; and `f1_alias` could be replaced at link time.
+define internal void @f1() {
+  ret void
+}
+
+define internal void @f2() {
+  ret void
+}
+; CHECK-LABEL: define void @foo() local_unnamed_addr {
+; CHECK-NEXT:    call void @f1_alias()
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define void @bar() local_unnamed_addr {
+; CHECK-NEXT:    call void @f1_alias()
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define void @baz() local_unnamed_addr {
+; CHECK-NEXT:    call void @f2_alias()
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define linkonce_odr hidden void @f1_alias() local_unnamed_addr {
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define linkonce_odr hidden void @f2_alias() local_unnamed_addr {
+; CHECK-NEXT:    ret void
+;

>From ab7be415ab419c2c94adc560b4a05ef6dba27642 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Wed, 8 May 2024 22:33:05 +0800
Subject: [PATCH 2/3] [GlobalOpt] Don't replace aliasee with alias that has
 weak linkage

---
 llvm/lib/Transforms/IPO/GlobalOpt.cpp        |  3 +++
 llvm/test/Transforms/GlobalOpt/alias-weak.ll | 13 +++++++++----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index c8c835115a992..b7c6d25657bc0 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -2224,6 +2224,9 @@ static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U) {
 
 static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U,
                              bool &RenameTarget) {
+  if (GA.isWeakForLinker())
+    return false;
+
   RenameTarget = false;
   bool Ret = false;
   if (hasUseOtherThanLLVMUsed(GA, U))
diff --git a/llvm/test/Transforms/GlobalOpt/alias-weak.ll b/llvm/test/Transforms/GlobalOpt/alias-weak.ll
index 4b7d4f3e364eb..aec2a56313b12 100644
--- a/llvm/test/Transforms/GlobalOpt/alias-weak.ll
+++ b/llvm/test/Transforms/GlobalOpt/alias-weak.ll
@@ -19,22 +19,27 @@ define void @baz() {
   ret void
 }
 
-; FIXME: We cannot use `f1_alias` to replace `f1` because they are both in use
+; We cannot use `f1_alias` to replace `f1` because they are both in use
 ; and `f1_alias` could be replaced at link time.
 define internal void @f1() {
   ret void
 }
 
+; FIXME: We can use `f2_alias` to replace `f2` because `b2` is not in use.
 define internal void @f2() {
   ret void
 }
+;.
+; CHECK: @f1_alias = linkonce_odr hidden alias void (), ptr @f1
+; CHECK: @f2_alias = linkonce_odr hidden alias void (), ptr @f2
+;.
 ; CHECK-LABEL: define void @foo() local_unnamed_addr {
 ; CHECK-NEXT:    call void @f1_alias()
 ; CHECK-NEXT:    ret void
 ;
 ;
 ; CHECK-LABEL: define void @bar() local_unnamed_addr {
-; CHECK-NEXT:    call void @f1_alias()
+; CHECK-NEXT:    call void @f1()
 ; CHECK-NEXT:    ret void
 ;
 ;
@@ -43,10 +48,10 @@ define internal void @f2() {
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define linkonce_odr hidden void @f1_alias() local_unnamed_addr {
+; CHECK-LABEL: define internal void @f1() {
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define linkonce_odr hidden void @f2_alias() local_unnamed_addr {
+; CHECK-LABEL: define internal void @f2() {
 ; CHECK-NEXT:    ret void
 ;

>From 067c4aae32a0025de75b957032ffae7004b6fdd6 Mon Sep 17 00:00:00 2001
From: DianQK <dianqk at dianqk.net>
Date: Thu, 9 May 2024 20:45:18 +0800
Subject: [PATCH 3/3] [GlobalOpt] Replace aliasee if it is not in use

---
 llvm/lib/Transforms/IPO/GlobalOpt.cpp        | 20 ++++++++++++++++++--
 llvm/test/Transforms/GlobalOpt/alias-weak.ll |  5 ++---
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
index b7c6d25657bc0..c2525f3aa114a 100644
--- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp
@@ -2215,6 +2215,17 @@ static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U) {
   return !U.usedCount(&GA) && !U.compilerUsedCount(&GA);
 }
 
+static bool hasMoreThanOneUseOtherThanLLVMUsed(GlobalValue &V,
+                                               const LLVMUsed &U) {
+  unsigned N = 2;
+  assert((!U.usedCount(&V) || !U.compilerUsedCount(&V)) &&
+         "We should have removed the duplicated "
+         "element from llvm.compiler.used");
+  if (U.usedCount(&V) || U.compilerUsedCount(&V))
+    ++N;
+  return V.hasNUsesOrMore(N);
+}
+
 static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U) {
   if (!GV.hasLocalLinkage())
     return true;
@@ -2224,8 +2235,6 @@ static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U) {
 
 static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U,
                              bool &RenameTarget) {
-  if (GA.isWeakForLinker())
-    return false;
 
   RenameTarget = false;
   bool Ret = false;
@@ -2245,6 +2254,13 @@ static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U,
   //   define ... @a(...)
   Constant *Aliasee = GA.getAliasee();
   GlobalValue *Target = cast<GlobalValue>(Aliasee->stripPointerCasts());
+  // Do not perform the transform if alias may be replaced at link time while
+  // someone is using the aliasee (e.g., multiple aliases potentially target it
+  // or someone calls it).
+  if (GA.isWeakForLinker())
+    Ret = false;
+  if (hasMoreThanOneUseOtherThanLLVMUsed(*Target, U))
+    return Ret;
   if (mayHaveOtherReferences(*Target, U))
     return Ret;
 
diff --git a/llvm/test/Transforms/GlobalOpt/alias-weak.ll b/llvm/test/Transforms/GlobalOpt/alias-weak.ll
index aec2a56313b12..e24085f00d714 100644
--- a/llvm/test/Transforms/GlobalOpt/alias-weak.ll
+++ b/llvm/test/Transforms/GlobalOpt/alias-weak.ll
@@ -25,13 +25,12 @@ define internal void @f1() {
   ret void
 }
 
-; FIXME: We can use `f2_alias` to replace `f2` because `b2` is not in use.
+; We can use `f2_alias` to replace `f2` because `b2` is not in use.
 define internal void @f2() {
   ret void
 }
 ;.
 ; CHECK: @f1_alias = linkonce_odr hidden alias void (), ptr @f1
-; CHECK: @f2_alias = linkonce_odr hidden alias void (), ptr @f2
 ;.
 ; CHECK-LABEL: define void @foo() local_unnamed_addr {
 ; CHECK-NEXT:    call void @f1_alias()
@@ -52,6 +51,6 @@ define internal void @f2() {
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define internal void @f2() {
+; CHECK-LABEL: define linkonce_odr hidden void @f2_alias() local_unnamed_addr {
 ; CHECK-NEXT:    ret void
 ;



More information about the llvm-commits mailing list