xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Utils/CallGraphUpdater.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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