From 4782b305c2ccc2b2e5a4cad65d7ffd15395d0727 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sun, 15 Feb 2009 09:56:08 +0000 Subject: [PATCH] If the target of an alias has internal linkage, then the alias can be morphed into the target. Implement this transform, and fix a crash in the existing transform at the same time. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@64583 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/IPO/GlobalOpt.cpp | 62 ++++++++++++++++--- .../GlobalOpt/2009-02-15-BitcastAlias.ll | 10 +++ .../GlobalOpt/2009-02-15-ResolveAlias.ll | 12 ++++ 3 files changed, 77 insertions(+), 7 deletions(-) create mode 100644 test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll create mode 100644 test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 7f636c92701..4208e9044e8 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -50,6 +50,8 @@ STATISTIC(NumShrunkToBool , "Number of global vars shrunk to booleans"); STATISTIC(NumFastCallFns , "Number of functions converted to fastcc"); STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated"); STATISTIC(NumNestRemoved , "Number of nest attributes removed"); +STATISTIC(NumAliasesResolved, "Number of global aliases resolved"); +STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated"); namespace { struct VISIBILITY_HIDDEN GlobalOpt : public ModulePass { @@ -2373,15 +2375,61 @@ bool GlobalOpt::ResolveAliases(Module &M) { bool Changed = false; for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); - I != E; ++I) { - if (I->use_empty()) + I != E;) { + Module::alias_iterator J = I++; + // If the aliasee may change at link time, nothing can be done - bail out. + if (J->mayBeOverridden()) continue; - if (const GlobalValue *GV = I->resolveAliasedGlobal()) - if (GV != I) { - I->replaceAllUsesWith(const_cast(GV)); - Changed = true; - } + Constant *Aliasee = J->getAliasee(); + GlobalValue *Target = cast(Aliasee->stripPointerCasts()); + bool hasOneUse = Target->hasOneUse() && Aliasee->hasOneUse(); + + // Make all users of the alias use the aliasee instead. + if (!J->use_empty()) { + J->replaceAllUsesWith(Aliasee); + ++NumAliasesResolved; + Changed = true; + } + + // If the aliasee has internal linkage, give it the name and linkage + // of the alias, and delete the alias. This turns: + // define internal ... @f(...) + // @a = alias ... @f + // into: + // define ... @a(...) + if (!Target->hasInternalLinkage()) + continue; + + // The transform is only useful if the alias does not have internal linkage. + if (J->hasInternalLinkage()) + continue; + + // Be conservative and do not perform the transform if multiple aliases + // potentially target the aliasee. TODO: Make this more aggressive. + if (!hasOneUse) + continue; + + // Do not perform the transform if it would change the visibility. + if (J->getVisibility() != Target->getVisibility()) + continue; + + // Do not perform the transform if it would change the section. + if (J->hasSection() != Target->hasSection() || + (J->hasSection() && J->getSection() != Target->getSection())) + continue; + + // Give the aliasee the name and linkage of the alias. + Target->takeName(J); + Target->setLinkage(J->getLinkage()); + + // The alignment is the only remaining attribute that may not match. + Target->setAlignment(std::max(J->getAlignment(), Target->getAlignment())); + + // Delete the alias. + M.getAliasList().erase(J); + ++NumAliasesRemoved; + Changed = true; } return Changed; diff --git a/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll b/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll new file mode 100644 index 00000000000..e59c8df5570 --- /dev/null +++ b/test/Transforms/GlobalOpt/2009-02-15-BitcastAlias.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | opt -globalopt + +@g = external global i32 + +@a = alias bitcast (i32* @g to i8*) + +define void @f() { + %tmp = load i8* @a + ret void +} diff --git a/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll b/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll new file mode 100644 index 00000000000..f042e59c19d --- /dev/null +++ b/test/Transforms/GlobalOpt/2009-02-15-ResolveAlias.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | opt -globalopt | llvm-dis | grep {define void @a} + +define internal void @f() { + ret void +} + +@a = alias void ()* @f + +define void @g() { + call void()* @a() + ret void +} -- 2.34.1