llvm.org GIT mirror llvm / 0b88030
[PM] Teach the always inliner in the new pass manager to support removing fully-dead comdats without removing dead entries in comdats with live members. This factors the core logic out of the current inliner's internals to a reusable utility and leverages that in both places. The factored out code should also be (minorly) more efficient in cases where we have very few dead functions or dead comdats to consider. I've added a test case to cover this behavior of the always inliner. This is the last significant bug in the new PM's always inliner I've found (so far). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@290557 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 2 years ago
5 changed file(s) with 137 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
6464 /// \brief Adds global values to the llvm.compiler.used list.
6565 void appendToCompilerUsed(Module &M, ArrayRef Values);
6666
67 /// Filter out potentially dead comdat functions where other entries keep the
68 /// entire comdat group alive.
69 ///
70 /// This is designed for cases where functions appear to become dead but remain
71 /// alive due to other live entries in their comdat group.
72 ///
73 /// The \p DeadComdatFunctions container should only have pointers to
74 /// `Function`s which are members of a comdat group and are believed to be
75 /// dead.
76 ///
77 /// After this routine finishes, the only remaining `Function`s in \p
78 /// DeadComdatFunctions are those where every member of the comdat is listed
79 /// and thus removing them is safe (provided *all* are removed).
80 void filterDeadComdatFunctions(
81 Module &M, SmallVectorImpl &DeadComdatFunctions);
82
6783 } // End llvm namespace
6884
6985 #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H
2828 #include "llvm/Transforms/IPO.h"
2929 #include "llvm/Transforms/IPO/Inliner.h"
3030 #include "llvm/Transforms/Utils/Cloning.h"
31 #include "llvm/Transforms/Utils/ModuleUtils.h"
3132
3233 using namespace llvm;
3334
5960 InlinedFunctions.push_back(&F);
6061 }
6162
62 // Now try to delete all the functions we inlined.
63 for (Function *InlinedF : InlinedFunctions) {
64 InlinedF->removeDeadConstantUsers();
65 // FIXME: We should use some utility to handle cases where we can
66 // completely remove the comdat.
67 if (InlinedF->isDefTriviallyDead() && !InlinedF->hasComdat())
68 M.getFunctionList().erase(InlinedF);
63 // Remove any live functions.
64 erase_if(InlinedFunctions, [&](Function *F) {
65 F->removeDeadConstantUsers();
66 return !F->isDefTriviallyDead();
67 });
68
69 // Delete the non-comdat ones from the module and also from our vector.
70 auto NonComdatBegin = partition(
71 InlinedFunctions, [&](Function *F) { return F->hasComdat(); });
72 for (Function *F : make_range(NonComdatBegin, InlinedFunctions.end()))
73 M.getFunctionList().erase(F);
74 InlinedFunctions.erase(NonComdatBegin, InlinedFunctions.end());
75
76 if (!InlinedFunctions.empty()) {
77 // Now we just have the comdat functions. Filter out the ones whose comdats
78 // are not actually dead.
79 filterDeadComdatFunctions(M, InlinedFunctions);
80 // The remaining functions are actually dead.
81 for (Function *F : InlinedFunctions)
82 M.getFunctionList().erase(F);
6983 }
7084
7185 return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
3434 #include "llvm/Support/raw_ostream.h"
3535 #include "llvm/Transforms/Utils/Cloning.h"
3636 #include "llvm/Transforms/Utils/Local.h"
37 #include "llvm/Transforms/Utils/ModuleUtils.h"
3738 using namespace llvm;
3839
3940 #define DEBUG_TYPE "inline"
667668 bool LegacyInlinerBase::removeDeadFunctions(CallGraph &CG,
668669 bool AlwaysInlineOnly) {
669670 SmallVector FunctionsToRemove;
670 SmallVector DeadFunctionsInComdats;
671 SmallDenseMap ComdatEntriesAlive;
671 SmallVector DeadFunctionsInComdats;
672672
673673 auto RemoveCGN = [&](CallGraphNode *CGN) {
674674 // Remove any call graph edges from the function to its callees.
709709 // The inliner doesn't visit non-function entities which are in COMDAT
710710 // groups so it is unsafe to do so *unless* the linkage is local.
711711 if (!F->hasLocalLinkage()) {
712 if (const Comdat *C = F->getComdat()) {
713 --ComdatEntriesAlive[C];
714 DeadFunctionsInComdats.push_back(CGN);
712 if (F->hasComdat()) {
713 DeadFunctionsInComdats.push_back(F);
715714 continue;
716715 }
717716 }
719718 RemoveCGN(CGN);
720719 }
721720 if (!DeadFunctionsInComdats.empty()) {
722 // Count up all the entities in COMDAT groups
723 auto ComdatGroupReferenced = [&](const Comdat *C) {
724 auto I = ComdatEntriesAlive.find(C);
725 if (I != ComdatEntriesAlive.end())
726 ++(I->getSecond());
727 };
728 for (const Function &F : CG.getModule())
729 if (const Comdat *C = F.getComdat())
730 ComdatGroupReferenced(C);
731 for (const GlobalVariable &GV : CG.getModule().globals())
732 if (const Comdat *C = GV.getComdat())
733 ComdatGroupReferenced(C);
734 for (const GlobalAlias &GA : CG.getModule().aliases())
735 if (const Comdat *C = GA.getComdat())
736 ComdatGroupReferenced(C);
737 for (CallGraphNode *CGN : DeadFunctionsInComdats) {
738 Function *F = CGN->getFunction();
739 const Comdat *C = F->getComdat();
740 int NumAlive = ComdatEntriesAlive[C];
741 // We can remove functions in a COMDAT group if the entire group is dead.
742 assert(NumAlive >= 0);
743 if (NumAlive > 0)
744 continue;
745
746 RemoveCGN(CGN);
747 }
721 // Filter out the functions whose comdats remain alive.
722 filterDeadComdatFunctions(CG.getModule(), DeadFunctionsInComdats);
723 // Remove the rest.
724 for (Function *F : DeadFunctionsInComdats)
725 RemoveCGN(CG[F]);
748726 }
749727
750728 if (FunctionsToRemove.empty())
163163 }
164164 return std::make_pair(Ctor, InitFunction);
165165 }
166
167 void llvm::filterDeadComdatFunctions(
168 Module &M, SmallVectorImpl &DeadComdatFunctions) {
169 // Build a map from the comdat to the number of entries in that comdat we
170 // think are dead. If this fully covers the comdat group, then the entire
171 // group is dead. If we find another entry in the comdat group though, we'll
172 // have to preserve the whole group.
173 SmallDenseMap ComdatEntriesCovered;
174 for (Function *F : DeadComdatFunctions) {
175 Comdat *C = F->getComdat();
176 assert(C && "Expected all input GVs to be in a comdat!");
177 ComdatEntriesCovered[C] += 1;
178 }
179
180 auto CheckComdat = [&](Comdat &C) {
181 auto CI = ComdatEntriesCovered.find(&C);
182 if (CI == ComdatEntriesCovered.end())
183 return;
184
185 // If this could have been covered by a dead entry, just subtract one to
186 // account for it.
187 if (CI->second > 0) {
188 CI->second -= 1;
189 return;
190 }
191
192 // If we've already accounted for all the entries that were dead, the
193 // entire comdat is alive so remove it from the map.
194 ComdatEntriesCovered.erase(CI);
195 };
196
197 auto CheckAllComdats = [&] {
198 for (Function &F : M.functions())
199 if (Comdat *C = F.getComdat()) {
200 CheckComdat(*C);
201 if (ComdatEntriesCovered.empty())
202 return;
203 }
204 for (GlobalVariable &GV : M.globals())
205 if (Comdat *C = GV.getComdat()) {
206 CheckComdat(*C);
207 if (ComdatEntriesCovered.empty())
208 return;
209 }
210 for (GlobalAlias &GA : M.aliases())
211 if (Comdat *C = GA.getComdat()) {
212 CheckComdat(*C);
213 if (ComdatEntriesCovered.empty())
214 return;
215 }
216 };
217 CheckAllComdats();
218
219 if (ComdatEntriesCovered.empty()) {
220 DeadComdatFunctions.clear();
221 return;
222 }
223
224 // Remove the entries that were not covering.
225 erase_if(DeadComdatFunctions, [&](GlobalValue *GV) {
226 return ComdatEntriesCovered.find(GV->getComdat()) ==
227 ComdatEntriesCovered.end();
228 });
229 }
277277 ret void
278278 ; CHECK: ret void
279279 }
280
281 ; The 'inner13*' and 'outer13' functions test that we do remove functions
282 ; which are part of a comdat group where all of the members are removed during
283 ; always inlining.
284 $comdat13 = comdat any
285
286 define linkonce void @inner13a() alwaysinline comdat($comdat13) {
287 ; CHECK-NOT: @inner13a(
288 ret void
289 }
290
291 define linkonce void @inner13b() alwaysinline comdat($comdat13) {
292 ; CHECK-NOT: @inner13b(
293 ret void
294 }
295
296 define void @outer13() {
297 ; CHECK-LABEL: @outer13(
298 entry:
299 call void @inner13a()
300 call void @inner13b()
301 ; CHECK-NOT: call void @inner13a
302 ; CHECK-NOT: call void @inner13b
303
304 ret void
305 ; CHECK: ret void
306 }