[llvm] [CGSCC] Fix compile time blowup with large RefSCCs (PR #94815)
Alina Sbirlea via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 10 14:36:39 PDT 2024
================
@@ -1515,57 +1511,68 @@ void LazyCallGraph::removeDeadFunction(Function &F) {
Node &N = *NI->second;
- // Cannot remove a function which has yet to be visited in the DFS walk, so
- // if we have a node at all then we must have an SCC and RefSCC.
- auto CI = SCCMap.find(&N);
- assert(CI != SCCMap.end() &&
- "Tried to remove a node without an SCC after DFS walk started!");
- SCC &C = *CI->second;
- RefSCC *RC = &C.getOuterRefSCC();
-
- // In extremely rare cases, we can delete a dead function which is still in a
- // non-trivial RefSCC. This can happen due to spurious ref edges sticking
- // around after an IR function reference is removed.
- if (RC->size() != 1) {
- SmallVector<Node *, 0> NodesInRC;
- for (SCC &OtherC : *RC) {
- for (Node &OtherN : OtherC)
- NodesInRC.push_back(&OtherN);
+ // Remove all call edges out of dead function.
+ for (Edge E : *N) {
+ if (E.isCall())
+ N->setEdgeKind(E.getNode(), Edge::Ref);
+ }
+}
+
+void LazyCallGraph::removeDeadFunctions(ArrayRef<Function *> DeadFs) {
+ if (DeadFs.empty())
+ return;
+
+ // Group dead functions by the RefSCC they're in.
+ DenseMap<RefSCC *, SmallVector<Node *, 1>> RCs;
+ for (Function *DeadF : DeadFs) {
+ Node *N = lookup(*DeadF);
+#ifndef NDEBUG
+ for (Edge &E : **N) {
+ assert(!E.isCall() &&
+ "dead function shouldn't have any outgoing call edges");
}
- for (Node *OtherN : NodesInRC) {
- if ((*OtherN)->lookup(N)) {
- auto NewRefSCCs =
- RC->removeInternalRefEdge(*OtherN, ArrayRef<Node *>(&N));
- // If we've split into multiple RefSCCs, RC is now invalid and the
- // RefSCC containing C will be different.
- if (!NewRefSCCs.empty())
- RC = &C.getOuterRefSCC();
+#endif
+ RefSCC *RC = lookupRefSCC(*N);
+ RCs[RC].push_back(N);
+ }
+ // Remove outgoing edges from all dead functions. Dead functions should
+ // already have had their call edges removed in markDeadFunction(), so we only
+ // need to worry about spurious ref edges.
+ for (auto [RC, DeadNs] : RCs) {
+ SmallVector<std::pair<Node *, Node *>> InternalEdgesToRemove;
+ for (Node *DeadN : DeadNs) {
+ if (lookupRefSCC(*DeadN) != RC)
----------------
alinas wrote:
Should this assert lookupRefSCC(*DeadN) == RC?
I'm missing when this can happen.
https://github.com/llvm/llvm-project/pull/94815
More information about the llvm-commits
mailing list