1 //===- CallGraphUpdater.cpp - A (lazy) call graph update helper -----------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file provides interfaces used to manipulate a call graph, regardless 11 /// if it is a "old style" CallGraph or an "new style" LazyCallGraph. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Transforms/Utils/CallGraphUpdater.h" 16 #include "llvm/IR/Constants.h" 17 #include "llvm/Transforms/Utils/ModuleUtils.h" 18 19 using namespace llvm; 20 21 bool CallGraphUpdater::finalize() { 22 if (!DeadFunctionsInComdats.empty()) { 23 filterDeadComdatFunctions(DeadFunctionsInComdats); 24 DeadFunctions.append(DeadFunctionsInComdats.begin(), 25 DeadFunctionsInComdats.end()); 26 } 27 28 // This is the code path for the new lazy call graph and for the case were 29 // no call graph was provided. 30 for (Function *DeadFn : DeadFunctions) { 31 DeadFn->removeDeadConstantUsers(); 32 DeadFn->replaceAllUsesWith(PoisonValue::get(DeadFn->getType())); 33 34 if (LCG && !ReplacedFunctions.count(DeadFn)) { 35 // Taken mostly from the inliner: 36 LazyCallGraph::Node &N = LCG->get(*DeadFn); 37 auto *DeadSCC = LCG->lookupSCC(N); 38 assert(DeadSCC && DeadSCC->size() == 1 && 39 &DeadSCC->begin()->getFunction() == DeadFn); 40 41 FAM->clear(*DeadFn, DeadFn->getName()); 42 AM->clear(*DeadSCC, DeadSCC->getName()); 43 LCG->markDeadFunction(*DeadFn); 44 45 // Mark the relevant parts of the call graph as invalid so we don't 46 // visit them. 47 UR->InvalidatedSCCs.insert(LCG->lookupSCC(N)); 48 UR->DeadFunctions.push_back(DeadFn); 49 } else { 50 // The CGSCC infrastructure batch deletes functions at the end of the 51 // call graph walk, so only erase the function if we're not using that 52 // infrastructure. 53 // The function is now really dead and de-attached from everything. 54 DeadFn->eraseFromParent(); 55 } 56 } 57 58 bool Changed = !DeadFunctions.empty(); 59 DeadFunctionsInComdats.clear(); 60 DeadFunctions.clear(); 61 return Changed; 62 } 63 64 void CallGraphUpdater::reanalyzeFunction(Function &Fn) { 65 if (LCG) { 66 LazyCallGraph::Node &N = LCG->get(Fn); 67 LazyCallGraph::SCC *C = LCG->lookupSCC(N); 68 updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM); 69 } 70 } 71 72 void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn, 73 Function &NewFn) { 74 if (LCG) 75 LCG->addSplitFunction(OriginalFn, NewFn); 76 } 77 78 void CallGraphUpdater::removeFunction(Function &DeadFn) { 79 DeadFn.deleteBody(); 80 DeadFn.setLinkage(GlobalValue::ExternalLinkage); 81 if (DeadFn.hasComdat()) 82 DeadFunctionsInComdats.push_back(&DeadFn); 83 else 84 DeadFunctions.push_back(&DeadFn); 85 86 if (FAM) 87 FAM->clear(DeadFn, DeadFn.getName()); 88 } 89 90 void CallGraphUpdater::replaceFunctionWith(Function &OldFn, Function &NewFn) { 91 OldFn.removeDeadConstantUsers(); 92 ReplacedFunctions.insert(&OldFn); 93 if (LCG) { 94 // Directly substitute the functions in the call graph. 95 LazyCallGraph::Node &OldLCGN = LCG->get(OldFn); 96 SCC->getOuterRefSCC().replaceNodeFunction(OldLCGN, NewFn); 97 } 98 removeFunction(OldFn); 99 } 100