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