1 //===- CallGraphUpdater.cpp - A (lazy) call graph update helper -----------===//
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
7 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
15 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
16 #include "llvm/IR/Constants.h"
17 #include "llvm/Transforms/Utils/ModuleUtils.h"
21 bool CallGraphUpdater::finalize() {
22 if (!DeadFunctionsInComdats
.empty()) {
23 filterDeadComdatFunctions(DeadFunctionsInComdats
);
24 DeadFunctions
.append(DeadFunctionsInComdats
.begin(),
25 DeadFunctionsInComdats
.end());
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()));
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
);
41 FAM
->clear(*DeadFn
, DeadFn
->getName());
42 AM
->clear(*DeadSCC
, DeadSCC
->getName());
43 LCG
->markDeadFunction(*DeadFn
);
45 // Mark the relevant parts of the call graph as invalid so we don't
47 UR
->InvalidatedSCCs
.insert(LCG
->lookupSCC(N
));
48 UR
->DeadFunctions
.push_back(DeadFn
);
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
53 // The function is now really dead and de-attached from everything.
54 DeadFn
->eraseFromParent();
58 bool Changed
= !DeadFunctions
.empty();
59 DeadFunctionsInComdats
.clear();
60 DeadFunctions
.clear();
64 void CallGraphUpdater::reanalyzeFunction(Function
&Fn
) {
66 LazyCallGraph::Node
&N
= LCG
->get(Fn
);
67 LazyCallGraph::SCC
*C
= LCG
->lookupSCC(N
);
68 updateCGAndAnalysisManagerForCGSCCPass(*LCG
, *C
, N
, *AM
, *UR
, *FAM
);
72 void CallGraphUpdater::registerOutlinedFunction(Function
&OriginalFn
,
75 LCG
->addSplitFunction(OriginalFn
, NewFn
);
78 void CallGraphUpdater::removeFunction(Function
&DeadFn
) {
80 DeadFn
.setLinkage(GlobalValue::ExternalLinkage
);
81 if (DeadFn
.hasComdat())
82 DeadFunctionsInComdats
.push_back(&DeadFn
);
84 DeadFunctions
.push_back(&DeadFn
);
87 FAM
->clear(DeadFn
, DeadFn
.getName());
90 void CallGraphUpdater::replaceFunctionWith(Function
&OldFn
, Function
&NewFn
) {
91 OldFn
.removeDeadConstantUsers();
92 ReplacedFunctions
.insert(&OldFn
);
94 // Directly substitute the functions in the call graph.
95 LazyCallGraph::Node
&OldLCGN
= LCG
->get(OldFn
);
96 SCC
->getOuterRefSCC().replaceNodeFunction(OldLCGN
, NewFn
);
98 removeFunction(OldFn
);