@@ -121,6 +121,10 @@ class SILGlobalOpt {
121
121
bool run ();
122
122
123
123
protected:
124
+ // / Checks if a given global variable is assigned only once.
125
+ bool isAssignedOnlyOnceInInitializer (SILGlobalVariable *SILG,
126
+ SILFunction *globalAddrF);
127
+
124
128
// / Reset all the maps of global variables.
125
129
void reset ();
126
130
@@ -637,15 +641,26 @@ static SILFunction *genGetterFromInit(SILOptFunctionBuilder &FunctionBuilder,
637
641
return GetterF;
638
642
}
639
643
640
- // / Checks if a given global variable is assigned only once.
641
- static bool isAssignedOnlyOnceInInitializer (SILGlobalVariable *SILG ) {
644
+ bool SILGlobalOpt::isAssignedOnlyOnceInInitializer (SILGlobalVariable *SILG,
645
+ SILFunction *globalAddrF ) {
642
646
if (SILG->isLet ())
643
647
return true ;
644
- // TODO: If we can prove that a given global variable
645
- // is assigned only once, during initialization, then
646
- // we can treat it as if it is a let.
647
- // If this global is internal or private, it should be
648
- return false ;
648
+
649
+ // If we should skip this, it is probably because there are multiple stores.
650
+ // Return false if there are multiple stores or no stores.
651
+ if (GlobalVarSkipProcessing.count (SILG) || !GlobalVarStore.count (SILG) ||
652
+ // Check if there is more than one use the global addr function. If there
653
+ // is only one use, it must be the use that we are trying to optimize, so
654
+ // that is OK. If there is more than one use, one of the other uses may
655
+ // have a store attached to it which means there may be more than one
656
+ // assignment, so return false.
657
+ (GlobalInitCallMap.count (globalAddrF) &&
658
+ GlobalInitCallMap[globalAddrF].size () != 1 ))
659
+ return false ;
660
+
661
+ // Otherwise, return true if this can't be used externally (false, otherwise).
662
+ return !isPossiblyUsedExternally (SILG->getLinkage (),
663
+ SILG->getModule ().isWholeModule ());
649
664
}
650
665
651
666
// / Replace load sequence which may contain
@@ -691,7 +706,7 @@ replaceLoadsByKnownValue(BuiltinInst *CallToOnce, SILFunction *AddrF,
691
706
LLVM_DEBUG (llvm::dbgs () << " GlobalOpt: replacing loads with known value for "
692
707
<< SILG->getName () << ' \n ' );
693
708
694
- assert (isAssignedOnlyOnceInInitializer (SILG) &&
709
+ assert (isAssignedOnlyOnceInInitializer (SILG, AddrF ) &&
695
710
" The value of the initializer should be known at compile-time" );
696
711
assert (SILG->getDecl () &&
697
712
" Decl corresponding to the global variable should be known" );
@@ -804,7 +819,7 @@ void SILGlobalOpt::optimizeInitializer(SILFunction *AddrF,
804
819
<< SILG->getName () << ' \n ' );
805
820
806
821
// Remove "once" call from the addressor.
807
- if (!isAssignedOnlyOnceInInitializer (SILG) || !SILG->getDecl ()) {
822
+ if (!isAssignedOnlyOnceInInitializer (SILG, AddrF ) || !SILG->getDecl ()) {
808
823
LLVM_DEBUG (llvm::dbgs () << " GlobalOpt: building static initializer for "
809
824
<< SILG->getName () << ' \n ' );
810
825
0 commit comments