123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- //===- CallGraphUpdater.cpp - A (lazy) call graph update helper -----------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- /// \file
- ///
- /// This file provides interfaces used to manipulate a call graph, regardless
- /// if it is a "old style" CallGraph or an "new style" LazyCallGraph.
- ///
- //===----------------------------------------------------------------------===//
- #include "llvm/Transforms/Utils/CallGraphUpdater.h"
- #include "llvm/ADT/STLExtras.h"
- #include "llvm/Analysis/CallGraph.h"
- #include "llvm/Analysis/CallGraphSCCPass.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/Transforms/Utils/ModuleUtils.h"
- using namespace llvm;
- bool CallGraphUpdater::finalize() {
- if (!DeadFunctionsInComdats.empty()) {
- filterDeadComdatFunctions(DeadFunctionsInComdats);
- DeadFunctions.append(DeadFunctionsInComdats.begin(),
- DeadFunctionsInComdats.end());
- }
- if (CG) {
- // First remove all references, e.g., outgoing via called functions. This is
- // necessary as we can delete functions that have circular references.
- for (Function *DeadFn : DeadFunctions) {
- DeadFn->removeDeadConstantUsers();
- CallGraphNode *DeadCGN = (*CG)[DeadFn];
- DeadCGN->removeAllCalledFunctions();
- CG->getExternalCallingNode()->removeAnyCallEdgeTo(DeadCGN);
- DeadFn->replaceAllUsesWith(PoisonValue::get(DeadFn->getType()));
- }
- // Then remove the node and function from the module.
- for (Function *DeadFn : DeadFunctions) {
- CallGraphNode *DeadCGN = CG->getOrInsertFunction(DeadFn);
- assert(DeadCGN->getNumReferences() == 0 &&
- "References should have been handled by now");
- delete CG->removeFunctionFromModule(DeadCGN);
- }
- } else {
- // This is the code path for the new lazy call graph and for the case were
- // no call graph was provided.
- for (Function *DeadFn : DeadFunctions) {
- DeadFn->removeDeadConstantUsers();
- DeadFn->replaceAllUsesWith(PoisonValue::get(DeadFn->getType()));
- if (LCG && !ReplacedFunctions.count(DeadFn)) {
- // Taken mostly from the inliner:
- LazyCallGraph::Node &N = LCG->get(*DeadFn);
- auto *DeadSCC = LCG->lookupSCC(N);
- assert(DeadSCC && DeadSCC->size() == 1 &&
- &DeadSCC->begin()->getFunction() == DeadFn);
- auto &DeadRC = DeadSCC->getOuterRefSCC();
- FunctionAnalysisManager &FAM =
- AM->getResult<FunctionAnalysisManagerCGSCCProxy>(*DeadSCC, *LCG)
- .getManager();
- FAM.clear(*DeadFn, DeadFn->getName());
- AM->clear(*DeadSCC, DeadSCC->getName());
- LCG->removeDeadFunction(*DeadFn);
- // Mark the relevant parts of the call graph as invalid so we don't
- // visit them.
- UR->InvalidatedSCCs.insert(DeadSCC);
- UR->InvalidatedRefSCCs.insert(&DeadRC);
- }
- // The function is now really dead and de-attached from everything.
- DeadFn->eraseFromParent();
- }
- }
- bool Changed = !DeadFunctions.empty();
- DeadFunctionsInComdats.clear();
- DeadFunctions.clear();
- return Changed;
- }
- void CallGraphUpdater::reanalyzeFunction(Function &Fn) {
- if (CG) {
- CallGraphNode *OldCGN = CG->getOrInsertFunction(&Fn);
- OldCGN->removeAllCalledFunctions();
- CG->populateCallGraphNode(OldCGN);
- } else if (LCG) {
- LazyCallGraph::Node &N = LCG->get(Fn);
- LazyCallGraph::SCC *C = LCG->lookupSCC(N);
- updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM);
- }
- }
- void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn,
- Function &NewFn) {
- if (CG)
- CG->addToCallGraph(&NewFn);
- else if (LCG)
- LCG->addSplitFunction(OriginalFn, NewFn);
- }
- void CallGraphUpdater::removeFunction(Function &DeadFn) {
- DeadFn.deleteBody();
- DeadFn.setLinkage(GlobalValue::ExternalLinkage);
- if (DeadFn.hasComdat())
- DeadFunctionsInComdats.push_back(&DeadFn);
- else
- DeadFunctions.push_back(&DeadFn);
- // For the old call graph we remove the function from the SCC right away.
- if (CG && !ReplacedFunctions.count(&DeadFn)) {
- CallGraphNode *DeadCGN = (*CG)[&DeadFn];
- DeadCGN->removeAllCalledFunctions();
- CGSCC->DeleteNode(DeadCGN);
- }
- }
- void CallGraphUpdater::replaceFunctionWith(Function &OldFn, Function &NewFn) {
- OldFn.removeDeadConstantUsers();
- ReplacedFunctions.insert(&OldFn);
- if (CG) {
- // Update the call graph for the newly promoted function.
- CallGraphNode *OldCGN = (*CG)[&OldFn];
- CallGraphNode *NewCGN = CG->getOrInsertFunction(&NewFn);
- NewCGN->stealCalledFunctionsFrom(OldCGN);
- CG->ReplaceExternalCallEdge(OldCGN, NewCGN);
- // And update the SCC we're iterating as well.
- CGSCC->ReplaceNode(OldCGN, NewCGN);
- } else if (LCG) {
- // Directly substitute the functions in the call graph.
- LazyCallGraph::Node &OldLCGN = LCG->get(OldFn);
- SCC->getOuterRefSCC().replaceNodeFunction(OldLCGN, NewFn);
- }
- removeFunction(OldFn);
- }
- bool CallGraphUpdater::replaceCallSite(CallBase &OldCS, CallBase &NewCS) {
- // This is only necessary in the (old) CG.
- if (!CG)
- return true;
- Function *Caller = OldCS.getCaller();
- CallGraphNode *NewCalleeNode =
- CG->getOrInsertFunction(NewCS.getCalledFunction());
- CallGraphNode *CallerNode = (*CG)[Caller];
- if (llvm::none_of(*CallerNode, [&OldCS](const CallGraphNode::CallRecord &CR) {
- return CR.first && *CR.first == &OldCS;
- }))
- return false;
- CallerNode->replaceCallEdge(OldCS, NewCS, NewCalleeNode);
- return true;
- }
- void CallGraphUpdater::removeCallSite(CallBase &CS) {
- // This is only necessary in the (old) CG.
- if (!CG)
- return;
- Function *Caller = CS.getCaller();
- CallGraphNode *CallerNode = (*CG)[Caller];
- CallerNode->removeCallEdgeFor(CS);
- }
|