
We don't have any legacy pass manager CGSCC passes that modify the call graph (we only use it in the codegen pipeline to run function passes in call graph order). This is the beginning of removing CallGraphUpdater and making all the relevant CGSCC passes directly use the new pass manager APIs.
100 lines
3.4 KiB
C++
100 lines
3.4 KiB
C++
//===- 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/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());
|
|
}
|
|
|
|
// 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);
|
|
|
|
FAM->clear(*DeadFn, DeadFn->getName());
|
|
AM->clear(*DeadSCC, DeadSCC->getName());
|
|
LCG->markDeadFunction(*DeadFn);
|
|
|
|
// Mark the relevant parts of the call graph as invalid so we don't
|
|
// visit them.
|
|
UR->InvalidatedSCCs.insert(LCG->lookupSCC(N));
|
|
UR->DeadFunctions.push_back(DeadFn);
|
|
} else {
|
|
// The CGSCC infrastructure batch deletes functions at the end of the
|
|
// call graph walk, so only erase the function if we're not using that
|
|
// infrastructure.
|
|
// 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 (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 (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);
|
|
|
|
if (FAM)
|
|
FAM->clear(DeadFn, DeadFn.getName());
|
|
}
|
|
|
|
void CallGraphUpdater::replaceFunctionWith(Function &OldFn, Function &NewFn) {
|
|
OldFn.removeDeadConstantUsers();
|
|
ReplacedFunctions.insert(&OldFn);
|
|
if (LCG) {
|
|
// Directly substitute the functions in the call graph.
|
|
LazyCallGraph::Node &OldLCGN = LCG->get(OldFn);
|
|
SCC->getOuterRefSCC().replaceNodeFunction(OldLCGN, NewFn);
|
|
}
|
|
removeFunction(OldFn);
|
|
}
|