15ffd83dbSDimitry Andric //===- CallGraphUpdater.cpp - A (lazy) call graph update helper -----------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric /// \file
95ffd83dbSDimitry Andric ///
105ffd83dbSDimitry Andric /// This file provides interfaces used to manipulate a call graph, regardless
115ffd83dbSDimitry Andric /// if it is a "old style" CallGraph or an "new style" LazyCallGraph.
125ffd83dbSDimitry Andric ///
135ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
145ffd83dbSDimitry Andric
155ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/CallGraphUpdater.h"
1681ad6265SDimitry Andric #include "llvm/IR/Constants.h"
175ffd83dbSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
185ffd83dbSDimitry Andric
195ffd83dbSDimitry Andric using namespace llvm;
205ffd83dbSDimitry Andric
finalize()215ffd83dbSDimitry Andric bool CallGraphUpdater::finalize() {
225ffd83dbSDimitry Andric if (!DeadFunctionsInComdats.empty()) {
2304eeddc0SDimitry Andric filterDeadComdatFunctions(DeadFunctionsInComdats);
245ffd83dbSDimitry Andric DeadFunctions.append(DeadFunctionsInComdats.begin(),
255ffd83dbSDimitry Andric DeadFunctionsInComdats.end());
265ffd83dbSDimitry Andric }
275ffd83dbSDimitry Andric
285ffd83dbSDimitry Andric // This is the code path for the new lazy call graph and for the case were
295ffd83dbSDimitry Andric // no call graph was provided.
305ffd83dbSDimitry Andric for (Function *DeadFn : DeadFunctions) {
315ffd83dbSDimitry Andric DeadFn->removeDeadConstantUsers();
32bdd1243dSDimitry Andric DeadFn->replaceAllUsesWith(PoisonValue::get(DeadFn->getType()));
335ffd83dbSDimitry Andric
345ffd83dbSDimitry Andric if (LCG && !ReplacedFunctions.count(DeadFn)) {
355ffd83dbSDimitry Andric // Taken mostly from the inliner:
365ffd83dbSDimitry Andric LazyCallGraph::Node &N = LCG->get(*DeadFn);
375ffd83dbSDimitry Andric auto *DeadSCC = LCG->lookupSCC(N);
385ffd83dbSDimitry Andric assert(DeadSCC && DeadSCC->size() == 1 &&
395ffd83dbSDimitry Andric &DeadSCC->begin()->getFunction() == DeadFn);
405ffd83dbSDimitry Andric
41*0fca6ea1SDimitry Andric FAM->clear(*DeadFn, DeadFn->getName());
425ffd83dbSDimitry Andric AM->clear(*DeadSCC, DeadSCC->getName());
43*0fca6ea1SDimitry Andric LCG->markDeadFunction(*DeadFn);
445ffd83dbSDimitry Andric
455ffd83dbSDimitry Andric // Mark the relevant parts of the call graph as invalid so we don't
465ffd83dbSDimitry Andric // visit them.
47*0fca6ea1SDimitry Andric UR->InvalidatedSCCs.insert(LCG->lookupSCC(N));
48*0fca6ea1SDimitry Andric UR->DeadFunctions.push_back(DeadFn);
49*0fca6ea1SDimitry Andric } else {
50*0fca6ea1SDimitry Andric // The CGSCC infrastructure batch deletes functions at the end of the
51*0fca6ea1SDimitry Andric // call graph walk, so only erase the function if we're not using that
52*0fca6ea1SDimitry Andric // infrastructure.
535ffd83dbSDimitry Andric // The function is now really dead and de-attached from everything.
545ffd83dbSDimitry Andric DeadFn->eraseFromParent();
555ffd83dbSDimitry Andric }
565ffd83dbSDimitry Andric }
575ffd83dbSDimitry Andric
585ffd83dbSDimitry Andric bool Changed = !DeadFunctions.empty();
595ffd83dbSDimitry Andric DeadFunctionsInComdats.clear();
605ffd83dbSDimitry Andric DeadFunctions.clear();
615ffd83dbSDimitry Andric return Changed;
625ffd83dbSDimitry Andric }
635ffd83dbSDimitry Andric
reanalyzeFunction(Function & Fn)645ffd83dbSDimitry Andric void CallGraphUpdater::reanalyzeFunction(Function &Fn) {
65*0fca6ea1SDimitry Andric if (LCG) {
665ffd83dbSDimitry Andric LazyCallGraph::Node &N = LCG->get(Fn);
675ffd83dbSDimitry Andric LazyCallGraph::SCC *C = LCG->lookupSCC(N);
685ffd83dbSDimitry Andric updateCGAndAnalysisManagerForCGSCCPass(*LCG, *C, N, *AM, *UR, *FAM);
695ffd83dbSDimitry Andric }
705ffd83dbSDimitry Andric }
715ffd83dbSDimitry Andric
registerOutlinedFunction(Function & OriginalFn,Function & NewFn)72e8d8bef9SDimitry Andric void CallGraphUpdater::registerOutlinedFunction(Function &OriginalFn,
73e8d8bef9SDimitry Andric Function &NewFn) {
74*0fca6ea1SDimitry Andric if (LCG)
75e8d8bef9SDimitry Andric LCG->addSplitFunction(OriginalFn, NewFn);
765ffd83dbSDimitry Andric }
775ffd83dbSDimitry Andric
removeFunction(Function & DeadFn)785ffd83dbSDimitry Andric void CallGraphUpdater::removeFunction(Function &DeadFn) {
795ffd83dbSDimitry Andric DeadFn.deleteBody();
805ffd83dbSDimitry Andric DeadFn.setLinkage(GlobalValue::ExternalLinkage);
815ffd83dbSDimitry Andric if (DeadFn.hasComdat())
825ffd83dbSDimitry Andric DeadFunctionsInComdats.push_back(&DeadFn);
835ffd83dbSDimitry Andric else
845ffd83dbSDimitry Andric DeadFunctions.push_back(&DeadFn);
855ffd83dbSDimitry Andric
8606c3fb27SDimitry Andric if (FAM)
8706c3fb27SDimitry Andric FAM->clear(DeadFn, DeadFn.getName());
885ffd83dbSDimitry Andric }
895ffd83dbSDimitry Andric
replaceFunctionWith(Function & OldFn,Function & NewFn)905ffd83dbSDimitry Andric void CallGraphUpdater::replaceFunctionWith(Function &OldFn, Function &NewFn) {
915ffd83dbSDimitry Andric OldFn.removeDeadConstantUsers();
925ffd83dbSDimitry Andric ReplacedFunctions.insert(&OldFn);
93*0fca6ea1SDimitry Andric if (LCG) {
945ffd83dbSDimitry Andric // Directly substitute the functions in the call graph.
955ffd83dbSDimitry Andric LazyCallGraph::Node &OldLCGN = LCG->get(OldFn);
965ffd83dbSDimitry Andric SCC->getOuterRefSCC().replaceNodeFunction(OldLCGN, NewFn);
975ffd83dbSDimitry Andric }
985ffd83dbSDimitry Andric removeFunction(OldFn);
995ffd83dbSDimitry Andric }
100