109467b48Spatrick //===-- GlobalDCE.cpp - DCE unreachable internal functions ----------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This transform is designed to eliminate unreachable internal globals from the
1009467b48Spatrick // program. It uses an aggressive algorithm, searching out globals that are
1109467b48Spatrick // known to be alive. After it finds all of the globals which are needed, it
1209467b48Spatrick // deletes whatever is left over. This allows it to delete recursive chunks of
1309467b48Spatrick // the program which are unreachable.
1409467b48Spatrick //
1509467b48Spatrick //===----------------------------------------------------------------------===//
1609467b48Spatrick
1709467b48Spatrick #include "llvm/Transforms/IPO/GlobalDCE.h"
1809467b48Spatrick #include "llvm/ADT/SmallPtrSet.h"
1909467b48Spatrick #include "llvm/ADT/Statistic.h"
2009467b48Spatrick #include "llvm/Analysis/TypeMetadataUtils.h"
2109467b48Spatrick #include "llvm/IR/Instructions.h"
2209467b48Spatrick #include "llvm/IR/IntrinsicInst.h"
2309467b48Spatrick #include "llvm/IR/Module.h"
2409467b48Spatrick #include "llvm/InitializePasses.h"
2509467b48Spatrick #include "llvm/Pass.h"
2609467b48Spatrick #include "llvm/Support/CommandLine.h"
2709467b48Spatrick #include "llvm/Transforms/IPO.h"
2809467b48Spatrick #include "llvm/Transforms/Utils/CtorUtils.h"
2909467b48Spatrick #include "llvm/Transforms/Utils/GlobalStatus.h"
3009467b48Spatrick
3109467b48Spatrick using namespace llvm;
3209467b48Spatrick
3309467b48Spatrick #define DEBUG_TYPE "globaldce"
3409467b48Spatrick
3509467b48Spatrick static cl::opt<bool>
36*d415bd75Srobert ClEnableVFE("enable-vfe", cl::Hidden, cl::init(true),
3709467b48Spatrick cl::desc("Enable virtual function elimination"));
3809467b48Spatrick
3909467b48Spatrick STATISTIC(NumAliases , "Number of global aliases removed");
4009467b48Spatrick STATISTIC(NumFunctions, "Number of functions removed");
4109467b48Spatrick STATISTIC(NumIFuncs, "Number of indirect functions removed");
4209467b48Spatrick STATISTIC(NumVariables, "Number of global variables removed");
4309467b48Spatrick STATISTIC(NumVFuncs, "Number of virtual functions removed");
4409467b48Spatrick
4509467b48Spatrick namespace {
4609467b48Spatrick class GlobalDCELegacyPass : public ModulePass {
4709467b48Spatrick public:
4809467b48Spatrick static char ID; // Pass identification, replacement for typeid
GlobalDCELegacyPass()4909467b48Spatrick GlobalDCELegacyPass() : ModulePass(ID) {
5009467b48Spatrick initializeGlobalDCELegacyPassPass(*PassRegistry::getPassRegistry());
5109467b48Spatrick }
5209467b48Spatrick
5309467b48Spatrick // run - Do the GlobalDCE pass on the specified module, optionally updating
5409467b48Spatrick // the specified callgraph to reflect the changes.
5509467b48Spatrick //
runOnModule(Module & M)5609467b48Spatrick bool runOnModule(Module &M) override {
5709467b48Spatrick if (skipModule(M))
5809467b48Spatrick return false;
5909467b48Spatrick
6009467b48Spatrick // We need a minimally functional dummy module analysis manager. It needs
6109467b48Spatrick // to at least know about the possibility of proxying a function analysis
6209467b48Spatrick // manager.
6309467b48Spatrick FunctionAnalysisManager DummyFAM;
6409467b48Spatrick ModuleAnalysisManager DummyMAM;
6509467b48Spatrick DummyMAM.registerPass(
6609467b48Spatrick [&] { return FunctionAnalysisManagerModuleProxy(DummyFAM); });
6709467b48Spatrick
6809467b48Spatrick auto PA = Impl.run(M, DummyMAM);
6909467b48Spatrick return !PA.areAllPreserved();
7009467b48Spatrick }
7109467b48Spatrick
7209467b48Spatrick private:
7309467b48Spatrick GlobalDCEPass Impl;
7409467b48Spatrick };
7509467b48Spatrick }
7609467b48Spatrick
7709467b48Spatrick char GlobalDCELegacyPass::ID = 0;
7809467b48Spatrick INITIALIZE_PASS(GlobalDCELegacyPass, "globaldce",
7909467b48Spatrick "Dead Global Elimination", false, false)
8009467b48Spatrick
8109467b48Spatrick // Public interface to the GlobalDCEPass.
createGlobalDCEPass()8209467b48Spatrick ModulePass *llvm::createGlobalDCEPass() {
8309467b48Spatrick return new GlobalDCELegacyPass();
8409467b48Spatrick }
8509467b48Spatrick
8609467b48Spatrick /// Returns true if F is effectively empty.
isEmptyFunction(Function * F)8709467b48Spatrick static bool isEmptyFunction(Function *F) {
88*d415bd75Srobert // Skip external functions.
89*d415bd75Srobert if (F->isDeclaration())
90*d415bd75Srobert return false;
9109467b48Spatrick BasicBlock &Entry = F->getEntryBlock();
9209467b48Spatrick for (auto &I : Entry) {
93*d415bd75Srobert if (I.isDebugOrPseudoInst())
9409467b48Spatrick continue;
9509467b48Spatrick if (auto *RI = dyn_cast<ReturnInst>(&I))
9609467b48Spatrick return !RI->getReturnValue();
9709467b48Spatrick break;
9809467b48Spatrick }
9909467b48Spatrick return false;
10009467b48Spatrick }
10109467b48Spatrick
10209467b48Spatrick /// Compute the set of GlobalValue that depends from V.
10309467b48Spatrick /// The recursion stops as soon as a GlobalValue is met.
ComputeDependencies(Value * V,SmallPtrSetImpl<GlobalValue * > & Deps)10409467b48Spatrick void GlobalDCEPass::ComputeDependencies(Value *V,
10509467b48Spatrick SmallPtrSetImpl<GlobalValue *> &Deps) {
10609467b48Spatrick if (auto *I = dyn_cast<Instruction>(V)) {
10709467b48Spatrick Function *Parent = I->getParent()->getParent();
10809467b48Spatrick Deps.insert(Parent);
10909467b48Spatrick } else if (auto *GV = dyn_cast<GlobalValue>(V)) {
11009467b48Spatrick Deps.insert(GV);
11109467b48Spatrick } else if (auto *CE = dyn_cast<Constant>(V)) {
11209467b48Spatrick // Avoid walking the whole tree of a big ConstantExprs multiple times.
11309467b48Spatrick auto Where = ConstantDependenciesCache.find(CE);
11409467b48Spatrick if (Where != ConstantDependenciesCache.end()) {
11509467b48Spatrick auto const &K = Where->second;
11609467b48Spatrick Deps.insert(K.begin(), K.end());
11709467b48Spatrick } else {
11809467b48Spatrick SmallPtrSetImpl<GlobalValue *> &LocalDeps = ConstantDependenciesCache[CE];
11909467b48Spatrick for (User *CEUser : CE->users())
12009467b48Spatrick ComputeDependencies(CEUser, LocalDeps);
12109467b48Spatrick Deps.insert(LocalDeps.begin(), LocalDeps.end());
12209467b48Spatrick }
12309467b48Spatrick }
12409467b48Spatrick }
12509467b48Spatrick
UpdateGVDependencies(GlobalValue & GV)12609467b48Spatrick void GlobalDCEPass::UpdateGVDependencies(GlobalValue &GV) {
12709467b48Spatrick SmallPtrSet<GlobalValue *, 8> Deps;
12809467b48Spatrick for (User *User : GV.users())
12909467b48Spatrick ComputeDependencies(User, Deps);
13009467b48Spatrick Deps.erase(&GV); // Remove self-reference.
13109467b48Spatrick for (GlobalValue *GVU : Deps) {
13209467b48Spatrick // If this is a dep from a vtable to a virtual function, and we have
13309467b48Spatrick // complete information about all virtual call sites which could call
13409467b48Spatrick // though this vtable, then skip it, because the call site information will
13509467b48Spatrick // be more precise.
13609467b48Spatrick if (VFESafeVTables.count(GVU) && isa<Function>(&GV)) {
13709467b48Spatrick LLVM_DEBUG(dbgs() << "Ignoring dep " << GVU->getName() << " -> "
13809467b48Spatrick << GV.getName() << "\n");
13909467b48Spatrick continue;
14009467b48Spatrick }
14109467b48Spatrick GVDependencies[GVU].insert(&GV);
14209467b48Spatrick }
14309467b48Spatrick }
14409467b48Spatrick
14509467b48Spatrick /// Mark Global value as Live
MarkLive(GlobalValue & GV,SmallVectorImpl<GlobalValue * > * Updates)14609467b48Spatrick void GlobalDCEPass::MarkLive(GlobalValue &GV,
14709467b48Spatrick SmallVectorImpl<GlobalValue *> *Updates) {
14809467b48Spatrick auto const Ret = AliveGlobals.insert(&GV);
14909467b48Spatrick if (!Ret.second)
15009467b48Spatrick return;
15109467b48Spatrick
15209467b48Spatrick if (Updates)
15309467b48Spatrick Updates->push_back(&GV);
15409467b48Spatrick if (Comdat *C = GV.getComdat()) {
15509467b48Spatrick for (auto &&CM : make_range(ComdatMembers.equal_range(C))) {
15609467b48Spatrick MarkLive(*CM.second, Updates); // Recursion depth is only two because only
15709467b48Spatrick // globals in the same comdat are visited.
15809467b48Spatrick }
15909467b48Spatrick }
16009467b48Spatrick }
16109467b48Spatrick
ScanVTables(Module & M)16209467b48Spatrick void GlobalDCEPass::ScanVTables(Module &M) {
16309467b48Spatrick SmallVector<MDNode *, 2> Types;
16409467b48Spatrick LLVM_DEBUG(dbgs() << "Building type info -> vtable map\n");
16509467b48Spatrick
16609467b48Spatrick auto *LTOPostLinkMD =
16709467b48Spatrick cast_or_null<ConstantAsMetadata>(M.getModuleFlag("LTOPostLink"));
16809467b48Spatrick bool LTOPostLink =
16909467b48Spatrick LTOPostLinkMD &&
17009467b48Spatrick (cast<ConstantInt>(LTOPostLinkMD->getValue())->getZExtValue() != 0);
17109467b48Spatrick
17209467b48Spatrick for (GlobalVariable &GV : M.globals()) {
17309467b48Spatrick Types.clear();
17409467b48Spatrick GV.getMetadata(LLVMContext::MD_type, Types);
17509467b48Spatrick if (GV.isDeclaration() || Types.empty())
17609467b48Spatrick continue;
17709467b48Spatrick
17809467b48Spatrick // Use the typeid metadata on the vtable to build a mapping from typeids to
17909467b48Spatrick // the list of (GV, offset) pairs which are the possible vtables for that
18009467b48Spatrick // typeid.
18109467b48Spatrick for (MDNode *Type : Types) {
18209467b48Spatrick Metadata *TypeID = Type->getOperand(1).get();
18309467b48Spatrick
18409467b48Spatrick uint64_t Offset =
18509467b48Spatrick cast<ConstantInt>(
18609467b48Spatrick cast<ConstantAsMetadata>(Type->getOperand(0))->getValue())
18709467b48Spatrick ->getZExtValue();
18809467b48Spatrick
18909467b48Spatrick TypeIdMap[TypeID].insert(std::make_pair(&GV, Offset));
19009467b48Spatrick }
19109467b48Spatrick
19209467b48Spatrick // If the type corresponding to the vtable is private to this translation
19309467b48Spatrick // unit, we know that we can see all virtual functions which might use it,
19409467b48Spatrick // so VFE is safe.
19509467b48Spatrick if (auto GO = dyn_cast<GlobalObject>(&GV)) {
19609467b48Spatrick GlobalObject::VCallVisibility TypeVis = GO->getVCallVisibility();
19709467b48Spatrick if (TypeVis == GlobalObject::VCallVisibilityTranslationUnit ||
19809467b48Spatrick (LTOPostLink &&
19909467b48Spatrick TypeVis == GlobalObject::VCallVisibilityLinkageUnit)) {
20009467b48Spatrick LLVM_DEBUG(dbgs() << GV.getName() << " is safe for VFE\n");
20109467b48Spatrick VFESafeVTables.insert(&GV);
20209467b48Spatrick }
20309467b48Spatrick }
20409467b48Spatrick }
20509467b48Spatrick }
20609467b48Spatrick
ScanVTableLoad(Function * Caller,Metadata * TypeId,uint64_t CallOffset)20709467b48Spatrick void GlobalDCEPass::ScanVTableLoad(Function *Caller, Metadata *TypeId,
20809467b48Spatrick uint64_t CallOffset) {
209*d415bd75Srobert for (const auto &VTableInfo : TypeIdMap[TypeId]) {
21009467b48Spatrick GlobalVariable *VTable = VTableInfo.first;
21109467b48Spatrick uint64_t VTableOffset = VTableInfo.second;
21209467b48Spatrick
21309467b48Spatrick Constant *Ptr =
21409467b48Spatrick getPointerAtOffset(VTable->getInitializer(), VTableOffset + CallOffset,
215*d415bd75Srobert *Caller->getParent(), VTable);
21609467b48Spatrick if (!Ptr) {
21709467b48Spatrick LLVM_DEBUG(dbgs() << "can't find pointer in vtable!\n");
21809467b48Spatrick VFESafeVTables.erase(VTable);
219*d415bd75Srobert continue;
22009467b48Spatrick }
22109467b48Spatrick
22209467b48Spatrick auto Callee = dyn_cast<Function>(Ptr->stripPointerCasts());
22309467b48Spatrick if (!Callee) {
22409467b48Spatrick LLVM_DEBUG(dbgs() << "vtable entry is not function pointer!\n");
22509467b48Spatrick VFESafeVTables.erase(VTable);
226*d415bd75Srobert continue;
22709467b48Spatrick }
22809467b48Spatrick
22909467b48Spatrick LLVM_DEBUG(dbgs() << "vfunc dep " << Caller->getName() << " -> "
23009467b48Spatrick << Callee->getName() << "\n");
23109467b48Spatrick GVDependencies[Caller].insert(Callee);
23209467b48Spatrick }
23309467b48Spatrick }
23409467b48Spatrick
ScanTypeCheckedLoadIntrinsics(Module & M)23509467b48Spatrick void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(Module &M) {
23609467b48Spatrick LLVM_DEBUG(dbgs() << "Scanning type.checked.load intrinsics\n");
23709467b48Spatrick Function *TypeCheckedLoadFunc =
23809467b48Spatrick M.getFunction(Intrinsic::getName(Intrinsic::type_checked_load));
23909467b48Spatrick
24009467b48Spatrick if (!TypeCheckedLoadFunc)
24109467b48Spatrick return;
24209467b48Spatrick
243*d415bd75Srobert for (auto *U : TypeCheckedLoadFunc->users()) {
24409467b48Spatrick auto CI = dyn_cast<CallInst>(U);
24509467b48Spatrick if (!CI)
24609467b48Spatrick continue;
24709467b48Spatrick
24809467b48Spatrick auto *Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
24909467b48Spatrick Value *TypeIdValue = CI->getArgOperand(2);
25009467b48Spatrick auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->getMetadata();
25109467b48Spatrick
25209467b48Spatrick if (Offset) {
25309467b48Spatrick ScanVTableLoad(CI->getFunction(), TypeId, Offset->getZExtValue());
25409467b48Spatrick } else {
25509467b48Spatrick // type.checked.load with a non-constant offset, so assume every entry in
25609467b48Spatrick // every matching vtable is used.
257*d415bd75Srobert for (const auto &VTableInfo : TypeIdMap[TypeId]) {
25809467b48Spatrick VFESafeVTables.erase(VTableInfo.first);
25909467b48Spatrick }
26009467b48Spatrick }
26109467b48Spatrick }
26209467b48Spatrick }
26309467b48Spatrick
AddVirtualFunctionDependencies(Module & M)26409467b48Spatrick void GlobalDCEPass::AddVirtualFunctionDependencies(Module &M) {
26509467b48Spatrick if (!ClEnableVFE)
26609467b48Spatrick return;
26709467b48Spatrick
268097a140dSpatrick // If the Virtual Function Elim module flag is present and set to zero, then
269097a140dSpatrick // the vcall_visibility metadata was inserted for another optimization (WPD)
270097a140dSpatrick // and we may not have type checked loads on all accesses to the vtable.
271097a140dSpatrick // Don't attempt VFE in that case.
272097a140dSpatrick auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
273097a140dSpatrick M.getModuleFlag("Virtual Function Elim"));
274097a140dSpatrick if (!Val || Val->getZExtValue() == 0)
275097a140dSpatrick return;
276097a140dSpatrick
27709467b48Spatrick ScanVTables(M);
27809467b48Spatrick
27909467b48Spatrick if (VFESafeVTables.empty())
28009467b48Spatrick return;
28109467b48Spatrick
28209467b48Spatrick ScanTypeCheckedLoadIntrinsics(M);
28309467b48Spatrick
28409467b48Spatrick LLVM_DEBUG(
28509467b48Spatrick dbgs() << "VFE safe vtables:\n";
28609467b48Spatrick for (auto *VTable : VFESafeVTables)
28709467b48Spatrick dbgs() << " " << VTable->getName() << "\n";
28809467b48Spatrick );
28909467b48Spatrick }
29009467b48Spatrick
run(Module & M,ModuleAnalysisManager & MAM)29109467b48Spatrick PreservedAnalyses GlobalDCEPass::run(Module &M, ModuleAnalysisManager &MAM) {
29209467b48Spatrick bool Changed = false;
29309467b48Spatrick
29409467b48Spatrick // The algorithm first computes the set L of global variables that are
29509467b48Spatrick // trivially live. Then it walks the initialization of these variables to
29609467b48Spatrick // compute the globals used to initialize them, which effectively builds a
29709467b48Spatrick // directed graph where nodes are global variables, and an edge from A to B
29809467b48Spatrick // means B is used to initialize A. Finally, it propagates the liveness
29909467b48Spatrick // information through the graph starting from the nodes in L. Nodes note
30009467b48Spatrick // marked as alive are discarded.
30109467b48Spatrick
30209467b48Spatrick // Remove empty functions from the global ctors list.
303*d415bd75Srobert Changed |= optimizeGlobalCtorsList(
304*d415bd75Srobert M, [](uint32_t, Function *F) { return isEmptyFunction(F); });
30509467b48Spatrick
30609467b48Spatrick // Collect the set of members for each comdat.
30709467b48Spatrick for (Function &F : M)
30809467b48Spatrick if (Comdat *C = F.getComdat())
30909467b48Spatrick ComdatMembers.insert(std::make_pair(C, &F));
31009467b48Spatrick for (GlobalVariable &GV : M.globals())
31109467b48Spatrick if (Comdat *C = GV.getComdat())
31209467b48Spatrick ComdatMembers.insert(std::make_pair(C, &GV));
31309467b48Spatrick for (GlobalAlias &GA : M.aliases())
31409467b48Spatrick if (Comdat *C = GA.getComdat())
31509467b48Spatrick ComdatMembers.insert(std::make_pair(C, &GA));
31609467b48Spatrick
31709467b48Spatrick // Add dependencies between virtual call sites and the virtual functions they
31809467b48Spatrick // might call, if we have that information.
31909467b48Spatrick AddVirtualFunctionDependencies(M);
32009467b48Spatrick
32109467b48Spatrick // Loop over the module, adding globals which are obviously necessary.
32209467b48Spatrick for (GlobalObject &GO : M.global_objects()) {
323*d415bd75Srobert GO.removeDeadConstantUsers();
32409467b48Spatrick // Functions with external linkage are needed if they have a body.
32509467b48Spatrick // Externally visible & appending globals are needed, if they have an
32609467b48Spatrick // initializer.
32709467b48Spatrick if (!GO.isDeclaration())
32809467b48Spatrick if (!GO.isDiscardableIfUnused())
32909467b48Spatrick MarkLive(GO);
33009467b48Spatrick
33109467b48Spatrick UpdateGVDependencies(GO);
33209467b48Spatrick }
33309467b48Spatrick
33409467b48Spatrick // Compute direct dependencies of aliases.
33509467b48Spatrick for (GlobalAlias &GA : M.aliases()) {
336*d415bd75Srobert GA.removeDeadConstantUsers();
33709467b48Spatrick // Externally visible aliases are needed.
33809467b48Spatrick if (!GA.isDiscardableIfUnused())
33909467b48Spatrick MarkLive(GA);
34009467b48Spatrick
34109467b48Spatrick UpdateGVDependencies(GA);
34209467b48Spatrick }
34309467b48Spatrick
34409467b48Spatrick // Compute direct dependencies of ifuncs.
34509467b48Spatrick for (GlobalIFunc &GIF : M.ifuncs()) {
346*d415bd75Srobert GIF.removeDeadConstantUsers();
34709467b48Spatrick // Externally visible ifuncs are needed.
34809467b48Spatrick if (!GIF.isDiscardableIfUnused())
34909467b48Spatrick MarkLive(GIF);
35009467b48Spatrick
35109467b48Spatrick UpdateGVDependencies(GIF);
35209467b48Spatrick }
35309467b48Spatrick
35409467b48Spatrick // Propagate liveness from collected Global Values through the computed
35509467b48Spatrick // dependencies.
35609467b48Spatrick SmallVector<GlobalValue *, 8> NewLiveGVs{AliveGlobals.begin(),
35709467b48Spatrick AliveGlobals.end()};
35809467b48Spatrick while (!NewLiveGVs.empty()) {
35909467b48Spatrick GlobalValue *LGV = NewLiveGVs.pop_back_val();
36009467b48Spatrick for (auto *GVD : GVDependencies[LGV])
36109467b48Spatrick MarkLive(*GVD, &NewLiveGVs);
36209467b48Spatrick }
36309467b48Spatrick
36409467b48Spatrick // Now that all globals which are needed are in the AliveGlobals set, we loop
36509467b48Spatrick // through the program, deleting those which are not alive.
36609467b48Spatrick //
36709467b48Spatrick
36809467b48Spatrick // The first pass is to drop initializers of global variables which are dead.
36909467b48Spatrick std::vector<GlobalVariable *> DeadGlobalVars; // Keep track of dead globals
37009467b48Spatrick for (GlobalVariable &GV : M.globals())
37109467b48Spatrick if (!AliveGlobals.count(&GV)) {
37209467b48Spatrick DeadGlobalVars.push_back(&GV); // Keep track of dead globals
37309467b48Spatrick if (GV.hasInitializer()) {
37409467b48Spatrick Constant *Init = GV.getInitializer();
37509467b48Spatrick GV.setInitializer(nullptr);
37609467b48Spatrick if (isSafeToDestroyConstant(Init))
37709467b48Spatrick Init->destroyConstant();
37809467b48Spatrick }
37909467b48Spatrick }
38009467b48Spatrick
38109467b48Spatrick // The second pass drops the bodies of functions which are dead...
38209467b48Spatrick std::vector<Function *> DeadFunctions;
38309467b48Spatrick for (Function &F : M)
38409467b48Spatrick if (!AliveGlobals.count(&F)) {
38509467b48Spatrick DeadFunctions.push_back(&F); // Keep track of dead globals
38609467b48Spatrick if (!F.isDeclaration())
38709467b48Spatrick F.deleteBody();
38809467b48Spatrick }
38909467b48Spatrick
39009467b48Spatrick // The third pass drops targets of aliases which are dead...
39109467b48Spatrick std::vector<GlobalAlias*> DeadAliases;
39209467b48Spatrick for (GlobalAlias &GA : M.aliases())
39309467b48Spatrick if (!AliveGlobals.count(&GA)) {
39409467b48Spatrick DeadAliases.push_back(&GA);
39509467b48Spatrick GA.setAliasee(nullptr);
39609467b48Spatrick }
39709467b48Spatrick
39809467b48Spatrick // The fourth pass drops targets of ifuncs which are dead...
39909467b48Spatrick std::vector<GlobalIFunc*> DeadIFuncs;
40009467b48Spatrick for (GlobalIFunc &GIF : M.ifuncs())
40109467b48Spatrick if (!AliveGlobals.count(&GIF)) {
40209467b48Spatrick DeadIFuncs.push_back(&GIF);
40309467b48Spatrick GIF.setResolver(nullptr);
40409467b48Spatrick }
40509467b48Spatrick
40609467b48Spatrick // Now that all interferences have been dropped, delete the actual objects
40709467b48Spatrick // themselves.
40809467b48Spatrick auto EraseUnusedGlobalValue = [&](GlobalValue *GV) {
409*d415bd75Srobert GV->removeDeadConstantUsers();
41009467b48Spatrick GV->eraseFromParent();
41109467b48Spatrick Changed = true;
41209467b48Spatrick };
41309467b48Spatrick
41409467b48Spatrick NumFunctions += DeadFunctions.size();
41509467b48Spatrick for (Function *F : DeadFunctions) {
41609467b48Spatrick if (!F->use_empty()) {
41709467b48Spatrick // Virtual functions might still be referenced by one or more vtables,
41809467b48Spatrick // but if we've proven them to be unused then it's safe to replace the
41909467b48Spatrick // virtual function pointers with null, allowing us to remove the
42009467b48Spatrick // function itself.
42109467b48Spatrick ++NumVFuncs;
422*d415bd75Srobert
423*d415bd75Srobert // Detect vfuncs that are referenced as "relative pointers" which are used
424*d415bd75Srobert // in Swift vtables, i.e. entries in the form of:
425*d415bd75Srobert //
426*d415bd75Srobert // i32 trunc (i64 sub (i64 ptrtoint @f, i64 ptrtoint ...)) to i32)
427*d415bd75Srobert //
428*d415bd75Srobert // In this case, replace the whole "sub" expression with constant 0 to
429*d415bd75Srobert // avoid leaving a weird sub(0, symbol) expression behind.
430*d415bd75Srobert replaceRelativePointerUsersWithZero(F);
431*d415bd75Srobert
43209467b48Spatrick F->replaceNonMetadataUsesWith(ConstantPointerNull::get(F->getType()));
43309467b48Spatrick }
43409467b48Spatrick EraseUnusedGlobalValue(F);
43509467b48Spatrick }
43609467b48Spatrick
43709467b48Spatrick NumVariables += DeadGlobalVars.size();
43809467b48Spatrick for (GlobalVariable *GV : DeadGlobalVars)
43909467b48Spatrick EraseUnusedGlobalValue(GV);
44009467b48Spatrick
44109467b48Spatrick NumAliases += DeadAliases.size();
44209467b48Spatrick for (GlobalAlias *GA : DeadAliases)
44309467b48Spatrick EraseUnusedGlobalValue(GA);
44409467b48Spatrick
44509467b48Spatrick NumIFuncs += DeadIFuncs.size();
44609467b48Spatrick for (GlobalIFunc *GIF : DeadIFuncs)
44709467b48Spatrick EraseUnusedGlobalValue(GIF);
44809467b48Spatrick
44909467b48Spatrick // Make sure that all memory is released
45009467b48Spatrick AliveGlobals.clear();
45109467b48Spatrick ConstantDependenciesCache.clear();
45209467b48Spatrick GVDependencies.clear();
45309467b48Spatrick ComdatMembers.clear();
45409467b48Spatrick TypeIdMap.clear();
45509467b48Spatrick VFESafeVTables.clear();
45609467b48Spatrick
45709467b48Spatrick if (Changed)
45809467b48Spatrick return PreservedAnalyses::none();
45909467b48Spatrick return PreservedAnalyses::all();
46009467b48Spatrick }
461