Inliner: Non-local functions in COMDATs shouldn't be dropped

A function with discardable linkage cannot be discarded if its a member
of a COMDAT group without considering all the other COMDAT members as
well.  This sort of thing is already handled by GlobalOpt/GlobalDCE.

This fixes PR21206.

llvm-svn: 219335
This commit is contained in:
David Majnemer 2014-10-08 19:32:32 +00:00
parent ce1af1a201
commit ac07703842
2 changed files with 25 additions and 0 deletions

View File

@ -670,6 +670,13 @@ bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {
if (!F->isDefTriviallyDead())
continue;
// It is unsafe to drop a function with discardable linkage from a COMDAT
// without also dropping the other members of the COMDAT.
// The inliner doesn't visit non-function entities which are in COMDAT
// groups so it is unsafe to do so *unless* the linkage is local.
if (!F->hasLocalLinkage() && F->hasComdat())
continue;
// Remove any call graph edges from the function to its callees.
CGN->removeAllCalledFunctions();

View File

@ -0,0 +1,18 @@
; RUN: opt < %s -inline -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() {
ret void()* @foo
}