100 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9///10/// This file provides interfaces used to manipulate a call graph, regardless11/// 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 19using namespace llvm;20 21bool 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 were29 // 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't46 // 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 the51 // call graph walk, so only erase the function if we're not using that52 // 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 64void 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 72void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn,73 Function &NewFn) {74 if (LCG)75 LCG->addSplitFunction(OriginalFn, NewFn);76}77 78void CallGraphUpdater::removeFunction(Function &DeadFn) {79 DeadFn.deleteBody();80 DeadFn.setLinkage(GlobalValue::ExternalLinkage);81 if (DeadFn.hasComdat())82 DeadFunctionsInComdats.push_back(&DeadFn);83 else84 DeadFunctions.push_back(&DeadFn);85 86 if (FAM)87 FAM->clear(DeadFn, DeadFn.getName());88}89 90void 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