Skip to content

Commit 0e389ce

Browse files
committed
Cleanup
1 parent f52a6f3 commit 0e389ce

File tree

1 file changed

+74
-26
lines changed

1 file changed

+74
-26
lines changed

lib/SILOptimizer/IPO/GlobalOpt.cpp

Lines changed: 74 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class SILGlobalOpt {
6060
typedef SmallVector<ApplyInst *, 4> GlobalInitCalls;
6161
typedef SmallVector<LoadInst *, 4> GlobalLoads;
6262
typedef SmallVector<BeginAccessInst *, 4> GlobalAccess;
63+
typedef SmallVector<GlobalAddrInst *, 4> GlobalAddrs;
6364

6465
/// A map from each visited global initializer call to a list of call sites.
6566
llvm::MapVector<SILFunction *, GlobalInitCalls> GlobalInitCallMap;
@@ -74,6 +75,9 @@ class SILGlobalOpt {
7475
/// A map from each visited global to its set of begin_access instructions.
7576
llvm::MapVector<SILGlobalVariable *, GlobalAccess> GlobalAccessMap;
7677

78+
/// A map from each visited global to all of its global address instructions.
79+
llvm::MapVector<SILGlobalVariable *, GlobalAddrs> GlobalAddrMap;
80+
7781
/// A map from each visited global let variable to the store instructions
7882
/// which initialize it.
7983
llvm::MapVector<SILGlobalVariable *, StoreInst *> GlobalVarStore;
@@ -152,8 +156,16 @@ class SILGlobalOpt {
152156
/// can be statically initialized.
153157
void optimizeInitializer(SILFunction *AddrF, GlobalInitCalls &Calls);
154158

155-
/// Remove private global variables that are never used.
156-
void tryOptimizeUnusedGlobal(SILGlobalVariable *global, StoreInst *store);
159+
/// If possible, remove global address instructions associated with the given
160+
/// global.
161+
bool tryRemoveGlobalAddr(SILGlobalVariable *global);
162+
163+
/// If possible, remove global alloc instructions associated with the given
164+
/// global.
165+
bool tryRemoveGlobalAlloc(SILGlobalVariable *global, AllocGlobalInst *alloc);
166+
167+
/// If a global has no uses, remove it.
168+
bool tryRemoveUnusedGlobal(SILGlobalVariable *global);
157169

158170
/// Optimize access to the global variable, which is known to have a constant
159171
/// value. Replace all loads from the global address by invocations of a
@@ -786,33 +798,41 @@ void SILGlobalOpt::optimizeInitializer(SILFunction *AddrF,
786798
HasChanged = true;
787799
}
788800

789-
/// Look through all the uses of the global variable. If the only use is a
790-
/// store, and the global is private, then we can remove the global, the store,
791-
/// and the alloc. Otherwise, return.
792-
void SILGlobalOpt::tryOptimizeUnusedGlobal(SILGlobalVariable *global,
793-
StoreInst *store) {
794-
if (global->getLinkage() != SILLinkage::Private)
795-
return;
801+
/// If there are no loads or accesses of a given global, then remove its
802+
/// associated global addr and all asssociated instructions.
803+
bool SILGlobalOpt::tryRemoveGlobalAddr(SILGlobalVariable *global) {
804+
if (isPossiblyUsedExternally(global->getLinkage(), Module->isWholeModule()))
805+
return false;
796806
if (GlobalLoadMap.count(global) || GlobalAccessMap.count(global))
797-
return;
807+
return false;
798808

799-
auto globalAddr = cast<GlobalAddrInst>(store->getDest());
800-
bool canRemove = true;
801-
for (auto *use : globalAddr->getUses()) {
802-
if (!isa<StoreInst>(use->getUser())) {
803-
canRemove = false;
804-
break;
805-
}
809+
for (auto *addr : GlobalAddrMap[global]) {
810+
eraseUsesOfInstruction(addr, [](SILInstruction *) {});
811+
addr->eraseFromParent();
806812
}
807813

808-
if (canRemove) {
809-
store->eraseFromParent();
810-
assert(globalAddr->getUses().begin() == globalAddr->getUses().end());
811-
globalAddr->eraseFromParent();
812-
if (AllocGlobalStore.count(global))
813-
AllocGlobalStore[global]->eraseFromParent();
814-
global->getModule().eraseGlobalVariable(global);
815-
}
814+
GlobalAddrMap.erase(global);
815+
return true;
816+
}
817+
818+
bool SILGlobalOpt::tryRemoveGlobalAlloc(SILGlobalVariable *global,
819+
AllocGlobalInst *alloc) {
820+
if (GlobalAddrMap.count(global))
821+
return false;
822+
823+
alloc->eraseFromParent();
824+
AllocGlobalStore.erase(global);
825+
return true;
826+
}
827+
828+
bool SILGlobalOpt::tryRemoveUnusedGlobal(SILGlobalVariable *global) {
829+
if (GlobalAddrMap.count(global) || GlobalAccessMap.count(global) ||
830+
GlobalLoadMap.count(global) || AllocGlobalStore.count(global) ||
831+
GlobalVarStore.count(global))
832+
return false;
833+
834+
global->getModule().eraseGlobalVariable(global);
835+
return true;
816836
}
817837

818838
static bool canBeChangedExternally(SILGlobalVariable *SILG) {
@@ -874,6 +894,8 @@ void SILGlobalOpt::collectGlobalAccess(GlobalAddrInst *GAI) {
874894
if (!SILG)
875895
return;
876896

897+
GlobalAddrMap[SILG].push_back(GAI);
898+
877899
if (!SILG->isLet()) {
878900
// We cannot determine the value for global variables which could be
879901
// changed externally at run-time.
@@ -1041,7 +1063,33 @@ bool SILGlobalOpt::run() {
10411063

10421064
// Optimize the access to globals if possible.
10431065
optimizeGlobalAccess(Init.first, Init.second);
1044-
tryOptimizeUnusedGlobal(Init.first, Init.second);
1066+
}
1067+
1068+
for (auto &addrPair : GlobalAddrMap) {
1069+
// Don't optimize functions that are marked with the opt.never attribute.
1070+
bool shouldOptimize = true;
1071+
for (auto *addr : addrPair.second) {
1072+
if (!addr->getFunction()->shouldOptimize()) {
1073+
shouldOptimize = false;
1074+
break;
1075+
}
1076+
}
1077+
if (!shouldOptimize)
1078+
continue;
1079+
1080+
HasChanged |= tryRemoveGlobalAddr(addrPair.first);
1081+
}
1082+
1083+
for (auto &alloc : AllocGlobalStore) {
1084+
if (!alloc.second->getFunction()->shouldOptimize())
1085+
continue;
1086+
HasChanged |= tryRemoveGlobalAlloc(alloc.first, alloc.second);
1087+
}
1088+
1089+
for (auto &global : Module->getSILGlobals()) {
1090+
// TODO: For some reaons, if we keep iterating through `getSILGlobals`
1091+
// after `tryRemoveUnusedGlobal` is called, we gen an error.
1092+
HasChanged |= tryRemoveUnusedGlobal(&global);
10451093
}
10461094

10471095
return HasChanged;

0 commit comments

Comments
 (0)