@@ -59,6 +59,7 @@ class SILGlobalOpt {
59
59
60
60
typedef SmallVector<ApplyInst *, 4 > GlobalInitCalls;
61
61
typedef SmallVector<LoadInst *, 4 > GlobalLoads;
62
+ typedef SmallVector<BeginAccessInst *, 4 > GlobalAccess;
62
63
63
64
// / A map from each visited global initializer call to a list of call sites.
64
65
llvm::MapVector<SILFunction *, GlobalInitCalls> GlobalInitCallMap;
@@ -70,10 +71,15 @@ class SILGlobalOpt {
70
71
// / A map from each visited global let variable to its set of loads.
71
72
llvm::MapVector<SILGlobalVariable *, GlobalLoads> GlobalLoadMap;
72
73
74
+ // / A map from each visited global to its set of begin_access instructions.
75
+ llvm::MapVector<SILGlobalVariable *, GlobalAccess> GlobalAccessMap;
76
+
73
77
// / A map from each visited global let variable to the store instructions
74
78
// / which initialize it.
75
79
llvm::MapVector<SILGlobalVariable *, StoreInst *> GlobalVarStore;
76
-
80
+
81
+ // / A map for each visited global variable to the alloc instruction that
82
+ // / allocated space for it.
77
83
llvm::MapVector<SILGlobalVariable *, AllocGlobalInst *> AllocGlobalStore;
78
84
79
85
// / A set of visited global variables that for some reason we have decided is
@@ -119,7 +125,9 @@ class SILGlobalOpt {
119
125
120
126
// / This is the main entrypoint for collecting global accesses.
121
127
void collectGlobalAccess (GlobalAddrInst *GAI);
122
-
128
+
129
+ // / Simple function to collect globals and their corresponding alloc
130
+ // / instructions.
123
131
void collectAllocGlobal (SILGlobalVariable *global,
124
132
AllocGlobalInst *allocGlobal);
125
133
@@ -144,6 +152,9 @@ class SILGlobalOpt {
144
152
// / can be statically initialized.
145
153
void optimizeInitializer (SILFunction *AddrF, GlobalInitCalls &Calls);
146
154
155
+ // / Remove private global variables that are never used.
156
+ void tryOptimizeUnusedGlobal (SILGlobalVariable *global, StoreInst *store);
157
+
147
158
// / Optimize access to the global variable, which is known to have a constant
148
159
// / value. Replace all loads from the global address by invocations of a
149
160
// / getter that returns the value of this variable.
@@ -775,6 +786,35 @@ void SILGlobalOpt::optimizeInitializer(SILFunction *AddrF,
775
786
HasChanged = true ;
776
787
}
777
788
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 ;
796
+ if (GlobalLoadMap.count (global) || GlobalAccessMap.count (global))
797
+ return ;
798
+
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
+ }
806
+ }
807
+
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
+ }
816
+ }
817
+
778
818
static bool canBeChangedExternally (SILGlobalVariable *SILG) {
779
819
// Don't assume anything about globals which are imported from other modules.
780
820
if (isAvailableExternally (SILG->getLinkage ()))
@@ -873,6 +913,10 @@ void SILGlobalOpt::collectGlobalAccess(GlobalAddrInst *GAI) {
873
913
continue ;
874
914
}
875
915
916
+ if (auto *beginAccess = dyn_cast<BeginAccessInst>(Op->getUser ())) {
917
+ GlobalAccessMap[SILG].push_back (beginAccess);
918
+ }
919
+
876
920
LLVM_DEBUG (llvm::dbgs () << " GlobalOpt: has non-store, non-load use: "
877
921
<< SILG->getName () << ' \n ' ;
878
922
Op->getUser ()->dump ());
@@ -883,7 +927,8 @@ void SILGlobalOpt::collectGlobalAccess(GlobalAddrInst *GAI) {
883
927
}
884
928
}
885
929
886
- void SILGlobalOpt::collectAllocGlobal (SILGlobalVariable *global, AllocGlobalInst *allocGlobal) {
930
+ void SILGlobalOpt::collectAllocGlobal (SILGlobalVariable *global,
931
+ AllocGlobalInst *allocGlobal) {
887
932
AllocGlobalStore[global] = allocGlobal;
888
933
}
889
934
@@ -937,11 +982,6 @@ void SILGlobalOpt::optimizeGlobalAccess(SILGlobalVariable *SILG,
937
982
938
983
bool SILGlobalOpt::run () {
939
984
for (auto &F : *Module) {
940
-
941
- // Don't optimize functions that are marked with the opt.never attribute.
942
- if (!F.shouldOptimize ())
943
- continue ;
944
-
945
985
// TODO: Add support for ownership.
946
986
if (F.hasOwnership ()) {
947
987
continue ;
@@ -978,32 +1018,30 @@ bool SILGlobalOpt::run() {
978
1018
}
979
1019
980
1020
for (auto &InitCalls : GlobalInitCallMap) {
1021
+ // Don't optimize functions that are marked with the opt.never attribute.
1022
+ bool shouldOptimize = true ;
1023
+ for (auto *apply : InitCalls.second ) {
1024
+ if (!apply->getFunction ()->shouldOptimize ()) {
1025
+ shouldOptimize = false ;
1026
+ break ;
1027
+ }
1028
+ }
1029
+ if (!shouldOptimize)
1030
+ continue ;
1031
+
981
1032
// Optimize the addressors if possible.
982
1033
optimizeInitializer (InitCalls.first , InitCalls.second );
983
1034
placeInitializers (InitCalls.first , InitCalls.second );
984
1035
}
985
1036
986
1037
for (auto &Init : GlobalVarStore) {
1038
+ // Don't optimize functions that are marked with the opt.never attribute.
1039
+ if (!Init.second ->getFunction ()->shouldOptimize ())
1040
+ continue ;
1041
+
987
1042
// Optimize the access to globals if possible.
988
1043
optimizeGlobalAccess (Init.first , Init.second );
989
-
990
- if (Init.first ->getLinkage () != SILLinkage::Private) continue ;
991
- bool canRemove = true ;
992
- auto globalAddr = cast<GlobalAddrInst>(Init.second ->getDest ());
993
- for (auto *use : globalAddr->getUses ()) {
994
- if (!isa<StoreInst>(use->getUser ())) {
995
- canRemove = false ;
996
- break ;
997
- }
998
- }
999
- if (canRemove) {
1000
- Init.second ->eraseFromParent ();
1001
- assert (globalAddr->getUses ().begin () == globalAddr->getUses ().end ());
1002
- globalAddr->eraseFromParent ();
1003
- if (AllocGlobalStore.count (Init.first ))
1004
- AllocGlobalStore[Init.first ]->eraseFromParent ();
1005
- Init.first ->getModule ().eraseGlobalVariable (Init.first );
1006
- }
1044
+ tryOptimizeUnusedGlobal (Init.first , Init.second );
1007
1045
}
1008
1046
1009
1047
return HasChanged;
0 commit comments