<p dir="ltr">Thanks! </p>
<div class="gmail_quote">On May 5, 2015 7:12 PM, "David Majnemer" <<a href="mailto:david.majnemer@gmail.com">david.majnemer@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: majnemer<br>
Date: Tue May 5 15:14:22 2015<br>
New Revision: 236539<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=236539&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=236539&view=rev</a><br>
Log:<br>
[Inliner] Discard empty COMDAT groups<br>
<br>
COMDAT groups which have become rendered unused because of inline are<br>
discardable if we can prove that we've made the group empty.<br>
<br>
This fixes PR22285.<br>
<br>
Added:<br>
llvm/trunk/test/Transforms/Inline/pr22285.ll<br>
Modified:<br>
llvm/trunk/lib/Transforms/IPO/Inliner.cpp<br>
<br>
Modified: llvm/trunk/lib/Transforms/IPO/Inliner.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=236539&r1=236538&r2=236539&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/Inliner.cpp?rev=236539&r1=236538&r2=236539&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/IPO/Inliner.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/IPO/Inliner.cpp Tue May 5 15:14:22 2015<br>
@@ -625,6 +625,21 @@ bool Inliner::doFinalization(CallGraph &<br>
/// Remove dead functions that are not included in DNR (Do Not Remove) list.<br>
bool Inliner::removeDeadFunctions(CallGraph &CG, bool AlwaysInlineOnly) {<br>
SmallVector<CallGraphNode*, 16> FunctionsToRemove;<br>
+ SmallVector<CallGraphNode *, 16> DeadFunctionsInComdats;<br>
+ SmallDenseMap<const Comdat *, int, 16> ComdatEntriesAlive;<br>
+<br>
+ auto RemoveCGN = [&](CallGraphNode *CGN) {<br>
+ // Remove any call graph edges from the function to its callees.<br>
+ CGN->removeAllCalledFunctions();<br>
+<br>
+ // Remove any edges from the external node to the function's call graph<br>
+ // node. These edges might have been made irrelegant due to<br>
+ // optimization of the program.<br>
+ CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);<br>
+<br>
+ // Removing the node for callee from the call graph and delete it.<br>
+ FunctionsToRemove.push_back(CGN);<br>
+ };<br>
<br>
// Scan for all of the functions, looking for ones that should now be removed<br>
// from the program. Insert the dead ones in the FunctionsToRemove set.<br>
@@ -651,20 +666,45 @@ bool Inliner::removeDeadFunctions(CallGr<br>
// without also dropping the other members of the COMDAT.<br>
// The inliner doesn't visit non-function entities which are in COMDAT<br>
// groups so it is unsafe to do so *unless* the linkage is local.<br>
- if (!F->hasLocalLinkage() && F->hasComdat())<br>
- continue;<br>
-<br>
- // Remove any call graph edges from the function to its callees.<br>
- CGN->removeAllCalledFunctions();<br>
+ if (!F->hasLocalLinkage()) {<br>
+ if (const Comdat *C = F->getComdat()) {<br>
+ --ComdatEntriesAlive[C];<br>
+ DeadFunctionsInComdats.push_back(CGN);<br>
+ continue;<br>
+ }<br>
+ }<br>
<br>
- // Remove any edges from the external node to the function's call graph<br>
- // node. These edges might have been made irrelegant due to<br>
- // optimization of the program.<br>
- CG.getExternalCallingNode()->removeAnyCallEdgeTo(CGN);<br>
+ RemoveCGN(CGN);<br>
+ }<br>
+ if (!DeadFunctionsInComdats.empty()) {<br>
+ // Count up all the entities in COMDAT groups<br>
+ auto ComdatGroupReferenced = [&](const Comdat *C) {<br>
+ auto I = ComdatEntriesAlive.find(C);<br>
+ if (I != ComdatEntriesAlive.end())<br>
+ ++(I->getSecond());<br>
+ };<br>
+ for (const Function &F : CG.getModule())<br>
+ if (const Comdat *C = F.getComdat())<br>
+ ComdatGroupReferenced(C);<br>
+ for (const GlobalVariable &GV : CG.getModule().globals())<br>
+ if (const Comdat *C = GV.getComdat())<br>
+ ComdatGroupReferenced(C);<br>
+ for (const GlobalAlias &GA : CG.getModule().aliases())<br>
+ if (const Comdat *C = GA.getComdat())<br>
+ ComdatGroupReferenced(C);<br>
+ for (CallGraphNode *CGN : DeadFunctionsInComdats) {<br>
+ Function *F = CGN->getFunction();<br>
+ const Comdat *C = F->getComdat();<br>
+ int NumAlive = ComdatEntriesAlive[C];<br>
+ // We can remove functions in a COMDAT group if the entire group is dead.<br>
+ assert(NumAlive >= 0);<br>
+ if (NumAlive > 0)<br>
+ continue;<br>
<br>
- // Removing the node for callee from the call graph and delete it.<br>
- FunctionsToRemove.push_back(CGN);<br>
+ RemoveCGN(CGN);<br>
+ }<br>
}<br>
+<br>
if (FunctionsToRemove.empty())<br>
return false;<br>
<br>
<br>
Added: llvm/trunk/test/Transforms/Inline/pr22285.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/pr22285.ll?rev=236539&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Inline/pr22285.ll?rev=236539&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Transforms/Inline/pr22285.ll (added)<br>
+++ llvm/trunk/test/Transforms/Inline/pr22285.ll Tue May 5 15:14:22 2015<br>
@@ -0,0 +1,15 @@<br>
+; RUN: opt < %s -inline -S | FileCheck %s<br>
+<br>
+$f1 = comdat any<br>
+; CHECK-NOT: $f1 = comdat any<br>
+<br>
+define void @f2() {<br>
+ call void @f1()<br>
+ ret void<br>
+}<br>
+; CHECK-LABEL: define void @f2<br>
+<br>
+define linkonce_odr void @f1() comdat {<br>
+ ret void<br>
+}<br>
+; CHECK-NOT: define linkonce_odr void @f1() comdat<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>