xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
1781ad6265SDimitry Andric #include "llvm/Analysis/CallGraph.h"
1881ad6265SDimitry Andric #include "llvm/Analysis/CallGraphSCCPass.h"
1981ad6265SDimitry Andric #include "llvm/IR/Constants.h"
205ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
215ffd83dbSDimitry Andric 
225ffd83dbSDimitry Andric using namespace llvm;
235ffd83dbSDimitry Andric 
245ffd83dbSDimitry Andric bool CallGraphUpdater::finalize() {
255ffd83dbSDimitry Andric   if (!DeadFunctionsInComdats.empty()) {
2604eeddc0SDimitry Andric     filterDeadComdatFunctions(DeadFunctionsInComdats);
275ffd83dbSDimitry Andric     DeadFunctions.append(DeadFunctionsInComdats.begin(),
285ffd83dbSDimitry Andric                          DeadFunctionsInComdats.end());
295ffd83dbSDimitry Andric   }
305ffd83dbSDimitry Andric 
315ffd83dbSDimitry Andric   if (CG) {
325ffd83dbSDimitry Andric     // First remove all references, e.g., outgoing via called functions. This is
335ffd83dbSDimitry Andric     // necessary as we can delete functions that have circular references.
345ffd83dbSDimitry Andric     for (Function *DeadFn : DeadFunctions) {
355ffd83dbSDimitry Andric       DeadFn->removeDeadConstantUsers();
365ffd83dbSDimitry Andric       CallGraphNode *DeadCGN = (*CG)[DeadFn];
375ffd83dbSDimitry Andric       DeadCGN->removeAllCalledFunctions();
385ffd83dbSDimitry Andric       CG->getExternalCallingNode()->removeAnyCallEdgeTo(DeadCGN);
39*bdd1243dSDimitry Andric       DeadFn->replaceAllUsesWith(PoisonValue::get(DeadFn->getType()));
405ffd83dbSDimitry Andric     }
415ffd83dbSDimitry Andric 
425ffd83dbSDimitry Andric     // Then remove the node and function from the module.
435ffd83dbSDimitry Andric     for (Function *DeadFn : DeadFunctions) {
445ffd83dbSDimitry Andric       CallGraphNode *DeadCGN = CG->getOrInsertFunction(DeadFn);
455ffd83dbSDimitry Andric       assert(DeadCGN->getNumReferences() == 0 &&
465ffd83dbSDimitry Andric              "References should have been handled by now");
475ffd83dbSDimitry Andric       delete CG->removeFunctionFromModule(DeadCGN);
485ffd83dbSDimitry Andric     }
495ffd83dbSDimitry Andric   } else {
505ffd83dbSDimitry Andric     // This is the code path for the new lazy call graph and for the case were
515ffd83dbSDimitry Andric     // no call graph was provided.
525ffd83dbSDimitry Andric     for (Function *DeadFn : DeadFunctions) {
535ffd83dbSDimitry Andric       DeadFn->removeDeadConstantUsers();
54*bdd1243dSDimitry Andric       DeadFn->replaceAllUsesWith(PoisonValue::get(DeadFn->getType()));
555ffd83dbSDimitry Andric 
565ffd83dbSDimitry Andric       if (LCG && !ReplacedFunctions.count(DeadFn)) {
575ffd83dbSDimitry Andric         // Taken mostly from the inliner:
585ffd83dbSDimitry Andric         LazyCallGraph::Node &N = LCG->get(*DeadFn);
595ffd83dbSDimitry Andric         auto *DeadSCC = LCG->lookupSCC(N);
605ffd83dbSDimitry Andric         assert(DeadSCC && DeadSCC->size() == 1 &&
615ffd83dbSDimitry Andric                &DeadSCC->begin()->getFunction() == DeadFn);
625ffd83dbSDimitry Andric         auto &DeadRC = DeadSCC->getOuterRefSCC();
635ffd83dbSDimitry Andric 
645ffd83dbSDimitry Andric         FunctionAnalysisManager &FAM =
655ffd83dbSDimitry Andric             AM->getResult<FunctionAnalysisManagerCGSCCProxy>(*DeadSCC, *LCG)
665ffd83dbSDimitry Andric                 .getManager();
675ffd83dbSDimitry Andric 
685ffd83dbSDimitry Andric         FAM.clear(*DeadFn, DeadFn->getName());
695ffd83dbSDimitry Andric         AM->clear(*DeadSCC, DeadSCC->getName());
705ffd83dbSDimitry Andric         LCG->removeDeadFunction(*DeadFn);
715ffd83dbSDimitry Andric 
725ffd83dbSDimitry Andric         // Mark the relevant parts of the call graph as invalid so we don't
735ffd83dbSDimitry Andric         // visit them.
745ffd83dbSDimitry Andric         UR->InvalidatedSCCs.insert(DeadSCC);
755ffd83dbSDimitry Andric         UR->InvalidatedRefSCCs.insert(&DeadRC);
765ffd83dbSDimitry Andric       }
775ffd83dbSDimitry Andric 
785ffd83dbSDimitry Andric       // The function is now really dead and de-attached from everything.
795ffd83dbSDimitry Andric       DeadFn->eraseFromParent();
805ffd83dbSDimitry Andric     }
815ffd83dbSDimitry Andric   }
825ffd83dbSDimitry Andric 
835ffd83dbSDimitry Andric   bool Changed = !DeadFunctions.empty();
845ffd83dbSDimitry Andric   DeadFunctionsInComdats.clear();
855ffd83dbSDimitry Andric   DeadFunctions.clear();
865ffd83dbSDimitry Andric   return Changed;
875ffd83dbSDimitry Andric }
885ffd83dbSDimitry Andric 
895ffd83dbSDimitry Andric void CallGraphUpdater::reanalyzeFunction(Function &Fn) {
905ffd83dbSDimitry Andric   if (CG) {
915ffd83dbSDimitry Andric     CallGraphNode *OldCGN = CG->getOrInsertFunction(&Fn);
925ffd83dbSDimitry Andric     OldCGN->removeAllCalledFunctions();
935ffd83dbSDimitry Andric     CG->populateCallGraphNode(OldCGN);
945ffd83dbSDimitry Andric   } else if (LCG) {
955ffd83dbSDimitry Andric     LazyCallGraph::Node &N = LCG->get(Fn);
965ffd83dbSDimitry Andric     LazyCallGraph::SCC *C = LCG->lookupSCC(N);
975ffd83dbSDimitry Andric     updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM);
985ffd83dbSDimitry Andric   }
995ffd83dbSDimitry Andric }
1005ffd83dbSDimitry Andric 
101e8d8bef9SDimitry Andric void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn,
102e8d8bef9SDimitry Andric                                                 Function &NewFn) {
1035ffd83dbSDimitry Andric   if (CG)
1045ffd83dbSDimitry Andric     CG->addToCallGraph(&NewFn);
1055ffd83dbSDimitry Andric   else if (LCG)
106e8d8bef9SDimitry Andric     LCG->addSplitFunction(OriginalFn, NewFn);
1075ffd83dbSDimitry Andric }
1085ffd83dbSDimitry Andric 
1095ffd83dbSDimitry Andric void CallGraphUpdater::removeFunction(Function &DeadFn) {
1105ffd83dbSDimitry Andric   DeadFn.deleteBody();
1115ffd83dbSDimitry Andric   DeadFn.setLinkage(GlobalValue::ExternalLinkage);
1125ffd83dbSDimitry Andric   if (DeadFn.hasComdat())
1135ffd83dbSDimitry Andric     DeadFunctionsInComdats.push_back(&DeadFn);
1145ffd83dbSDimitry Andric   else
1155ffd83dbSDimitry Andric     DeadFunctions.push_back(&DeadFn);
1165ffd83dbSDimitry Andric 
1175ffd83dbSDimitry Andric   // For the old call graph we remove the function from the SCC right away.
1185ffd83dbSDimitry Andric   if (CG && !ReplacedFunctions.count(&DeadFn)) {
1195ffd83dbSDimitry Andric     CallGraphNode *DeadCGN = (*CG)[&DeadFn];
1205ffd83dbSDimitry Andric     DeadCGN->removeAllCalledFunctions();
1215ffd83dbSDimitry Andric     CGSCC->DeleteNode(DeadCGN);
1225ffd83dbSDimitry Andric   }
1235ffd83dbSDimitry Andric }
1245ffd83dbSDimitry Andric 
1255ffd83dbSDimitry Andric void CallGraphUpdater::replaceFunctionWith(Function &OldFn, Function &NewFn) {
1265ffd83dbSDimitry Andric   OldFn.removeDeadConstantUsers();
1275ffd83dbSDimitry Andric   ReplacedFunctions.insert(&OldFn);
1285ffd83dbSDimitry Andric   if (CG) {
1295ffd83dbSDimitry Andric     // Update the call graph for the newly promoted function.
1305ffd83dbSDimitry Andric     CallGraphNode *OldCGN = (*CG)[&OldFn];
1315ffd83dbSDimitry Andric     CallGraphNode *NewCGN = CG->getOrInsertFunction(&NewFn);
1325ffd83dbSDimitry Andric     NewCGN->stealCalledFunctionsFrom(OldCGN);
1335ffd83dbSDimitry Andric     CG->ReplaceExternalCallEdge(OldCGN, NewCGN);
1345ffd83dbSDimitry Andric 
1355ffd83dbSDimitry Andric     // And update the SCC we're iterating as well.
1365ffd83dbSDimitry Andric     CGSCC->ReplaceNode(OldCGN, NewCGN);
1375ffd83dbSDimitry Andric   } else if (LCG) {
1385ffd83dbSDimitry Andric     // Directly substitute the functions in the call graph.
1395ffd83dbSDimitry Andric     LazyCallGraph::Node &OldLCGN = LCG->get(OldFn);
1405ffd83dbSDimitry Andric     SCC->getOuterRefSCC().replaceNodeFunction(OldLCGN, NewFn);
1415ffd83dbSDimitry Andric   }
1425ffd83dbSDimitry Andric   removeFunction(OldFn);
1435ffd83dbSDimitry Andric }
1445ffd83dbSDimitry Andric 
1455ffd83dbSDimitry Andric bool CallGraphUpdater::replaceCallSite(CallBase &OldCS, CallBase &NewCS) {
1465ffd83dbSDimitry Andric   // This is only necessary in the (old) CG.
1475ffd83dbSDimitry Andric   if (!CG)
1485ffd83dbSDimitry Andric     return true;
1495ffd83dbSDimitry Andric 
1505ffd83dbSDimitry Andric   Function *Caller = OldCS.getCaller();
1515ffd83dbSDimitry Andric   CallGraphNode *NewCalleeNode =
1525ffd83dbSDimitry Andric       CG->getOrInsertFunction(NewCS.getCalledFunction());
1535ffd83dbSDimitry Andric   CallGraphNode *CallerNode = (*CG)[Caller];
1545ffd83dbSDimitry Andric   if (llvm::none_of(*CallerNode, [&OldCS](const CallGraphNode::CallRecord &CR) {
1555ffd83dbSDimitry Andric         return CR.first && *CR.first == &OldCS;
1565ffd83dbSDimitry Andric       }))
1575ffd83dbSDimitry Andric     return false;
1585ffd83dbSDimitry Andric   CallerNode->replaceCallEdge(OldCS, NewCS, NewCalleeNode);
1595ffd83dbSDimitry Andric   return true;
1605ffd83dbSDimitry Andric }
1615ffd83dbSDimitry Andric 
1625ffd83dbSDimitry Andric void CallGraphUpdater::removeCallSite(CallBase &CS) {
1635ffd83dbSDimitry Andric   // This is only necessary in the (old) CG.
1645ffd83dbSDimitry Andric   if (!CG)
1655ffd83dbSDimitry Andric     return;
1665ffd83dbSDimitry Andric 
1675ffd83dbSDimitry Andric   Function *Caller = CS.getCaller();
1685ffd83dbSDimitry Andric   CallGraphNode *CallerNode = (*CG)[Caller];
1695ffd83dbSDimitry Andric   CallerNode->removeCallEdgeFor(CS);
1705ffd83dbSDimitry Andric }
171