diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -2204,22 +2204,11 @@ 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(GlobalAlias &GA, const LLVMUsed &U) { - if (!GA.hasLocalLinkage()) +static bool mayHaveOtherReferences(GlobalValue &GV, const LLVMUsed &U) { + if (!GV.hasLocalLinkage()) return true; - return U.usedCount(&GA) || U.compilerUsedCount(&GA); + return U.usedCount(&GV) || U.compilerUsedCount(&GV); } static bool hasUsesToReplace(GlobalAlias &GA, const LLVMUsed &U, @@ -2233,21 +2222,16 @@ if (!mayHaveOtherReferences(GA, U)) return Ret; - // If the aliasee has internal linkage, give it the name and linkage - // of the alias, and delete the alias. This turns: + // If the aliasee has internal linkage and no other references (e.g., + // @llvm.used, @llvm.compiler.used), give it the name and linkage of the + // alias, and delete the alias. This turns: // define internal ... @f(...) // @a = alias ... @f // into: // define ... @a(...) Constant *Aliasee = GA.getAliasee(); GlobalValue *Target = cast(Aliasee->stripPointerCasts()); - if (!Target->hasLocalLinkage()) - return Ret; - - // Do not perform the transform if multiple aliases potentially target the - // aliasee. This check also ensures that it is safe to replace the section - // and other attributes of the aliasee with those of the alias. - if (hasMoreThanOneUseOtherThanLLVMUsed(*Target, U)) + if (mayHaveOtherReferences(*Target, U)) return Ret; RenameTarget = true; diff --git a/llvm/test/Transforms/GlobalOpt/X86/alias-used-with-asm.ll b/llvm/test/Transforms/GlobalOpt/X86/alias-used-with-asm.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/X86/alias-used-with-asm.ll @@ -0,0 +1,22 @@ +; RUN: opt < %s -passes=globalopt -S | FileCheck %s + +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +module asm ".global foo1" +module asm "foo1: jmp bar1" +module asm ".global foo2" +module asm "foo2: jmp bar2" + +; The `llvm.compiler.used` indicates that `foo1` and `foo2` have associated symbol references in asm. +; Checking globalopt does not remove these two symbols. +@llvm.compiler.used = appending global [2 x ptr] [ptr @bar1, ptr @bar2], section "llvm.metadata" +; CHECK: @llvm.compiler.used = appending global [2 x ptr] [ptr @bar1, ptr @bar2], section "llvm.metadata" + +@bar2 = internal alias void (), ptr @bar1 +; CHECK: @bar2 = internal alias void (), ptr @bar1 + +define internal void @bar1() { +; CHECK: define internal void @bar1() + ret void +} diff --git a/llvm/test/Transforms/GlobalOpt/alias-used-address-space.ll b/llvm/test/Transforms/GlobalOpt/alias-used-address-space.ll --- a/llvm/test/Transforms/GlobalOpt/alias-used-address-space.ll +++ b/llvm/test/Transforms/GlobalOpt/alias-used-address-space.ll @@ -5,19 +5,20 @@ @c = hidden addrspace(1) global i8 42 @i = internal addrspace(1) global i8 42 - -; CHECK: @ia = internal addrspace(1) global i8 42 -@ia = internal alias i8, ptr addrspace(1) @i +; CHECK: @i = internal addrspace(1) global i8 42 @llvm.used = appending global [1 x ptr] [ptr addrspacecast (ptr addrspace(1) @ca to ptr)], section "llvm.metadata" ; CHECK-DAG: @llvm.used = appending global [1 x ptr] [ptr addrspacecast (ptr addrspace(1) @ca to ptr)], section "llvm.metadata" @llvm.compiler.used = appending global [2 x ptr] [ptr addrspacecast(ptr addrspace(1) @ia to ptr), ptr addrspacecast (ptr addrspace(1) @i to ptr)], section "llvm.metadata" -; CHECK-DAG: @llvm.compiler.used = appending global [1 x ptr] [ptr addrspacecast (ptr addrspace(1) @ia to ptr)], section "llvm.metadata" +; CHECK-DAG: @llvm.compiler.used = appending global [2 x ptr] [ptr addrspacecast (ptr addrspace(1) @i to ptr), ptr addrspacecast (ptr addrspace(1) @ia to ptr)], section "llvm.metadata" @sameAsUsed = global [1 x ptr] [ptr addrspacecast(ptr addrspace(1) @ca to ptr)] ; CHECK-DAG: @sameAsUsed = local_unnamed_addr global [1 x ptr] [ptr addrspacecast (ptr addrspace(1) @c to ptr)] +@ia = internal alias i8, ptr addrspace(1) @i +; CHECK: @ia = internal alias i8, ptr addrspace(1) @i + @ca = internal alias i8, ptr addrspace(1) @c ; CHECK: @ca = internal alias i8, ptr addrspace(1) @c diff --git a/llvm/test/Transforms/GlobalOpt/alias-used.ll b/llvm/test/Transforms/GlobalOpt/alias-used.ll --- a/llvm/test/Transforms/GlobalOpt/alias-used.ll +++ b/llvm/test/Transforms/GlobalOpt/alias-used.ll @@ -2,15 +2,16 @@ @c = dso_local global i8 42 +; CHECK: @i = internal global i8 42 @i = internal global i8 42 -; CHECK: @ia = internal global i8 42 +; CHECK-DAG: @ia = internal alias i8, ptr @i @ia = internal alias i8, ptr @i @llvm.used = appending global [3 x ptr] [ptr @fa, ptr @f, ptr @ca], section "llvm.metadata" ; CHECK-DAG: @llvm.used = appending global [3 x ptr] [ptr @ca, ptr @f, ptr @fa], section "llvm.metadata" @llvm.compiler.used = appending global [4 x ptr] [ptr @fa3, ptr @fa, ptr @ia, ptr @i], section "llvm.metadata" -; CHECK-DAG: @llvm.compiler.used = appending global [2 x ptr] [ptr @fa3, ptr @ia], section "llvm.metadata" +; CHECK-DAG: @llvm.compiler.used = appending global [3 x ptr] [ptr @fa3, ptr @i, ptr @ia], section "llvm.metadata" @sameAsUsed = global [3 x ptr] [ptr @fa, ptr @f, ptr @ca] ; CHECK-DAG: @sameAsUsed = local_unnamed_addr global [3 x ptr] [ptr @f, ptr @f, ptr @c]