mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-12 13:30:51 +00:00
Merging r181524:
------------------------------------------------------------------------ r181524 | rafael | 2013-05-09 10:22:59 -0700 (Thu, 09 May 2013) | 4 lines 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). ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_33@181909 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b1ecefd0b5
commit
5b85a9b5ad
@ -3041,6 +3041,105 @@ bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) {
|
||||
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(Module &M) {
|
||||
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()) {
|
||||
|
42
test/Transforms/GlobalOpt/alias-used.ll
Normal file
42
test/Transforms/GlobalOpt/alias-used.ll
Normal file
@ -0,0 +1,42 @@
|
||||
; RUN: opt < %s -globalopt -S | FileCheck %s
|
||||
|
||||
@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"
|
||||
|
||||
@llvm.compiler_used = appending global [2 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @fa3 to i8*)], 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]
|
||||
|
||||
@other = global i32* bitcast (void ()* @fa to i32*)
|
||||
; CHECK: @other = global i32* bitcast (void ()* @f to i32*)
|
||||
|
||||
@fa = alias internal void ()* @f
|
||||
; CHECK: @fa = alias internal void ()* @f
|
||||
|
||||
@fa2 = alias internal void ()* @f
|
||||
; CHECK-NOT: @fa2
|
||||
|
||||
@fa3 = alias internal void ()* @f
|
||||
; CHECK: @fa3
|
||||
|
||||
@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
|
||||
}
|
Loading…
Reference in New Issue
Block a user