@@ -121,6 +121,10 @@ class SILGlobalOpt {
121121 bool run ();
122122
123123protected:
124+ // / Checks if a given global variable is assigned only once.
125+ bool isAssignedOnlyOnceInInitializer (SILGlobalVariable *SILG,
126+ SILFunction *globalAddrF);
127+
124128 // / Reset all the maps of global variables.
125129 void reset ();
126130
@@ -637,15 +641,26 @@ static SILFunction *genGetterFromInit(SILOptFunctionBuilder &FunctionBuilder,
637641 return GetterF;
638642}
639643
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 ) {
642646 if (SILG->isLet ())
643647 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 ());
649664}
650665
651666// / Replace load sequence which may contain
@@ -691,7 +706,7 @@ replaceLoadsByKnownValue(BuiltinInst *CallToOnce, SILFunction *AddrF,
691706 LLVM_DEBUG (llvm::dbgs () << " GlobalOpt: replacing loads with known value for "
692707 << SILG->getName () << ' \n ' );
693708
694- assert (isAssignedOnlyOnceInInitializer (SILG) &&
709+ assert (isAssignedOnlyOnceInInitializer (SILG, AddrF ) &&
695710 " The value of the initializer should be known at compile-time" );
696711 assert (SILG->getDecl () &&
697712 " Decl corresponding to the global variable should be known" );
@@ -804,7 +819,7 @@ void SILGlobalOpt::optimizeInitializer(SILFunction *AddrF,
804819 << SILG->getName () << ' \n ' );
805820
806821 // Remove "once" call from the addressor.
807- if (!isAssignedOnlyOnceInInitializer (SILG) || !SILG->getDecl ()) {
822+ if (!isAssignedOnlyOnceInInitializer (SILG, AddrF ) || !SILG->getDecl ()) {
808823 LLVM_DEBUG (llvm::dbgs () << " GlobalOpt: building static initializer for "
809824 << SILG->getName () << ' \n ' );
810825
0 commit comments