diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 4a9cb27b034..72ba250f470 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -3041,107 +3041,168 @@ bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) { return true; } -static Value::use_iterator getFirst(Value *V, SmallPtrSet &Tried) { - for (Value::use_iterator I = V->use_begin(), E = V->use_end(); I != E; ++I) { - Use *U = &I.getUse(); - if (Tried.count(U)) - continue; +/// \brief Given "llvm.used" or "llvm.compiler_used" as a global name, collect +/// the initializer elements of that global in Set and return the global itself. +static GlobalVariable * +collectUsedGlobalVariables(const Module &M, const char *Name, + SmallPtrSet &Set) { + GlobalVariable *GV = M.getGlobalVariable(Name); + if (!GV || !GV->hasInitializer()) + return GV; - User *Usr = *I; - GlobalVariable *GV = dyn_cast(Usr); - if (!GV || !GV->hasName()) { - Tried.insert(U); - return I; - } - - StringRef Name = GV->getName(); - if (Name != "llvm.used" && Name != "llvm.compiler_used") { - Tried.insert(U); - return I; - } + const ConstantArray *Init = cast(GV->getInitializer()); + for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) { + Value *Op = Init->getOperand(I); + GlobalValue *G = cast(Op->stripPointerCastsNoFollowAliases()); + Set.insert(G); } - return V->use_end(); + return GV; } -static bool replaceAllNonLLVMUsedUsesWith(Constant *Old, Constant *New); +static int compareNames(const void *A, const void *B) { + const GlobalValue *VA = *reinterpret_cast(A); + const GlobalValue *VB = *reinterpret_cast(B); + if (VA->getName() < VB->getName()) + return -1; + if (VB->getName() < VA->getName()) + return 1; + return 0; +} -static bool replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From, - Value *ToV, Use *U) { - Constant *To = cast(ToV); +static void setUsedInitializer(GlobalVariable &V, + SmallPtrSet Init) { + SmallVector UsedArray; + PointerType *Int8PtrTy = Type::getInt8PtrTy(V.getContext()); - SmallVector NewOps; - for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) { - Constant *Op = CA->getOperand(i); - NewOps.push_back(Op == From ? To : Op); + for (SmallPtrSet::iterator I = Init.begin(), E = Init.end(); + I != E; ++I) { + Constant *Cast = llvm::ConstantExpr::getBitCast(*I, Int8PtrTy); + UsedArray.push_back(Cast); } + // Sort to get deterministic order. + array_pod_sort(UsedArray.begin(), UsedArray.end(), compareNames); + ArrayType *ATy = ArrayType::get(Int8PtrTy, UsedArray.size()); - Constant *Replacement = ConstantArray::get(CA->getType(), NewOps); - assert(Replacement != CA && "CA didn't contain From!"); - - bool Ret = replaceAllNonLLVMUsedUsesWith(CA, Replacement); - if (Replacement->use_empty()) - Replacement->destroyConstant(); - if (CA->use_empty()) - CA->destroyConstant(); - return Ret; + Module *M = V.getParent(); + V.removeFromParent(); + GlobalVariable *NV = + new GlobalVariable(*M, ATy, false, llvm::GlobalValue::AppendingLinkage, + llvm::ConstantArray::get(ATy, UsedArray), ""); + NV->takeName(&V); + NV->setSection("llvm.metadata"); + delete &V; } -static bool replaceUsesOfWithOnConstant(ConstantExpr *CE, Value *From, - Value *ToV, Use *U) { - Constant *To = cast(ToV); - SmallVector NewOps; - for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) { - Constant *Op = CE->getOperand(i); - NewOps.push_back(Op == From ? To : Op); +namespace { +/// \brief An easy to access representation of llvm.used and llvm.compiler_used. +class LLVMUsed { + SmallPtrSet Used; + SmallPtrSet CompilerUsed; + GlobalVariable *UsedV; + GlobalVariable *CompilerUsedV; + +public: + LLVMUsed(const Module &M) { + UsedV = collectUsedGlobalVariables(M, "llvm.used", Used); + CompilerUsedV = + collectUsedGlobalVariables(M, "llvm.compiler_used", CompilerUsed); } + typedef SmallPtrSet::iterator iterator; + iterator usedBegin() { return Used.begin(); } + iterator usedEnd() { return Used.end(); } + iterator compilerUsedBegin() { return CompilerUsed.begin(); } + iterator compilerUsedEnd() { return CompilerUsed.end(); } + bool usedCount(GlobalValue *GV) const { return Used.count(GV); } + bool compilerUsedCount(GlobalValue *GV) const { + return CompilerUsed.count(GV); + } + bool usedErase(GlobalValue *GV) { return Used.erase(GV); } + bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); } + bool usedInsert(GlobalValue *GV) { return Used.insert(GV); } + bool compilerUsedInsert(GlobalValue *GV) { return CompilerUsed.insert(GV); } - Constant *Replacement = CE->getWithOperands(NewOps); - assert(Replacement != CE && "CE didn't contain From!"); - - bool Ret = replaceAllNonLLVMUsedUsesWith(CE, Replacement); - if (Replacement->use_empty()) - Replacement->destroyConstant(); - if (CE->use_empty()) - CE->destroyConstant(); - return Ret; + void syncVariablesAndSets() { + if (UsedV) + setUsedInitializer(*UsedV, Used); + if (CompilerUsedV) + setUsedInitializer(*CompilerUsedV, CompilerUsed); + } +}; } -static bool replaceUsesOfWithOnConstant(Constant *C, Value *From, Value *To, - Use *U) { - if (ConstantArray *CA = dyn_cast(C)) - return replaceUsesOfWithOnConstant(CA, From, To, U); - if (ConstantExpr *CE = dyn_cast(C)) - return replaceUsesOfWithOnConstant(CE, From, To, U); - C->replaceUsesOfWithOnConstant(From, To, U); - return true; +static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U) { + if (GA.use_empty()) // No use at all. + return false; + + assert((!U.usedCount(&GA) || !U.compilerUsedCount(&GA)) && + "We should have removed the duplicated " + "element from llvm.compiler_used"); + if (!GA.hasOneUse()) + // Strictly more than one use. So at least one is not in llvm.used and + // llvm.compiler_used. + return true; + + // Exactly one use. Check if it is in llvm.used or llvm.compiler_used. + return !U.usedCount(&GA) && !U.compilerUsedCount(&GA); } -static bool replaceAllNonLLVMUsedUsesWith(Constant *Old, Constant *New) { - SmallPtrSet Tried; +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()) + return true; + + return U.usedCount(&GA) || U.compilerUsedCount(&GA); +} + +static bool hasUsesToReplace(GlobalAlias &GA, LLVMUsed &U, bool &RenameTarget) { + RenameTarget = false; bool Ret = false; - for (;;) { - Value::use_iterator I = getFirst(Old, Tried); - if (I == Old->use_end()) - break; - Use &U = I.getUse(); - - // Must handle Constants specially, we cannot call replaceUsesOfWith on a - // constant because they are uniqued. - if (Constant *C = dyn_cast(U.getUser())) { - if (!isa(C)) { - Ret |= replaceUsesOfWithOnConstant(C, Old, New, &U); - continue; - } - } - - U.set(New); + if (hasUseOtherThanLLVMUsed(GA, U)) Ret = true; - } - return Ret; + + // If the alias is externally visible, we may still be able to simplify it. + 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: + // 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)) + return Ret; + + RenameTarget = true; + return true; } bool GlobalOpt::OptimizeGlobalAliases(Module &M) { bool Changed = false; + LLVMUsed Used(M); + + for (SmallPtrSet::iterator I = Used.usedBegin(), + E = Used.usedEnd(); + I != E; ++I) + Used.compilerUsedErase(*I); for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E;) { @@ -3156,45 +3217,40 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) { Constant *Aliasee = J->getAliasee(); GlobalValue *Target = cast(Aliasee->stripPointerCasts()); Target->removeDeadConstantUsers(); - bool hasOneUse = Target->hasOneUse() && Aliasee->hasOneUse(); // Make all users of the alias use the aliasee instead. - if (replaceAllNonLLVMUsedUsesWith(J, Aliasee)) { - ++NumAliasesResolved; - Changed = true; - } - if (!J->use_empty()) + bool RenameTarget; + if (!hasUsesToReplace(*J, Used, RenameTarget)) continue; - // If the alias is externally visible, we may still be able to simplify it. - if (!J->hasLocalLinkage()) { - // 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->hasLocalLinkage()) - continue; - - // 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 (!hasOneUse) - continue; + J->replaceAllUsesWith(Aliasee); + ++NumAliasesResolved; + Changed = true; + if (RenameTarget) { // Give the aliasee the name, linkage and other attributes of the alias. Target->takeName(J); Target->setLinkage(J->getLinkage()); Target->GlobalValue::copyAttributesFrom(J); + + if (Used.usedErase(J)) + Used.usedInsert(Target); + + if (Used.compilerUsedErase(J)) + Used.compilerUsedInsert(Target); } + if (mayHaveOtherReferences(*J, Used)) + continue; + // Delete the alias. M.getAliasList().erase(J); ++NumAliasesRemoved; Changed = true; } + Used.syncVariablesAndSets(); + return Changed; } diff --git a/test/Transforms/GlobalOpt/alias-used.ll b/test/Transforms/GlobalOpt/alias-used.ll index f91579bf050..758e469b3c8 100644 --- a/test/Transforms/GlobalOpt/alias-used.ll +++ b/test/Transforms/GlobalOpt/alias-used.ll @@ -2,16 +2,21 @@ @c = global i8 42 -@llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca], section "llvm.metadata" -; CHECK: @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca], section "llvm.metadata" +@i = internal global i8 42 +; CHECK: @ia = internal global i8 42 +@ia = alias internal i8* @i -@llvm.compiler_used = appending global [2 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @fa3 to i8*)], section "llvm.metadata" +@llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca], section "llvm.metadata" +; CHECK-DAG: @llvm.used = appending global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca], section "llvm.metadata" + +@llvm.compiler_used = appending global [4 x i8*] [i8* bitcast (void ()* @fa3 to i8*), i8* bitcast (void ()* @fa to i8*), i8* @ia, i8* @i], section "llvm.metadata" +; CHECK-DAG: @llvm.compiler_used = appending global [2 x i8*] [i8* bitcast (void ()* @fa3 to i8*), i8* @ia], section "llvm.metadata" @sameAsUsed = global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca] -; CHECK: @sameAsUsed = global [3 x i8*] [i8* bitcast (void ()* @f to i8*), i8* bitcast (void ()* @f to i8*), i8* @c] +; CHECK-DAG: @sameAsUsed = global [3 x i8*] [i8* bitcast (void ()* @f to i8*), i8* bitcast (void ()* @f to i8*), i8* @c] @other = global i32* bitcast (void ()* @fa to i32*) -; CHECK: @other = global i32* bitcast (void ()* @f to i32*) +; CHECK-DAG: @other = global i32* bitcast (void ()* @f to i32*) @fa = alias internal void ()* @f ; CHECK: @fa = alias internal void ()* @f