xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
15ffd83dbSDimitry Andric //===- CallGraphUpdater.cpp - A (lazy) call graph update helper -----------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric /// \file
95ffd83dbSDimitry Andric ///
105ffd83dbSDimitry Andric /// This file provides interfaces used to manipulate a call graph, regardless
115ffd83dbSDimitry Andric /// if it is a "old style" CallGraph or an "new style" LazyCallGraph.
125ffd83dbSDimitry Andric ///
135ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
145ffd83dbSDimitry Andric 
155ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/CallGraphUpdater.h"
165ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
175ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
185ffd83dbSDimitry Andric 
195ffd83dbSDimitry Andric using namespace llvm;
205ffd83dbSDimitry Andric 
215ffd83dbSDimitry Andric bool CallGraphUpdater::finalize() {
225ffd83dbSDimitry Andric   if (!DeadFunctionsInComdats.empty()) {
235ffd83dbSDimitry Andric     filterDeadComdatFunctions(*DeadFunctionsInComdats.front()->getParent(),
245ffd83dbSDimitry Andric                               DeadFunctionsInComdats);
255ffd83dbSDimitry Andric     DeadFunctions.append(DeadFunctionsInComdats.begin(),
265ffd83dbSDimitry Andric                          DeadFunctionsInComdats.end());
275ffd83dbSDimitry Andric   }
285ffd83dbSDimitry Andric 
295ffd83dbSDimitry Andric   if (CG) {
305ffd83dbSDimitry Andric     // First remove all references, e.g., outgoing via called functions. This is
315ffd83dbSDimitry Andric     // necessary as we can delete functions that have circular references.
325ffd83dbSDimitry Andric     for (Function *DeadFn : DeadFunctions) {
335ffd83dbSDimitry Andric       DeadFn->removeDeadConstantUsers();
345ffd83dbSDimitry Andric       CallGraphNode *DeadCGN = (*CG)[DeadFn];
355ffd83dbSDimitry Andric       DeadCGN->removeAllCalledFunctions();
365ffd83dbSDimitry Andric       CG->getExternalCallingNode()->removeAnyCallEdgeTo(DeadCGN);
375ffd83dbSDimitry Andric       DeadFn->replaceAllUsesWith(UndefValue::get(DeadFn->getType()));
385ffd83dbSDimitry Andric     }
395ffd83dbSDimitry Andric 
405ffd83dbSDimitry Andric     // Then remove the node and function from the module.
415ffd83dbSDimitry Andric     for (Function *DeadFn : DeadFunctions) {
425ffd83dbSDimitry Andric       CallGraphNode *DeadCGN = CG->getOrInsertFunction(DeadFn);
435ffd83dbSDimitry Andric       assert(DeadCGN->getNumReferences() == 0 &&
445ffd83dbSDimitry Andric              "References should have been handled by now");
455ffd83dbSDimitry Andric       delete CG->removeFunctionFromModule(DeadCGN);
465ffd83dbSDimitry Andric     }
475ffd83dbSDimitry Andric   } else {
485ffd83dbSDimitry Andric     // This is the code path for the new lazy call graph and for the case were
495ffd83dbSDimitry Andric     // no call graph was provided.
505ffd83dbSDimitry Andric     for (Function *DeadFn : DeadFunctions) {
515ffd83dbSDimitry Andric       DeadFn->removeDeadConstantUsers();
525ffd83dbSDimitry Andric       DeadFn->replaceAllUsesWith(UndefValue::get(DeadFn->getType()));
535ffd83dbSDimitry Andric 
545ffd83dbSDimitry Andric       if (LCG && !ReplacedFunctions.count(DeadFn)) {
555ffd83dbSDimitry Andric         // Taken mostly from the inliner:
565ffd83dbSDimitry Andric         LazyCallGraph::Node &N = LCG->get(*DeadFn);
575ffd83dbSDimitry Andric         auto *DeadSCC = LCG->lookupSCC(N);
585ffd83dbSDimitry Andric         assert(DeadSCC && DeadSCC->size() == 1 &&
595ffd83dbSDimitry Andric                &DeadSCC->begin()->getFunction() == DeadFn);
605ffd83dbSDimitry Andric         auto &DeadRC = DeadSCC->getOuterRefSCC();
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric         FunctionAnalysisManager &FAM =
635ffd83dbSDimitry Andric             AM->getResult<FunctionAnalysisManagerCGSCCProxy>(*DeadSCC, *LCG)
645ffd83dbSDimitry Andric                 .getManager();
655ffd83dbSDimitry Andric 
665ffd83dbSDimitry Andric         FAM.clear(*DeadFn, DeadFn->getName());
675ffd83dbSDimitry Andric         AM->clear(*DeadSCC, DeadSCC->getName());
685ffd83dbSDimitry Andric         LCG->removeDeadFunction(*DeadFn);
695ffd83dbSDimitry Andric 
705ffd83dbSDimitry Andric         // Mark the relevant parts of the call graph as invalid so we don't
715ffd83dbSDimitry Andric         // visit them.
725ffd83dbSDimitry Andric         UR->InvalidatedSCCs.insert(DeadSCC);
735ffd83dbSDimitry Andric         UR->InvalidatedRefSCCs.insert(&DeadRC);
745ffd83dbSDimitry Andric       }
755ffd83dbSDimitry Andric 
765ffd83dbSDimitry Andric       // The function is now really dead and de-attached from everything.
775ffd83dbSDimitry Andric       DeadFn->eraseFromParent();
785ffd83dbSDimitry Andric     }
795ffd83dbSDimitry Andric   }
805ffd83dbSDimitry Andric 
815ffd83dbSDimitry Andric   bool Changed = !DeadFunctions.empty();
825ffd83dbSDimitry Andric   DeadFunctionsInComdats.clear();
835ffd83dbSDimitry Andric   DeadFunctions.clear();
845ffd83dbSDimitry Andric   return Changed;
855ffd83dbSDimitry Andric }
865ffd83dbSDimitry Andric 
875ffd83dbSDimitry Andric void CallGraphUpdater::reanalyzeFunction(Function &Fn) {
885ffd83dbSDimitry Andric   if (CG) {
895ffd83dbSDimitry Andric     CallGraphNode *OldCGN = CG->getOrInsertFunction(&Fn);
905ffd83dbSDimitry Andric     OldCGN->removeAllCalledFunctions();
915ffd83dbSDimitry Andric     CG->populateCallGraphNode(OldCGN);
925ffd83dbSDimitry Andric   } else if (LCG) {
935ffd83dbSDimitry Andric     LazyCallGraph::Node &N = LCG->get(Fn);
945ffd83dbSDimitry Andric     LazyCallGraph::SCC *C = LCG->lookupSCC(N);
955ffd83dbSDimitry Andric     updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM);
965ffd83dbSDimitry Andric   }
975ffd83dbSDimitry Andric }
985ffd83dbSDimitry Andric 
99*e8d8bef9SDimitry Andric void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn,
100*e8d8bef9SDimitry Andric                                                 Function &NewFn) {
1015ffd83dbSDimitry Andric   if (CG)
1025ffd83dbSDimitry Andric     CG->addToCallGraph(&NewFn);
1035ffd83dbSDimitry Andric   else if (LCG)
104*e8d8bef9SDimitry Andric     LCG->addSplitFunction(OriginalFn, NewFn);
1055ffd83dbSDimitry Andric }
1065ffd83dbSDimitry Andric 
1075ffd83dbSDimitry Andric void CallGraphUpdater::removeFunction(Function &DeadFn) {
1085ffd83dbSDimitry Andric   DeadFn.deleteBody();
1095ffd83dbSDimitry Andric   DeadFn.setLinkage(GlobalValue::ExternalLinkage);
1105ffd83dbSDimitry Andric   if (DeadFn.hasComdat())
1115ffd83dbSDimitry Andric     DeadFunctionsInComdats.push_back(&DeadFn);
1125ffd83dbSDimitry Andric   else
1135ffd83dbSDimitry Andric     DeadFunctions.push_back(&DeadFn);
1145ffd83dbSDimitry Andric 
1155ffd83dbSDimitry Andric   // For the old call graph we remove the function from the SCC right away.
1165ffd83dbSDimitry Andric   if (CG && !ReplacedFunctions.count(&DeadFn)) {
1175ffd83dbSDimitry Andric     CallGraphNode *DeadCGN = (*CG)[&DeadFn];
1185ffd83dbSDimitry Andric     DeadCGN->removeAllCalledFunctions();
1195ffd83dbSDimitry Andric     CGSCC->DeleteNode(DeadCGN);
1205ffd83dbSDimitry Andric   }
1215ffd83dbSDimitry Andric }
1225ffd83dbSDimitry Andric 
1235ffd83dbSDimitry Andric void CallGraphUpdater::replaceFunctionWith(Function &OldFn, Function &NewFn) {
1245ffd83dbSDimitry Andric   OldFn.removeDeadConstantUsers();
1255ffd83dbSDimitry Andric   ReplacedFunctions.insert(&OldFn);
1265ffd83dbSDimitry Andric   if (CG) {
1275ffd83dbSDimitry Andric     // Update the call graph for the newly promoted function.
1285ffd83dbSDimitry Andric     CallGraphNode *OldCGN = (*CG)[&OldFn];
1295ffd83dbSDimitry Andric     CallGraphNode *NewCGN = CG->getOrInsertFunction(&NewFn);
1305ffd83dbSDimitry Andric     NewCGN->stealCalledFunctionsFrom(OldCGN);
1315ffd83dbSDimitry Andric     CG->ReplaceExternalCallEdge(OldCGN, NewCGN);
1325ffd83dbSDimitry Andric 
1335ffd83dbSDimitry Andric     // And update the SCC we're iterating as well.
1345ffd83dbSDimitry Andric     CGSCC->ReplaceNode(OldCGN, NewCGN);
1355ffd83dbSDimitry Andric   } else if (LCG) {
1365ffd83dbSDimitry Andric     // Directly substitute the functions in the call graph.
1375ffd83dbSDimitry Andric     LazyCallGraph::Node &OldLCGN = LCG->get(OldFn);
1385ffd83dbSDimitry Andric     SCC->getOuterRefSCC().replaceNodeFunction(OldLCGN, NewFn);
1395ffd83dbSDimitry Andric   }
1405ffd83dbSDimitry Andric   removeFunction(OldFn);
1415ffd83dbSDimitry Andric }
1425ffd83dbSDimitry Andric 
1435ffd83dbSDimitry Andric bool CallGraphUpdater::replaceCallSite(CallBase &OldCS, CallBase &NewCS) {
1445ffd83dbSDimitry Andric   // This is only necessary in the (old) CG.
1455ffd83dbSDimitry Andric   if (!CG)
1465ffd83dbSDimitry Andric     return true;
1475ffd83dbSDimitry Andric 
1485ffd83dbSDimitry Andric   Function *Caller = OldCS.getCaller();
1495ffd83dbSDimitry Andric   CallGraphNode *NewCalleeNode =
1505ffd83dbSDimitry Andric       CG->getOrInsertFunction(NewCS.getCalledFunction());
1515ffd83dbSDimitry Andric   CallGraphNode *CallerNode = (*CG)[Caller];
1525ffd83dbSDimitry Andric   if (llvm::none_of(*CallerNode, [&OldCS](const CallGraphNode::CallRecord &CR) {
1535ffd83dbSDimitry Andric         return CR.first && *CR.first == &OldCS;
1545ffd83dbSDimitry Andric       }))
1555ffd83dbSDimitry Andric     return false;
1565ffd83dbSDimitry Andric   CallerNode->replaceCallEdge(OldCS, NewCS, NewCalleeNode);
1575ffd83dbSDimitry Andric   return true;
1585ffd83dbSDimitry Andric }
1595ffd83dbSDimitry Andric 
1605ffd83dbSDimitry Andric void CallGraphUpdater::removeCallSite(CallBase &CS) {
1615ffd83dbSDimitry Andric   // This is only necessary in the (old) CG.
1625ffd83dbSDimitry Andric   if (!CG)
1635ffd83dbSDimitry Andric     return;
1645ffd83dbSDimitry Andric 
1655ffd83dbSDimitry Andric   Function *Caller = CS.getCaller();
1665ffd83dbSDimitry Andric   CallGraphNode *CallerNode = (*CG)[Caller];
1675ffd83dbSDimitry Andric   CallerNode->removeCallEdgeFor(CS);
1685ffd83dbSDimitry Andric }
169