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
finalize()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
reanalyzeFunction(Function & Fn)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
registerOutlinedFunction(Function & OriginalFn,Function & NewFn)72 void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn,
73 Function &NewFn) {
74 if (LCG)
75 LCG->addSplitFunction(OriginalFn, NewFn);
76 }
77
removeFunction(Function & DeadFn)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
replaceFunctionWith(Function & OldFn,Function & NewFn)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