xref: /llvm-project/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp (revision 58bc98cd3abd72226cdbaa05bd92af9598d491db)
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