mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-17 18:24:34 +00:00
GlobalOpt: Don't drop unused memberes of a Comdat
A linkonce_odr member of a COMDAT shouldn't be dropped if we need to keep the entire COMDAT group. This fixes PR21191. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219283 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -88,6 +88,7 @@ namespace {
|
|||||||
|
|
||||||
const DataLayout *DL;
|
const DataLayout *DL;
|
||||||
TargetLibraryInfo *TLI;
|
TargetLibraryInfo *TLI;
|
||||||
|
SmallSet<const Comdat *, 8> NotDiscardableComdats;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1908,8 +1909,11 @@ bool GlobalOpt::OptimizeFunctions(Module &M) {
|
|||||||
// Functions without names cannot be referenced outside this module.
|
// Functions without names cannot be referenced outside this module.
|
||||||
if (!F->hasName() && !F->isDeclaration() && !F->hasLocalLinkage())
|
if (!F->hasName() && !F->isDeclaration() && !F->hasLocalLinkage())
|
||||||
F->setLinkage(GlobalValue::InternalLinkage);
|
F->setLinkage(GlobalValue::InternalLinkage);
|
||||||
|
|
||||||
|
const Comdat *C = F->getComdat();
|
||||||
|
bool inComdat = C && NotDiscardableComdats.count(C);
|
||||||
F->removeDeadConstantUsers();
|
F->removeDeadConstantUsers();
|
||||||
if (F->isDefTriviallyDead()) {
|
if ((!inComdat || F->hasLocalLinkage()) && F->isDefTriviallyDead()) {
|
||||||
F->eraseFromParent();
|
F->eraseFromParent();
|
||||||
Changed = true;
|
Changed = true;
|
||||||
++NumFnDeleted;
|
++NumFnDeleted;
|
||||||
@@ -1941,12 +1945,6 @@ bool GlobalOpt::OptimizeFunctions(Module &M) {
|
|||||||
bool GlobalOpt::OptimizeGlobalVars(Module &M) {
|
bool GlobalOpt::OptimizeGlobalVars(Module &M) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
SmallSet<const Comdat *, 8> NotDiscardableComdats;
|
|
||||||
for (const GlobalVariable &GV : M.globals())
|
|
||||||
if (const Comdat *C = GV.getComdat())
|
|
||||||
if (!GV.isDiscardableIfUnused())
|
|
||||||
NotDiscardableComdats.insert(C);
|
|
||||||
|
|
||||||
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
|
for (Module::global_iterator GVI = M.global_begin(), E = M.global_end();
|
||||||
GVI != E; ) {
|
GVI != E; ) {
|
||||||
GlobalVariable *GV = GVI++;
|
GlobalVariable *GV = GVI++;
|
||||||
@@ -1963,7 +1961,7 @@ bool GlobalOpt::OptimizeGlobalVars(Module &M) {
|
|||||||
|
|
||||||
if (GV->isDiscardableIfUnused()) {
|
if (GV->isDiscardableIfUnused()) {
|
||||||
if (const Comdat *C = GV->getComdat())
|
if (const Comdat *C = GV->getComdat())
|
||||||
if (NotDiscardableComdats.count(C))
|
if (NotDiscardableComdats.count(C) && !GV->hasLocalLinkage())
|
||||||
continue;
|
continue;
|
||||||
Changed |= ProcessGlobal(GV, GVI);
|
Changed |= ProcessGlobal(GV, GVI);
|
||||||
}
|
}
|
||||||
@@ -3047,6 +3045,20 @@ bool GlobalOpt::runOnModule(Module &M) {
|
|||||||
while (LocalChange) {
|
while (LocalChange) {
|
||||||
LocalChange = false;
|
LocalChange = false;
|
||||||
|
|
||||||
|
NotDiscardableComdats.clear();
|
||||||
|
for (const GlobalVariable &GV : M.globals())
|
||||||
|
if (const Comdat *C = GV.getComdat())
|
||||||
|
if (!GV.isDiscardableIfUnused() || !GV.use_empty())
|
||||||
|
NotDiscardableComdats.insert(C);
|
||||||
|
for (Function &F : M)
|
||||||
|
if (const Comdat *C = F.getComdat())
|
||||||
|
if (!F.isDefTriviallyDead())
|
||||||
|
NotDiscardableComdats.insert(C);
|
||||||
|
for (GlobalAlias &GA : M.aliases())
|
||||||
|
if (const Comdat *C = GA.getComdat())
|
||||||
|
if (!GA.isDiscardableIfUnused() || !GA.use_empty())
|
||||||
|
NotDiscardableComdats.insert(C);
|
||||||
|
|
||||||
// Delete functions that are trivially dead, ccc -> fastcc
|
// Delete functions that are trivially dead, ccc -> fastcc
|
||||||
LocalChange |= OptimizeFunctions(M);
|
LocalChange |= OptimizeFunctions(M);
|
||||||
|
|
||||||
|
19
test/Transforms/GlobalOpt/pr21191.ll
Normal file
19
test/Transforms/GlobalOpt/pr21191.ll
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
; RUN: opt < %s -globalopt -S | FileCheck %s
|
||||||
|
|
||||||
|
$c = comdat any
|
||||||
|
; CHECK: $c = comdat any
|
||||||
|
|
||||||
|
define linkonce_odr void @foo() comdat $c {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
; CHECK: define linkonce_odr void @foo() comdat $c
|
||||||
|
|
||||||
|
define linkonce_odr void @bar() comdat $c {
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
; CHECK: define linkonce_odr void @bar() comdat $c
|
||||||
|
|
||||||
|
define void @zed() {
|
||||||
|
call void @foo()
|
||||||
|
ret void
|
||||||
|
}
|
Reference in New Issue
Block a user