From 937ab674ce246630600b0537336a1c4f890c079b Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 9 May 2024 21:23:06 +0800 Subject: [PATCH 1/4] 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 + +@f1_alias = linkonce_odr hidden alias void (), ptr @f1 +@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 Date: Wed, 8 May 2024 22:33:05 +0800 Subject: [PATCH 2/4] [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 b901a982d8e618d13049e5a804d19bce30fbac3c Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 9 May 2024 20:45:18 +0800 Subject: [PATCH 3/4] [GlobalOpt] Replace aliasee if it is not in use --- llvm/lib/Transforms/IPO/GlobalOpt.cpp | 21 ++++++++++++++++--- llvm/test/Transforms/GlobalOpt/alias-weak.ll | 5 ++--- .../cfi-nounwind-direct-call.ll | 4 ++-- .../LowerTypeTests/cfi-unwind-direct-call.ll | 8 +++---- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index b7c6d25657bc0..d6a8609b7c328 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,9 +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; if (hasUseOtherThanLLVMUsed(GA, U)) @@ -2245,6 +2253,13 @@ static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U, // define ... @a(...) Constant *Aliasee = GA.getAliasee(); GlobalValue *Target = cast(Aliasee->stripPointerCasts()); + // Don't perform the transform if the 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 ; diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll b/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll index 2795333effd76..f05befb10658b 100644 --- a/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll +++ b/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll @@ -121,7 +121,7 @@ attributes #6 = { noreturn nounwind } ; CHECK-LABEL: define dso_local noundef range(i32 0, 2) i32 @_Z10call_catchi ; CHECK-SAME: (i32 noundef [[NUM:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !type [[META4]] !type [[META5]] !type [[META6]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: store ptr @_Z9nothrow_ei.cfi_jt, ptr @catch_ptr, align 8, !tbaa [[TBAA7:![0-9]+]] +; CHECK-NEXT: store ptr @.cfi.jumptable, ptr @catch_ptr, align 8, !tbaa [[TBAA7:![0-9]+]] ; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp ne i32 [[NUM]], 0 ; CHECK-NEXT: [[DOT_I:%.*]] = zext i1 [[TOBOOL_NOT_I]] to i32 ; CHECK-NEXT: ret i32 [[DOT_I]] @@ -152,7 +152,7 @@ attributes #6 = { noreturn nounwind } ; ; ; CHECK: Function Attrs: naked nocf_check noinline nounwind -; CHECK-LABEL: define internal void @_Z9nothrow_ei.cfi_jt +; CHECK-LABEL: define private void @.cfi.jumptable ; CHECK-SAME: () #[[ATTR5:[0-9]+]] align 8 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(ptr nonnull @_Z9nothrow_ei) #[[ATTR7:[0-9]+]] diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll b/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll index 3e1f8b97e98b8..ca540a1cc5f97 100644 --- a/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll +++ b/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll @@ -174,8 +174,8 @@ attributes #8 = { noreturn nounwind } ; CHECK-LABEL: define dso_local void @_Z10call_catchi( ; CHECK-SAME: i32 noundef [[NUM:%.*]]) local_unnamed_addr #[[ATTR0]] personality ptr @__gxx_personality_v0 !type [[META4]] !type [[META5]] !type [[META6]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: store ptr @_Z7throw_ei.cfi_jt, ptr @catch_ptr, align 8, !tbaa [[TBAA11:![0-9]+]] -; CHECK-NEXT: invoke void @_Z7throw_ei.cfi_jt(i32 noundef [[NUM]]) #[[ATTR8:[0-9]+]] +; CHECK-NEXT: store ptr @.cfi.jumptable, ptr @catch_ptr, align 8, !tbaa [[TBAA11:![0-9]+]] +; CHECK-NEXT: invoke void @.cfi.jumptable(i32 noundef [[NUM]]) #[[ATTR8:[0-9]+]] ; CHECK-NEXT: to label [[TRY_CONT:%.*]] unwind label [[LPAD:%.*]], !callees [[META13:![0-9]+]] ; CHECK: lpad: ; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } @@ -220,7 +220,7 @@ attributes #8 = { noreturn nounwind } ; ; ; CHECK: Function Attrs: naked nocf_check noinline -; CHECK-LABEL: define internal void @_Z7throw_ei.cfi_jt( +; CHECK-LABEL: define private void @.cfi.jumptable( ; CHECK-SAME: ) #[[ATTR5:[0-9]+]] align 8 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(ptr nonnull @_Z7throw_ei) #[[ATTR6]] @@ -236,6 +236,6 @@ attributes #8 = { noreturn nounwind } ; CHECK: [[META10]] = !{!"Simple C++ TBAA"} ; CHECK: [[TBAA11]] = !{[[META12:![0-9]+]], [[META12]], i64 0} ; CHECK: [[META12]] = !{!"any pointer", [[META9]], i64 0} -; CHECK: [[META13]] = !{ptr @_Z7throw_ei.cfi_jt} +; CHECK: [[META13]] = !{ptr @.cfi.jumptable} ; CHECK: [[META14]] = !{} ;. From b4660c76859664d6f32c281867ba04ab14320e94 Mon Sep 17 00:00:00 2001 From: DianQK Date: Thu, 16 May 2024 13:37:17 +0800 Subject: [PATCH 4/4] Revert "[GlobalOpt] Replace aliasee if it is not in use" This reverts commit b901a982d8e618d13049e5a804d19bce30fbac3c. --- llvm/lib/Transforms/IPO/GlobalOpt.cpp | 21 +++---------------- llvm/test/Transforms/GlobalOpt/alias-weak.ll | 5 +++-- .../cfi-nounwind-direct-call.ll | 4 ++-- .../LowerTypeTests/cfi-unwind-direct-call.ll | 8 +++---- 4 files changed, 12 insertions(+), 26 deletions(-) diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp index d6a8609b7c328..b7c6d25657bc0 100644 --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -2215,17 +2215,6 @@ 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; @@ -2235,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)) @@ -2253,13 +2245,6 @@ static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U, // define ... @a(...) Constant *Aliasee = GA.getAliasee(); GlobalValue *Target = cast(Aliasee->stripPointerCasts()); - // Don't perform the transform if the 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 e24085f00d714..aec2a56313b12 100644 --- a/llvm/test/Transforms/GlobalOpt/alias-weak.ll +++ b/llvm/test/Transforms/GlobalOpt/alias-weak.ll @@ -25,12 +25,13 @@ define internal void @f1() { ret void } -; We can use `f2_alias` to replace `f2` because `b2` is not in use. +; 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() @@ -51,6 +52,6 @@ define internal void @f2() { ; 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 ; diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll b/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll index f05befb10658b..2795333effd76 100644 --- a/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll +++ b/llvm/test/Transforms/LowerTypeTests/cfi-nounwind-direct-call.ll @@ -121,7 +121,7 @@ attributes #6 = { noreturn nounwind } ; CHECK-LABEL: define dso_local noundef range(i32 0, 2) i32 @_Z10call_catchi ; CHECK-SAME: (i32 noundef [[NUM:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] !type [[META4]] !type [[META5]] !type [[META6]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: store ptr @.cfi.jumptable, ptr @catch_ptr, align 8, !tbaa [[TBAA7:![0-9]+]] +; CHECK-NEXT: store ptr @_Z9nothrow_ei.cfi_jt, ptr @catch_ptr, align 8, !tbaa [[TBAA7:![0-9]+]] ; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp ne i32 [[NUM]], 0 ; CHECK-NEXT: [[DOT_I:%.*]] = zext i1 [[TOBOOL_NOT_I]] to i32 ; CHECK-NEXT: ret i32 [[DOT_I]] @@ -152,7 +152,7 @@ attributes #6 = { noreturn nounwind } ; ; ; CHECK: Function Attrs: naked nocf_check noinline nounwind -; CHECK-LABEL: define private void @.cfi.jumptable +; CHECK-LABEL: define internal void @_Z9nothrow_ei.cfi_jt ; CHECK-SAME: () #[[ATTR5:[0-9]+]] align 8 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(ptr nonnull @_Z9nothrow_ei) #[[ATTR7:[0-9]+]] diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll b/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll index ca540a1cc5f97..3e1f8b97e98b8 100644 --- a/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll +++ b/llvm/test/Transforms/LowerTypeTests/cfi-unwind-direct-call.ll @@ -174,8 +174,8 @@ attributes #8 = { noreturn nounwind } ; CHECK-LABEL: define dso_local void @_Z10call_catchi( ; CHECK-SAME: i32 noundef [[NUM:%.*]]) local_unnamed_addr #[[ATTR0]] personality ptr @__gxx_personality_v0 !type [[META4]] !type [[META5]] !type [[META6]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: store ptr @.cfi.jumptable, ptr @catch_ptr, align 8, !tbaa [[TBAA11:![0-9]+]] -; CHECK-NEXT: invoke void @.cfi.jumptable(i32 noundef [[NUM]]) #[[ATTR8:[0-9]+]] +; CHECK-NEXT: store ptr @_Z7throw_ei.cfi_jt, ptr @catch_ptr, align 8, !tbaa [[TBAA11:![0-9]+]] +; CHECK-NEXT: invoke void @_Z7throw_ei.cfi_jt(i32 noundef [[NUM]]) #[[ATTR8:[0-9]+]] ; CHECK-NEXT: to label [[TRY_CONT:%.*]] unwind label [[LPAD:%.*]], !callees [[META13:![0-9]+]] ; CHECK: lpad: ; CHECK-NEXT: [[TMP0:%.*]] = landingpad { ptr, i32 } @@ -220,7 +220,7 @@ attributes #8 = { noreturn nounwind } ; ; ; CHECK: Function Attrs: naked nocf_check noinline -; CHECK-LABEL: define private void @.cfi.jumptable( +; CHECK-LABEL: define internal void @_Z7throw_ei.cfi_jt( ; CHECK-SAME: ) #[[ATTR5:[0-9]+]] align 8 { ; CHECK-NEXT: entry: ; CHECK-NEXT: tail call void asm sideeffect "jmp ${0:c}@plt\0Aint3\0Aint3\0Aint3\0A", "s"(ptr nonnull @_Z7throw_ei) #[[ATTR6]] @@ -236,6 +236,6 @@ attributes #8 = { noreturn nounwind } ; CHECK: [[META10]] = !{!"Simple C++ TBAA"} ; CHECK: [[TBAA11]] = !{[[META12:![0-9]+]], [[META12]], i64 0} ; CHECK: [[META12]] = !{!"any pointer", [[META9]], i64 0} -; CHECK: [[META13]] = !{ptr @.cfi.jumptable} +; CHECK: [[META13]] = !{ptr @_Z7throw_ei.cfi_jt} ; CHECK: [[META14]] = !{} ;.