mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-13 09:33:50 +00:00
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/trunk@181524 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9bd913c4c1
commit
95f885390b
@ -3041,6 +3041,105 @@ bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) {
|
|||||||
return true;
|
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 GlobalOpt::OptimizeGlobalAliases(Module &M) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
@ -3060,11 +3159,12 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) {
|
|||||||
bool hasOneUse = Target->hasOneUse() && Aliasee->hasOneUse();
|
bool hasOneUse = Target->hasOneUse() && Aliasee->hasOneUse();
|
||||||
|
|
||||||
// Make all users of the alias use the aliasee instead.
|
// Make all users of the alias use the aliasee instead.
|
||||||
if (!J->use_empty()) {
|
if (replaceAllNonLLVMUsedUsesWith(J, Aliasee)) {
|
||||||
J->replaceAllUsesWith(Aliasee);
|
|
||||||
++NumAliasesResolved;
|
++NumAliasesResolved;
|
||||||
Changed = true;
|
Changed = true;
|
||||||
}
|
}
|
||||||
|
if (!J->use_empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
// If the alias is externally visible, we may still be able to simplify it.
|
// If the alias is externally visible, we may still be able to simplify it.
|
||||||
if (!J->hasLocalLinkage()) {
|
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…
x
Reference in New Issue
Block a user