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