33 #define DEBUG_TYPE "globaldce"
37 cl::desc(
"Enable virtual function elimination"));
39 STATISTIC(NumAliases ,
"Number of global aliases removed");
40 STATISTIC(NumFunctions,
"Number of functions removed");
41 STATISTIC(NumIFuncs,
"Number of indirect functions removed");
42 STATISTIC(NumVariables,
"Number of global variables removed");
43 STATISTIC(NumVFuncs,
"Number of virtual functions removed");
46 class GlobalDCELegacyPass :
public ModulePass {
56 bool runOnModule(
Module &M)
override {
68 auto PA = Impl.run(M, DummyMAM);
69 return !PA.areAllPreserved();
79 "Dead Global Elimination",
false,
false)
83 return new GlobalDCELegacyPass();
89 if (
F->isDeclaration())
92 for (
auto &
I : Entry) {
93 if (
I.isDebugOrPseudoInst())
95 if (
auto *RI = dyn_cast<ReturnInst>(&
I))
96 return !RI->getReturnValue();
104 void GlobalDCEPass::ComputeDependencies(
Value *V,
106 if (
auto *
I = dyn_cast<Instruction>(V)) {
107 Function *Parent =
I->getParent()->getParent();
109 }
else if (
auto *GV = dyn_cast<GlobalValue>(V)) {
111 }
else if (
auto *CE = dyn_cast<Constant>(V)) {
113 auto Where = ConstantDependenciesCache.find(CE);
114 if (Where != ConstantDependenciesCache.end()) {
115 auto const &K = Where->second;
116 Deps.
insert(K.begin(), K.end());
119 for (
User *CEUser :
CE->users())
120 ComputeDependencies(CEUser, LocalDeps);
126 void GlobalDCEPass::UpdateGVDependencies(
GlobalValue &GV) {
129 ComputeDependencies(
User, Deps);
136 if (VFESafeVTables.count(GVU) && isa<Function>(&GV)) {
141 GVDependencies[GVU].insert(&GV);
148 auto const Ret = AliveGlobals.insert(&GV);
153 Updates->push_back(&GV);
155 for (
auto &&CM :
make_range(ComdatMembers.equal_range(
C))) {
156 MarkLive(*CM.second, Updates);
162 void GlobalDCEPass::ScanVTables(
Module &M) {
166 auto *LTOPostLinkMD =
167 cast_or_null<ConstantAsMetadata>(
M.getModuleFlag(
"LTOPostLink"));
170 (cast<ConstantInt>(LTOPostLinkMD->getValue())->getZExtValue() != 0);
186 cast<ConstantAsMetadata>(
Type->getOperand(0))->getValue())
189 TypeIdMap[
TypeID].insert(std::make_pair(&GV, Offset));
195 if (
auto GO = dyn_cast<GlobalObject>(&GV)) {
201 VFESafeVTables.insert(&GV);
209 for (
auto &VTableInfo : TypeIdMap[TypeId]) {
211 uint64_t VTableOffset = VTableInfo.second;
215 *
Caller->getParent(), VTable);
218 VFESafeVTables.erase(VTable);
225 VFESafeVTables.erase(VTable);
230 <<
Callee->getName() <<
"\n");
231 GVDependencies[
Caller].insert(Callee);
235 void GlobalDCEPass::ScanTypeCheckedLoadIntrinsics(
Module &M) {
240 if (!TypeCheckedLoadFunc)
243 for (
auto U : TypeCheckedLoadFunc->
users()) {
244 auto CI = dyn_cast<CallInst>(U);
248 auto *
Offset = dyn_cast<ConstantInt>(CI->getArgOperand(1));
249 Value *TypeIdValue = CI->getArgOperand(2);
250 auto *TypeId = cast<MetadataAsValue>(TypeIdValue)->
getMetadata();
253 ScanVTableLoad(CI->getFunction(), TypeId,
Offset->getZExtValue());
257 for (
auto &VTableInfo : TypeIdMap[TypeId]) {
258 VFESafeVTables.erase(VTableInfo.first);
264 void GlobalDCEPass::AddVirtualFunctionDependencies(
Module &M) {
272 auto *Val = mdconst::dyn_extract_or_null<ConstantInt>(
273 M.getModuleFlag(
"Virtual Function Elim"));
274 if (!Val || Val->getZExtValue() == 0)
279 if (VFESafeVTables.empty())
282 ScanTypeCheckedLoadIntrinsics(M);
285 dbgs() <<
"VFE safe vtables:\n";
286 for (
auto *VTable : VFESafeVTables)
292 bool Changed =
false;
309 ComdatMembers.insert(std::make_pair(
C, &
F));
312 ComdatMembers.insert(std::make_pair(
C, &GV));
314 if (
Comdat *
C = GA.getComdat())
315 ComdatMembers.insert(std::make_pair(
C, &GA));
319 AddVirtualFunctionDependencies(
M);
323 GO.removeDeadConstantUsers();
327 if (!GO.isDeclaration())
328 if (!GO.isDiscardableIfUnused())
331 UpdateGVDependencies(GO);
336 GA.removeDeadConstantUsers();
338 if (!GA.isDiscardableIfUnused())
341 UpdateGVDependencies(GA);
346 GIF.removeDeadConstantUsers();
348 if (!GIF.isDiscardableIfUnused())
351 UpdateGVDependencies(GIF);
358 while (!NewLiveGVs.empty()) {
360 for (
auto *GVD : GVDependencies[LGV])
361 MarkLive(*GVD, &NewLiveGVs);
369 std::vector<GlobalVariable *> DeadGlobalVars;
371 if (!AliveGlobals.count(&GV)) {
372 DeadGlobalVars.push_back(&GV);
373 if (GV.hasInitializer()) {
375 GV.setInitializer(
nullptr);
377 Init->destroyConstant();
382 std::vector<Function *> DeadFunctions;
384 if (!AliveGlobals.count(&
F)) {
385 DeadFunctions.push_back(&
F);
386 if (!
F.isDeclaration())
391 std::vector<GlobalAlias*> DeadAliases;
393 if (!AliveGlobals.count(&GA)) {
394 DeadAliases.push_back(&GA);
395 GA.setAliasee(
nullptr);
399 std::vector<GlobalIFunc*> DeadIFuncs;
401 if (!AliveGlobals.count(&GIF)) {
402 DeadIFuncs.push_back(&GIF);
403 GIF.setResolver(
nullptr);
408 auto EraseUnusedGlobalValue = [&](
GlobalValue *GV) {
414 NumFunctions += DeadFunctions.size();
416 if (!
F->use_empty()) {
434 EraseUnusedGlobalValue(
F);
437 NumVariables += DeadGlobalVars.size();
439 EraseUnusedGlobalValue(GV);
441 NumAliases += DeadAliases.size();
443 EraseUnusedGlobalValue(GA);
445 NumIFuncs += DeadIFuncs.size();
447 EraseUnusedGlobalValue(GIF);
450 AliveGlobals.clear();
451 ConstantDependenciesCache.clear();
452 GVDependencies.clear();
453 ComdatMembers.clear();
455 VFESafeVTables.clear();