[llvm] r181524 - Don't replace an alias in llvm.used with its target.

Rafael EspĂ­ndola rafael.espindola at gmail.com
Thu May 9 10:30:40 PDT 2013


Hi Bill,

I think this should go in 3.3 as it is the patch that makes sure

extern "C" {
  __attribute__((used)) static void f() {
  }
}

produces a symbol named 'f'. Without it llvm would optimize away the
alias clang produces.

ccing Chris for the approval since there doesn't seem to be any other
code owner for this.


On 9 May 2013 13:23, Rafael Espindola <rafael.espindola at gmail.com> wrote:
> Author: rafael
> Date: Thu May  9 12:22:59 2013
> New Revision: 181524
>
> URL: http://llvm.org/viewvc/llvm-project?rev=181524&view=rev
> Log:
> Don't replace an alias in llvm.used with its target.
>
> When we replace an internal alias with its target, be careful not to
> replace the entry in llvm.used (and llvm.compiler_used).
>
> Added:
>     llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll
> Modified:
>     llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
>
> Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=181524&r1=181523&r2=181524&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Thu May  9 12:22:59 2013
> @@ -3041,6 +3041,105 @@ bool GlobalOpt::OptimizeGlobalCtorsList(
>    return true;
>  }
>
> +static Value::use_iterator getFirst(Value *V, SmallPtrSet<Use*, 8> &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;
> +
> +    User *Usr = *I;
> +    GlobalVariable *GV = dyn_cast<GlobalVariable>(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;
> +    }
> +  }
> +  return V->use_end();
> +}
> +
> +static bool replaceAllNonLLVMUsedUsesWith(Constant *Old, Constant *New);
> +
> +static bool replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From,
> +                                        Value *ToV, Use *U) {
> +  Constant *To = cast<Constant>(ToV);
> +
> +  SmallVector<Constant*, 8> NewOps;
> +  for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
> +    Constant *Op = CA->getOperand(i);
> +    NewOps.push_back(Op == From ? To : Op);
> +  }
> +
> +  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;
> +}
> +
> +static bool replaceUsesOfWithOnConstant(ConstantExpr *CE, Value *From,
> +                                        Value *ToV, Use *U) {
> +  Constant *To = cast<Constant>(ToV);
> +  SmallVector<Constant*, 8> NewOps;
> +  for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
> +    Constant *Op = CE->getOperand(i);
> +    NewOps.push_back(Op == From ? To : Op);
> +  }
> +
> +  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;
> +}
> +
> +static bool replaceUsesOfWithOnConstant(Constant *C, Value *From, Value *To,
> +                                        Use *U) {
> +  if (ConstantArray *CA = dyn_cast<ConstantArray>(C))
> +    return replaceUsesOfWithOnConstant(CA, From, To, U);
> +  if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
> +    return replaceUsesOfWithOnConstant(CE, From, To, U);
> +  C->replaceUsesOfWithOnConstant(From, To, U);
> +  return true;
> +}
> +
> +static bool replaceAllNonLLVMUsedUsesWith(Constant *Old, Constant *New) {
> +  SmallPtrSet<Use*, 8> Tried;
> +  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<Constant>(U.getUser())) {
> +      if (!isa<GlobalValue>(C)) {
> +        Ret |= replaceUsesOfWithOnConstant(C, Old, New, &U);
> +        continue;
> +      }
> +    }
> +
> +    U.set(New);
> +    Ret = true;
> +  }
> +  return Ret;
> +}
> +
>  bool GlobalOpt::OptimizeGlobalAliases(Module &M) {
>    bool Changed = false;
>
> @@ -3060,11 +3159,12 @@ bool GlobalOpt::OptimizeGlobalAliases(Mo
>      bool hasOneUse = Target->hasOneUse() && Aliasee->hasOneUse();
>
>      // Make all users of the alias use the aliasee instead.
> -    if (!J->use_empty()) {
> -      J->replaceAllUsesWith(Aliasee);
> +    if (replaceAllNonLLVMUsedUsesWith(J, Aliasee)) {
>        ++NumAliasesResolved;
>        Changed = true;
>      }
> +    if (!J->use_empty())
> +      continue;
>
>      // If the alias is externally visible, we may still be able to simplify it.
>      if (!J->hasLocalLinkage()) {
>
> Added: llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll?rev=181524&view=auto
> ==============================================================================
> --- llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll (added)
> +++ llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll Thu May  9 12:22:59 2013
> @@ -0,0 +1,42 @@
> +; RUN: opt < %s -globalopt -S | FileCheck %s
> +
> + at c = global i8 42
> +
> + at 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"
> +
> + at llvm.compiler_used = appending global [2 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @fa3 to i8*)], section "llvm.metadata"
> +
> + at 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]
> +
> + at other = global i32* bitcast (void ()* @fa to i32*)
> +; CHECK: @other = global i32* bitcast (void ()* @f to i32*)
> +
> + at fa = alias internal void ()* @f
> +; CHECK: @fa = alias internal void ()* @f
> +
> + at fa2 = alias internal void ()* @f
> +; CHECK-NOT: @fa2
> +
> + at fa3 = alias internal void ()* @f
> +; CHECK: @fa3
> +
> + at ca = alias internal i8* @c
> +; CHECK: @ca = alias internal i8* @c
> +
> +define void @f() {
> +  ret void
> +}
> +
> +define i8* @g() {
> +  ret i8* bitcast (void ()* @fa to i8*);
> +}
> +
> +define i8* @g2() {
> +  ret i8* bitcast (void ()* @fa2 to i8*);
> +}
> +
> +define i8* @h() {
> +  ret i8* @ca
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits



More information about the llvm-commits mailing list