172277ecdSJohannes Doerfert //===- CallGraphUpdater.cpp - A (lazy) call graph update helper -----------===// 272277ecdSJohannes Doerfert // 372277ecdSJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 472277ecdSJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 572277ecdSJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 672277ecdSJohannes Doerfert // 772277ecdSJohannes Doerfert //===----------------------------------------------------------------------===// 872277ecdSJohannes Doerfert /// \file 972277ecdSJohannes Doerfert /// 1072277ecdSJohannes Doerfert /// This file provides interfaces used to manipulate a call graph, regardless 1172277ecdSJohannes Doerfert /// if it is a "old style" CallGraph or an "new style" LazyCallGraph. 1272277ecdSJohannes Doerfert /// 1372277ecdSJohannes Doerfert //===----------------------------------------------------------------------===// 1472277ecdSJohannes Doerfert 1572277ecdSJohannes Doerfert #include "llvm/Transforms/Utils/CallGraphUpdater.h" 16a5bbc6efSBill Wendling #include "llvm/IR/Constants.h" 1772277ecdSJohannes Doerfert #include "llvm/Transforms/Utils/ModuleUtils.h" 1872277ecdSJohannes Doerfert 1972277ecdSJohannes Doerfert using namespace llvm; 2072277ecdSJohannes Doerfert 2172277ecdSJohannes Doerfert bool CallGraphUpdater::finalize() { 2272277ecdSJohannes Doerfert if (!DeadFunctionsInComdats.empty()) { 23c8189da2SNikita Popov filterDeadComdatFunctions(DeadFunctionsInComdats); 2472277ecdSJohannes Doerfert DeadFunctions.append(DeadFunctionsInComdats.begin(), 2572277ecdSJohannes Doerfert DeadFunctionsInComdats.end()); 2672277ecdSJohannes Doerfert } 2772277ecdSJohannes Doerfert 287ec8d793SJohannes Doerfert // This is the code path for the new lazy call graph and for the case were 297ec8d793SJohannes Doerfert // no call graph was provided. 307ec8d793SJohannes Doerfert for (Function *DeadFn : DeadFunctions) { 317ec8d793SJohannes Doerfert DeadFn->removeDeadConstantUsers(); 32b51c6130SManuel Brito DeadFn->replaceAllUsesWith(PoisonValue::get(DeadFn->getType())); 3372277ecdSJohannes Doerfert 3472277ecdSJohannes Doerfert if (LCG && !ReplacedFunctions.count(DeadFn)) { 3572277ecdSJohannes Doerfert // Taken mostly from the inliner: 3672277ecdSJohannes Doerfert LazyCallGraph::Node &N = LCG->get(*DeadFn); 3772277ecdSJohannes Doerfert auto *DeadSCC = LCG->lookupSCC(N); 3872277ecdSJohannes Doerfert assert(DeadSCC && DeadSCC->size() == 1 && 3972277ecdSJohannes Doerfert &DeadSCC->begin()->getFunction() == DeadFn); 4072277ecdSJohannes Doerfert 418d800e6cSArthur Eubanks FAM->clear(*DeadFn, DeadFn->getName()); 4272277ecdSJohannes Doerfert AM->clear(*DeadSCC, DeadSCC->getName()); 4371497cc7SArthur Eubanks LCG->markDeadFunction(*DeadFn); 4472277ecdSJohannes Doerfert 457ec8d793SJohannes Doerfert // Mark the relevant parts of the call graph as invalid so we don't 467ec8d793SJohannes Doerfert // visit them. 478d800e6cSArthur Eubanks UR->InvalidatedSCCs.insert(LCG->lookupSCC(N)); 4871497cc7SArthur Eubanks UR->DeadFunctions.push_back(DeadFn); 4971497cc7SArthur Eubanks } else { 5071497cc7SArthur Eubanks // The CGSCC infrastructure batch deletes functions at the end of the 5171497cc7SArthur Eubanks // call graph walk, so only erase the function if we're not using that 5271497cc7SArthur Eubanks // infrastructure. 5372277ecdSJohannes Doerfert // The function is now really dead and de-attached from everything. 5472277ecdSJohannes Doerfert DeadFn->eraseFromParent(); 5572277ecdSJohannes Doerfert } 567ec8d793SJohannes Doerfert } 5772277ecdSJohannes Doerfert 5872277ecdSJohannes Doerfert bool Changed = !DeadFunctions.empty(); 5972277ecdSJohannes Doerfert DeadFunctionsInComdats.clear(); 6072277ecdSJohannes Doerfert DeadFunctions.clear(); 6172277ecdSJohannes Doerfert return Changed; 6272277ecdSJohannes Doerfert } 6372277ecdSJohannes Doerfert 6472277ecdSJohannes Doerfert void CallGraphUpdater::reanalyzeFunction(Function &Fn) { 65*58bc98cdSArthur Eubanks if (LCG) { 6672277ecdSJohannes Doerfert LazyCallGraph::Node &N = LCG->get(Fn); 6772277ecdSJohannes Doerfert LazyCallGraph::SCC *C = LCG->lookupSCC(N); 68bd541b21SAlina Sbirlea updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM); 6972277ecdSJohannes Doerfert } 7072277ecdSJohannes Doerfert } 7172277ecdSJohannes Doerfert 727fea561eSArthur Eubanks void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn, 737fea561eSArthur Eubanks Function &NewFn) { 74*58bc98cdSArthur Eubanks if (LCG) 757fea561eSArthur Eubanks LCG->addSplitFunction(OriginalFn, NewFn); 7672277ecdSJohannes Doerfert } 7772277ecdSJohannes Doerfert 7872277ecdSJohannes Doerfert void CallGraphUpdater::removeFunction(Function &DeadFn) { 7972277ecdSJohannes Doerfert DeadFn.deleteBody(); 8072277ecdSJohannes Doerfert DeadFn.setLinkage(GlobalValue::ExternalLinkage); 8172277ecdSJohannes Doerfert if (DeadFn.hasComdat()) 8272277ecdSJohannes Doerfert DeadFunctionsInComdats.push_back(&DeadFn); 8372277ecdSJohannes Doerfert else 8472277ecdSJohannes Doerfert DeadFunctions.push_back(&DeadFn); 8593702575SJohannes Doerfert 868542d8f3SJohannes Doerfert if (FAM) 878542d8f3SJohannes Doerfert FAM->clear(DeadFn, DeadFn.getName()); 8872277ecdSJohannes Doerfert } 8972277ecdSJohannes Doerfert 9072277ecdSJohannes Doerfert void CallGraphUpdater::replaceFunctionWith(Function &OldFn, Function &NewFn) { 91cb0ecc5cSJohannes Doerfert OldFn.removeDeadConstantUsers(); 9272277ecdSJohannes Doerfert ReplacedFunctions.insert(&OldFn); 93*58bc98cdSArthur Eubanks if (LCG) { 9472277ecdSJohannes Doerfert // Directly substitute the functions in the call graph. 9572277ecdSJohannes Doerfert LazyCallGraph::Node &OldLCGN = LCG->get(OldFn); 9672277ecdSJohannes Doerfert SCC->getOuterRefSCC().replaceNodeFunction(OldLCGN, NewFn); 9772277ecdSJohannes Doerfert } 9872277ecdSJohannes Doerfert removeFunction(OldFn); 9972277ecdSJohannes Doerfert } 100